/// <summary> /// /// </summary> public static void DecompressBuffer(this BinaryReader binaryReader, Stream outstream, uint zSize, uint size) { if (zSize == size) { try { var buffer = binaryReader.ReadBytes((int)zSize); outstream.Write(buffer); } catch (Exception e) { Console.WriteLine(e); throw; } } else { var pos = binaryReader.BaseStream.Position; var oodleCompression = binaryReader.ReadBytes(4); if ((oodleCompression.SequenceEqual(new byte[] { 0x4b, 0x41, 0x52, 0x4b }))) { var headerSize = binaryReader.ReadUInt32(); if (headerSize != size) { throw new Exception($"Buffer size doesn't match size in info table. {headerSize} vs {size}"); } var inputBuffer = binaryReader.ReadBytes((int)zSize - 8); try { var outputBuffer = new byte[size]; long unpackedSize = OodleHelper.Decompress(inputBuffer, outputBuffer); if (unpackedSize != size) { throw new DecompressionException( $"Unpacked size {unpackedSize} doesn't match real size {size}"); } outstream.Write(outputBuffer); } catch (DecompressionException) { //logger.LogString(e.Message, Logtype.Error); //logger.LogString( // $"Unable to decompress file {hash.ToString()}. Exporting uncompressed file", // Logtype.Error); outstream.Write(inputBuffer); } } else { binaryReader.BaseStream.Seek(pos, SeekOrigin.Begin); var buffer = binaryReader.ReadBytes((int)zSize); outstream.Write(buffer); } } }
/// <summary> /// Decompresses and copies a segment of zsize bytes from a stream to another stream /// </summary> /// <param name="stream"></param> /// <param name="outStream"></param> /// <param name="zSize"></param> /// <param name="size"></param> /// <exception cref="Exception"></exception> /// <exception cref="DecompressionException"></exception> public static void DecompressAndCopySegment(this Stream stream, Stream outStream, uint zSize, uint size) { if (zSize == size) { stream.CopyToWithLength(outStream, (int)zSize); } else { var oodleCompression = stream.ReadStruct <uint>(); if (oodleCompression == KARK) { var headerSize = stream.ReadStruct <uint>(); if (headerSize != size) { throw new Exception($"Buffer size doesn't match size in info table. {headerSize} vs {size}"); } var inputBuffer = new byte[(int)zSize - 8]; stream.Read(inputBuffer); var outputBuffer = new byte[size]; long unpackedSize = OodleHelper.Decompress(inputBuffer, outputBuffer); if (unpackedSize != size) { throw new DecompressionException( $"Unpacked size {unpackedSize} doesn't match real size {size}."); } outStream.Write(outputBuffer); // try // { // // } // catch (DecompressionException) // { // //logger.LogString(e.Message, Logtype.Error); // //logger.LogString( // // $"Unable to decompress file {hash.ToString()}. Exporting uncompressed file", // // Logtype.Error); // stream.CopyTo(outStream); // } } else { stream.Seek(0, SeekOrigin.Begin); stream.CopyToWithLength(outStream, (int)zSize); } } }
/// <summary> /// Decompresses and copies a segment of zsize bytes from a stream to another stream /// </summary> /// <param name="stream"></param> /// <param name="outStream"></param> /// <param name="zSize"></param> /// <param name="size"></param> /// <exception cref="Exception"></exception> /// <exception cref="DecompressionException"></exception> public static void DecompressAndCopySegment(this Stream stream, Stream outStream, uint zSize, uint size) { if (zSize == size) { stream.CopyToWithLength(outStream, (int)zSize); } else { var oodleCompression = stream.ReadStruct <uint>(); if (oodleCompression == KARK) { var headerSize = stream.ReadStruct <uint>(); if (headerSize != size) { throw new DecompressionException($"Buffer size doesn't match size in info table. {headerSize} vs {size}"); } const int SPAN_LEN = 5333;//32768; var length = (int)zSize - 8; var inputBufferSpan = length <= SPAN_LEN ? stackalloc byte[length] : new byte[length]; var outputBufferSpan = size <= SPAN_LEN ? stackalloc byte[(int)size] : new byte[size]; stream.Read(inputBufferSpan); long unpackedSize = OodleHelper.Decompress(inputBufferSpan, outputBufferSpan); if (unpackedSize != size) { throw new DecompressionException( $"Unpacked size {unpackedSize} doesn't match real size {size}."); } outStream.Write(outputBufferSpan); } else { stream.Seek(0, SeekOrigin.Begin); stream.CopyToWithLength(outStream, (int)zSize); } } }
/// <summary> /// Decompresses and copies a segment of zsize bytes from a stream to another stream /// </summary> /// <param name="stream"></param> /// <param name="outStream"></param> /// <param name="zSize"></param> /// <param name="size"></param> /// <exception cref="Exception"></exception> /// <exception cref="DecompressionException"></exception> public static async Task DecompressAndCopySegmentAsync(this Stream stream, Stream outStream, uint zSize, uint size) { if (zSize == size) { stream.CopyToWithLength(outStream, (int)zSize); } else { var oodleCompression = stream.ReadStruct <uint>(); if (oodleCompression == KARK) { var headerSize = stream.ReadStruct <uint>(); if (headerSize != size) { throw new Exception($"Buffer size doesn't match size in info table. {headerSize} vs {size}"); } var inputBuffer = new byte[(int)zSize - 8]; stream.Read(inputBuffer); var outputBuffer = new byte[size]; long unpackedSize = await Task.Run(() => OodleHelper.Decompress(inputBuffer, outputBuffer)); if (unpackedSize != size) { throw new DecompressionException( $"Unpacked size {unpackedSize} doesn't match real size {size}."); } outStream.Write(outputBuffer); } else { stream.Seek(0, SeekOrigin.Begin); stream.CopyToWithLength(outStream, (int)zSize); } } }
/// <summary> /// /// </summary> /// <param name="inputBytes"></param> /// <param name="inputOffset"></param> /// <param name="inputCount"></param> /// <param name="outputBytes"></param> /// <param name="outputOffset"></param> /// <param name="outputCount"></param> /// <param name="algo"></param> /// <param name="level"></param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="NotImplementedException"></exception> public static int Compress( byte[] inputBytes, // int inputOffset, int inputCount, ref IEnumerable <byte> outputBuffer, // int outputOffset, // int outputCount, OodleNative.OodleLZ_Compressor algo = OodleNative.OodleLZ_Compressor.Kraken, OodleNative.OodleLZ_Compression level = OodleNative.OodleLZ_Compression.Normal) { if (inputBytes == null) { throw new ArgumentNullException(nameof(inputBytes)); } if (inputCount <= 0 || inputCount > inputBytes.Length) { throw new ArgumentOutOfRangeException(nameof(inputCount)); } if (outputBuffer == null) { throw new ArgumentNullException(nameof(outputBuffer)); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var compressedBufferSizeNeeded = OodleHelper.GetCompressedBufferSizeNeeded((int)inputCount); var compressedBuffer = new byte[compressedBufferSizeNeeded]; var inputHandle = GCHandle.Alloc(inputBytes, GCHandleType.Pinned); var inputAddress = inputHandle.AddrOfPinnedObject(); var outputHandle = GCHandle.Alloc(compressedBuffer, GCHandleType.Pinned); var outputAddress = outputHandle.AddrOfPinnedObject(); var result = (int)OodleNative.Compress( (int)algo, inputAddress, inputCount, outputAddress, (int)level, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (long)0 ); inputHandle.Free(); outputHandle.Free(); //resize buffer var writelist = new List <byte>() { 0x4B, 0x41, 0x52, 0x4B //KARK, TODO: make this dependent on the compression algo }; writelist.AddRange(BitConverter.GetBytes(inputCount)); writelist.AddRange(compressedBuffer.Take(result)); outputBuffer = writelist; return(outputBuffer.Count()); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { //TODO: use ooz to compress outputBuffer = inputBytes; return(outputBuffer.Count()); // try // { // var result = OozNative.Compress( // (int)algo, // inputAddress, // outputAddress, // inputCount, // IntPtr.Zero, // IntPtr.Zero // ); // inputHandle.Free(); // outputHandle.Free(); // return result; // } // catch (Exception e) // { // Console.WriteLine(e); // throw; // } } else { throw new NotImplementedException(); } }