Esempio n. 1
0
        private static (int Read, bool StreamIsEnd, GzipBuffer gzipBuffer) ReadGzipBufferFromStream(RewindableReadonlyStream stream, byte[] currentBuffer)
        {
            GzipBuffer gzipBuffer = default;

            var(readBuffer, endOfStream) = stream.ReadExactBuffer(currentBuffer);
            if (readBuffer.Count > 0)
            {
                var readGzipBuffer = new GzipBuffer(readBuffer);
                if (readGzipBuffer.NoHeaders)
                {
                    gzipBuffer = default;
                }
                else
                {
                    gzipBuffer = readGzipBuffer;
                    if (!endOfStream && readGzipBuffer.IsStartsWithCompressedBlock && readGzipBuffer.Headers.Count == 1)
                    {
                        endOfStream = stream.IsReadToTheEnd;
                    }
                }
            }

            return(readBuffer.Count, endOfStream, gzipBuffer);
        }
Esempio n. 2
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            CheckStreamPosition();
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset), "Need non negative number");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "Need non negative number");
            }
            if (buffer.Length - offset < count)
            {
                throw new ArgumentException($"Buffer have smaller elements {buffer.Length - offset} from given offset {offset} than requested in count {count}", nameof(count));
            }

            if (count == 0)
            {
                throw new ArgumentException("Requested zero elements", nameof(count));
            }

            if (count < GzipHeader.Length)
            {
                throw new ArgumentException("Buffer element count can't be less than Gzip header length", nameof(count));
            }

            if (buffer.Length - offset == 0)
            {
                throw new ArgumentException("Buffer has no elements from requested offset", nameof(offset));
            }

            var currentGzipBuffer = leftBuffer;
            var isEnd             = streamEnded;
            var read = 0;

            if (currentGzipBuffer.IsEmpty && !streamEnded)
            {
                (read, isEnd, currentGzipBuffer) = ReadGzipBufferFromStream();
            }

            if (!currentGzipBuffer.IsEmpty)
            {
                ArraySegment <byte> readBlock;
                (readBlock, currentGzipBuffer) = ReadFirstBockFromBuffer(currentGzipBuffer, count);
                read = readBlock.Count;

                if (readBlock.Array != null && readBlock.Count > 0)
                {
                    Buffer.BlockCopy(readBlock.Array, readBlock.Offset, buffer, offset, readBlock.Count);
                }
            }

            leftBuffer  = currentGzipBuffer;
            position   += read;
            streamEnded = isEnd;

            return(read);

            (int Read, bool StreamIsEnd, GzipBuffer gzipBuffer) ReadGzipBufferFromStream()
            {
                GzipBuffer gzipBuffer = default;

                var(readBuffer, endOfStream) = stream.ReadExactBuffer(buffer, offset, count);
                if (readBuffer.Count > 0)
                {
                    var readGzipBuffer = new GzipBuffer(readBuffer);
                    gzipBuffer = readGzipBuffer.NoHeadersOrParts || readGzipBuffer.ContainsOnlyOneCompressedBlockFromStart
                        ? default
                        : readGzipBuffer.ToOwnedBuffer();
                }

                return(readBuffer.Count, endOfStream, gzipBuffer);
            }

            (ArraySegment <byte> Block, GzipBuffer LeftGzipBuffer) ReadFirstBockFromBuffer(GzipBuffer gzipBuffer, int requestedCount)
            {
                var(block, left) = gzipBuffer.CutFirstBlock();
                if (block.Array == null || block.Count == 0)
                {
                    if (left.ContainsOnlyPart)
                    {
                        block = gzipBuffer.GetPossiblePart();
                    }

                    left = default;
                }
                else if (block.Count > requestedCount)
                {
                    block = block.Slice(block.Offset, requestedCount);
                    var returnBlock = block.Slice(block.Offset + requestedCount, block.Count - requestedCount);
                    left = left.ReturnToStart(returnBlock);
                }

                return(block, left);
            }
        }