public static void Decompress(Stream input, Stream output, long originalSize) { if (input == null) { throw new ArgumentNullException("input"); } if (output == null) { throw new ArgumentNullException("output"); } var remaining = originalSize; var work = new byte[0]; var buffer = new byte[0]; while (remaining > 0) { var header = CompressionHeader.Read(input); if (header.CompressionFlags == CompressionFlags.None) { throw new NotSupportedException(); header.CompressionType = header.CompressedBlockSize == header.UncompressedBlockSize ? CompressionType.None : CompressionType.Zlib; header.CompressionFlags = (CompressionFlags)7; } var compressedBlockSize = header.CompressedBlockSize; var uncompressedBlockSize = header.UncompressedBlockSize; if (buffer.Length < uncompressedBlockSize) { Array.Resize(ref buffer, uncompressedBlockSize); } switch (header.CompressionType) { case CompressionType.None: { if (compressedBlockSize != uncompressedBlockSize) { throw new InvalidOperationException(); } output.WriteFromStream(input, compressedBlockSize); remaining -= compressedBlockSize; break; } case CompressionType.Zstd: { if (work.Length < compressedBlockSize) { Array.Resize(ref work, compressedBlockSize); } var read = input.Read(work, 0, compressedBlockSize); if (read != compressedBlockSize) { throw new EndOfStreamException(); } var result = Zstd.Decompress(work, 0, compressedBlockSize, buffer, 0, uncompressedBlockSize); if (Zstd.IsError(result) == true) { throw new InvalidOperationException(); } if (result != (uint)uncompressedBlockSize) { throw new InvalidOperationException(); } output.Write(buffer, 0, uncompressedBlockSize); remaining -= uncompressedBlockSize; break; } default: { throw new NotSupportedException(); } } } }
private static void Decompress(Stream input, Stream output, long originalSize) { var remaining = originalSize; var compressedBytes = new byte[0]; var uncompressedBytes = new byte[0]; while (remaining > 0) { var uncompressedBlockSize = input.ReadValueS32(Endian.Big); var compressionType = input.ReadValueU16(Endian.Big); var compressedBlockSize = input.ReadValueU16(Endian.Big); if (uncompressedBytes.Length < uncompressedBlockSize) { Array.Resize(ref uncompressedBytes, uncompressedBlockSize); } switch (compressionType) // might be flags+type? { case 0x70: { if (compressedBlockSize != uncompressedBlockSize) { throw new InvalidOperationException(); } output.WriteFromStream(input, compressedBlockSize); remaining -= compressedBlockSize; break; } case 0x71: { if (compressedBlockSize != 0) { throw new InvalidOperationException(); } output.WriteFromStream(input, uncompressedBlockSize); remaining -= uncompressedBlockSize; break; } case 0x0F70: { if (compressedBytes.Length < compressedBlockSize) { Array.Resize(ref compressedBytes, compressedBlockSize); } var read = input.Read(compressedBytes, 0, compressedBlockSize); if (read != compressedBlockSize) { throw new EndOfStreamException(); } var result = Zstd.Decompress( compressedBytes, 0, compressedBlockSize, uncompressedBytes, 0, uncompressedBlockSize); if (Zstd.IsError(result) == true) { throw new InvalidOperationException(); } if (result != (uint)uncompressedBlockSize) { throw new InvalidOperationException(); } output.Write(uncompressedBytes, 0, uncompressedBlockSize); remaining -= uncompressedBlockSize; break; } default: { throw new NotSupportedException(); } } } }
public static int DecompressBlock(Stream input, byte[] buffer, int offset, int count, byte[] work) { if (input == null) { throw new ArgumentNullException("input"); } if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || offset + count > buffer.Length) { throw new ArgumentOutOfRangeException("count"); } if (work == null) { throw new ArgumentNullException("work"); } var header = CompressionHeader.Read(input); /* * if (header.CompressionFlags == CompressionFlags.None) * { * throw new NotSupportedException(); * header.CompressionType = header.CompressedBlockSize == header.UncompressedBlockSize * ? CompressionType.None * : CompressionType.Zlib; * header.CompressionFlags = (CompressionFlags)7; * } */ if (header.UncompressedBlockSize > count) { throw new ArgumentOutOfRangeException("count"); } switch (header.CompressionType) { case CompressionType.None: { if (header.CompressedBlockSize != header.UncompressedBlockSize) { throw new InvalidOperationException(); } return(input.Read(buffer, offset, Math.Min(count, header.CompressedBlockSize))); } case CompressionType.Zstd: { var read = input.Read(work, 0, header.CompressedBlockSize); if (read != header.CompressedBlockSize) { throw new EndOfStreamException(); } var result = Zstd.Decompress(work, 0, header.CompressedBlockSize, buffer, offset, count); if (Zstd.IsError(result) == true) { throw new InvalidOperationException(); } return((int)result); } default: { throw new NotSupportedException(); } } }