Exemplo n.º 1
0
        /// <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);
                }
        }
Exemplo n.º 2
0
        /// <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);
        }