diff --git a/Aaru6.Compression/AppleRle.cs b/Aaru6.Compression/AppleRle.cs index d43e251..c4cf908 100644 --- a/Aaru6.Compression/AppleRle.cs +++ b/Aaru6.Compression/AppleRle.cs @@ -31,8 +31,6 @@ // Copyright © 2018-2019 David Ryskalczyk // ****************************************************************************/ -using System.IO; - namespace Aaru6.Compression { /// Implements the Apple version of RLE @@ -40,89 +38,87 @@ namespace Aaru6.Compression { 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/AaruBenchmark/Benchs.cs b/AaruBenchmark/Benchs.cs index 8c90483..e477eba 100644 --- a/AaruBenchmark/Benchs.cs +++ b/AaruBenchmark/Benchs.cs @@ -12,7 +12,7 @@ namespace AaruBenchmark public void Aaru() => Compression.Aaru.AppleRle(); [Benchmark] - public void Aaru6() => Compression.Aaru6.AppleRle(); + public void Aaru6() => Aaru6Compressions.AppleRle(); } [SimpleJob(RuntimeMoniker.Net60)] @@ -22,7 +22,7 @@ namespace AaruBenchmark public void Aaru() => Compression.Aaru.TeleDiskLzh(); [Benchmark] - public void Aaru6() => Compression.Aaru6.TeleDiskLzh(); + public void Aaru6() => Aaru6Compressions.TeleDiskLzh(); } [SimpleJob(RuntimeMoniker.Net60)] diff --git a/AaruBenchmark/Compression/Aaru6.cs b/AaruBenchmark/Compression/Aaru6Compressions.cs similarity index 83% rename from AaruBenchmark/Compression/Aaru6.cs rename to AaruBenchmark/Compression/Aaru6Compressions.cs index a6b9750..d4c6f5e 100644 --- a/AaruBenchmark/Compression/Aaru6.cs +++ b/AaruBenchmark/Compression/Aaru6Compressions.cs @@ -4,11 +4,11 @@ using Aaru6.Compression; namespace AaruBenchmark.Compression { - public class Aaru6 + public class Aaru6Compressions { public static void AppleRle() { - const int bufferSize = 20960; + const int bufferSize = 32768; byte[] input = new byte[1102]; var fs = new FileStream(Path.Combine(Program.Folder, "apple_rle.bin"), FileMode.Open, FileAccess.Read); @@ -19,12 +19,12 @@ namespace AaruBenchmark.Compression byte[] output = new byte[bufferSize]; - var rle = new AppleRle(new MemoryStream(input)); + int realSize = Aaru6.Compression.AppleRle.DecodeBuffer(input, output); - for(int i = 0; i < bufferSize; i++) - output[i] = (byte)rle.ProduceByte(); + if(realSize != 20960) + throw new InvalidDataException("Incorrect decompressed size"); - string crc = Crc32Context.Data(output, out _); + string crc = Crc32Context.Data(output, (uint)realSize, out _); if(crc != "3525ef06") throw new InvalidDataException("Incorrect decompressed checksum"); diff --git a/Benchmarks.ods b/Benchmarks.ods index 6bd76e4..7fa0b63 100644 Binary files a/Benchmarks.ods and b/Benchmarks.ods differ