/// <summary>Decompress data and resize output if needed.</summary> /// <param name="input">Array segment to decompress.</param> /// <param name="output">Output buffer to write to.</param> /// <param name="offset">Output offset to write to.</param> /// <returns>Total number of bytes written to the output.</returns> public int Decompress(ArraySegment <byte> input, ref byte[] output, int offset) { // Validate if (Disposed) { throw new ObjectDisposedException(GetType().FullName); } else if (output == null) { throw new ArgumentNullException(nameof(output), "Output buffer is null"); } else if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), string.Format( "Output offset {0} is negative", offset )); } // Decompress using (Stream stream = new MemoryStream(input.Array, input.Offset, input.Count, false)) using (Stream zip = new DeflateStream(stream, CompressionMode.Decompress)) { int total = 0, outputOffset = offset, count; do { // Expand output if needed if (output == null || outputOffset >= output.Length) { output = Allocator.ExpandMessage(output, outputOffset); } // Process next chunk count = zip.Read(output, outputOffset, output.Length - outputOffset); outputOffset += count; total += count; } while (count > 0); return(total); } }
/// <summary>Decompress data and resize output if needed.</summary> /// <param name="input">Array segment to decompress.</param> /// <param name="output">Output buffer to write to.</param> /// <param name="offset">Output offset to write to.</param> /// <returns>Total number of bytes written to the output.</returns> public int Decompress(ArraySegment <byte> input, ref byte[] output, int offset) { // Validate if (Disposed) { throw new ObjectDisposedException(GetType().FullName); } else if (output == null) { throw new ArgumentNullException(nameof(output), "Output buffer is null"); } else if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), string.Format( "Output offset {0} is negative", offset )); } uint iidx = 0; uint oidx = 0; do { uint ctrl = input.Array[input.Offset + iidx++]; if (ctrl < (1 << 5)) { ctrl++; // Expand output if needed if (output == null || output.Length < oidx + ctrl) { output = Allocator.ExpandMessage(output, (int)oidx, (int)ctrl); } do { output[oidx++] = input.Array[input.Offset + iidx++]; } while ((--ctrl) != 0); } else { uint len = ctrl >> 5; int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1); if (len == 7) { len += input.Array[input.Offset + iidx++]; } reference -= input.Array[input.Offset + iidx++]; if (reference < 0) { throw new InvalidOperationException("Bad compressed data"); } // Expand output if needed if (output == null || output.Length < oidx + len + 2) { output = Allocator.ExpandMessage(output, (int)oidx, (int)(len + 2)); } output[oidx++] = output[reference++]; output[oidx++] = output[reference++]; do { output[oidx++] = output[reference++]; } while ((--len) != 0); } } while (iidx < input.Count); return((int)oidx); }