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;