diff --git a/Aaru.Compression/AppleRle.cs b/Aaru.Compression/AppleRle.cs
index 3da06de8c..6ca21a4e7 100644
--- a/Aaru.Compression/AppleRle.cs
+++ b/Aaru.Compression/AppleRle.cs
@@ -31,98 +31,94 @@
// Copyright © 2018-2019 David Ryskalczyk
// ****************************************************************************/
-using System.IO;
-
namespace Aaru.Compression
{
/// Implements the Apple version of RLE
- public class AppleRle
+ public static class AppleRle
{
const uint DART_CHUNK = 20960;
- readonly Stream _inStream;
- int _count;
- bool _nextA; // true if A, false if B
- byte _repeatedByteA, _repeatedByteB;
- bool _repeatMode; // true if we're repeating, false if we're just copying
-
- /// Initializes a decompressor for the specified stream
- /// Stream containing the compressed data
- public AppleRle(Stream stream)
+ /// Decodes a buffer compressed with Apple RLE
+ /// Encoded buffer
+ /// Buffer where to write the decoded data
+ /// The number of decoded bytes
+ public static int DecodeBuffer(byte[] source, byte[] destination)
{
- _inStream = stream;
- Reset();
- }
+ int count = 0;
+ bool nextA = true; // true if A, false if B
+ byte repeatedByteA = 0, repeatedByteB = 0;
+ bool repeatMode = false; // true if we're repeating, false if we're just copying
+ int inPosition = 0, outPosition = 0;
- void Reset()
- {
- _repeatedByteA = _repeatedByteB = 0;
- _count = 0;
- _nextA = true;
- _repeatMode = false;
- }
-
- /// Decompresses a byte
- /// Decompressed byte
- public int ProduceByte()
- {
- if(_repeatMode && _count > 0)
+ while(inPosition <= source.Length &&
+ outPosition <= destination.Length)
{
- _count--;
-
- if(_nextA)
+ switch(repeatMode)
{
- _nextA = false;
+ case true when count > 0:
+ {
+ count--;
- return _repeatedByteA;
+ if(nextA)
+ {
+ nextA = false;
+
+ destination[outPosition++] = repeatedByteA;
+
+ continue;
+ }
+
+ nextA = true;
+
+ destination[outPosition++] = repeatedByteB;
+
+ continue;
+ }
+ case false when count > 0:
+ count--;
+
+ destination[outPosition++] = source[inPosition++];
+
+ continue;
}
- _nextA = true;
+ if(inPosition == source.Length)
+ break;
- return _repeatedByteB;
- }
-
- if(!_repeatMode &&
- _count > 0)
- {
- _count--;
-
- return _inStream.ReadByte();
- }
-
- if(_inStream.Position == _inStream.Length)
- return -1;
-
- while(true)
- {
- byte b1 = (byte)_inStream.ReadByte();
- byte b2 = (byte)_inStream.ReadByte();
- short s = (short)((b1 << 8) | b2);
-
- if(s == 0 ||
- s >= DART_CHUNK ||
- s <= -DART_CHUNK)
- continue;
-
- if(s < 0)
+ while(true)
{
- _repeatMode = true;
- _repeatedByteA = (byte)_inStream.ReadByte();
- _repeatedByteB = (byte)_inStream.ReadByte();
- _count = (-s * 2) - 1;
- _nextA = false;
+ byte b1 = source[inPosition++];
+ byte b2 = source[inPosition++];
+ short s = (short)((b1 << 8) | b2);
- return _repeatedByteA;
+ if(s == 0 ||
+ s >= DART_CHUNK ||
+ s <= -DART_CHUNK)
+ continue;
+
+ if(s < 0)
+ {
+ repeatMode = true;
+ repeatedByteA = source[inPosition++];
+ repeatedByteB = source[inPosition++];
+ count = (-s * 2) - 1;
+ nextA = false;
+
+ destination[outPosition++] = repeatedByteA;
+
+ break;
+ }
+
+ repeatMode = false;
+ count = (s * 2) - 1;
+
+ destination[outPosition++] = source[inPosition++];
+
+ break;
}
-
- if(s <= 0)
- continue;
-
- _repeatMode = false;
- _count = (s * 2) - 1;
-
- return _inStream.ReadByte();
}
+
+ return outPosition;
}
}
}
\ No newline at end of file
diff --git a/Aaru.Images/DART/Read.cs b/Aaru.Images/DART/Read.cs
index 60ffccd70..aa352cf6c 100644
--- a/Aaru.Images/DART/Read.cs
+++ b/Aaru.Images/DART/Read.cs
@@ -146,11 +146,9 @@ namespace Aaru.DiscImages
{
temp = new byte[l * 2];
stream.Read(temp, 0, temp.Length);
- var rle = new AppleRle(new MemoryStream(temp));
buffer = new byte[BUFFER_SIZE];
- for(int i = 0; i < BUFFER_SIZE; i++)
- buffer[i] = (byte)rle.ProduceByte();
+ AppleRle.DecodeBuffer(temp, buffer);
dataMs.Write(buffer, 0, DATA_SIZE);
tagMs.Write(buffer, DATA_SIZE, TAG_SIZE);
diff --git a/Aaru.Images/NDIF/Read.cs b/Aaru.Images/NDIF/Read.cs
index 7d06daa2d..3e8e9ece3 100644
--- a/Aaru.Images/NDIF/Read.cs
+++ b/Aaru.Images/NDIF/Read.cs
@@ -384,21 +384,8 @@ namespace Aaru.DiscImages
case CHUNK_TYPE_RLE:
{
byte[] tmpBuffer = new byte[_bufferSize];
- realSize = 0;
- var rle = new AppleRle(cmpMs);
-
- for(int i = 0; i < _bufferSize; i++)
- {
- int b = rle.ProduceByte();
-
- if(b == -1)
- break;
-
- tmpBuffer[i] = (byte)b;
- realSize++;
- }
-
- data = new byte[realSize];
+ realSize = AppleRle.DecodeBuffer(cmpBuffer, tmpBuffer);
+ data = new byte[realSize];
Array.Copy(tmpBuffer, 0, data, 0, realSize);
break;
diff --git a/Aaru.Images/UDIF/Read.cs b/Aaru.Images/UDIF/Read.cs
index 1cb3f78d9..672b0517b 100644
--- a/Aaru.Images/UDIF/Read.cs
+++ b/Aaru.Images/UDIF/Read.cs
@@ -546,21 +546,8 @@ namespace Aaru.DiscImages
break;
case CHUNK_TYPE_RLE:
tmpBuffer = new byte[_buffersize];
- realSize = 0;
- var rle = new AppleRle(cmpMs);
-
- for(int i = 0; i < _buffersize; i++)
- {
- int b = rle.ProduceByte();
-
- if(b == -1)
- break;
-
- tmpBuffer[i] = (byte)b;
- realSize++;
- }
-
- data = new byte[realSize];
+ realSize = AppleRle.DecodeBuffer(cmpBuffer, tmpBuffer);
+ data = new byte[realSize];
Array.Copy(tmpBuffer, 0, data, 0, realSize);
break;