예제 #1
0
        /// <summary>
        /// Reads data from the buffer or the underlying stream.
        /// </summary>
        /// <param name="userBuffer">The buffer to read the data to.</param>
        /// <param name="offset">The offset in the buffer to write to.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The number of bytes actually read.</returns>
        public override int Read(byte[] userBuffer, int offset, int count)
        {
            ExceptionUtils.CheckArgumentNotNull(userBuffer, "userBuffer");
            ExceptionUtils.CheckIntegerNotNegative(offset, "offset");
            ExceptionUtils.CheckIntegerPositive(count, "count");

            int bytesRead = 0;

            // See whether we still have buffered data and read from it if we have;
            // NOTE When not reading from the buffer the currentReadNode must be null.
            while (this.currentReadNode != null && count > 0)
            {
                byte[] currentBytes         = this.currentReadNode.Value;
                int    bytesInCurrentBuffer = currentBytes.Length - this.positionInCurrentBuffer;
                if (bytesInCurrentBuffer == count)
                {
                    // Copy all the remaining bytes of the current buffer to the user buffer
                    // and move to the next buffer
                    Buffer.BlockCopy(currentBytes, this.positionInCurrentBuffer, userBuffer, offset, count);
                    bytesRead += count;

                    this.MoveToNextBuffer();
                    return(bytesRead);
                }

                if (bytesInCurrentBuffer > count)
                {
                    // Copy the requested number of bytes to the user buffer
                    // and update the position in the current buffer
                    Buffer.BlockCopy(currentBytes, this.positionInCurrentBuffer, userBuffer, offset, count);
                    bytesRead += count;
                    this.positionInCurrentBuffer += count;
                    return(bytesRead);
                }

                // Copy the remaining bytes of the current buffer to the user buffer and
                // move to the next buffer
                Buffer.BlockCopy(currentBytes, this.positionInCurrentBuffer, userBuffer, offset, bytesInCurrentBuffer);
                bytesRead += bytesInCurrentBuffer;
                offset    += bytesInCurrentBuffer;
                count     -= bytesInCurrentBuffer;

                this.MoveToNextBuffer();
            }

            // When we get here we either could not satisfy the requested number of bytes
            // from the buffers or are in buffering mode.
            Debug.Assert(this.currentReadNode == null, "No current read node should exist if we are not working off the buffers.");
            int bytesReadFromInnerStream = this.innerStream.Read(userBuffer, offset, count);

            // If we are in buffering mode, store the read bytes in our buffer
            if (!this.bufferingModeDisabled && bytesReadFromInnerStream > 0)
            {
                byte[] newDataBuffer = new byte[bytesReadFromInnerStream];
                Buffer.BlockCopy(userBuffer, offset, newDataBuffer, 0, bytesReadFromInnerStream);
                this.buffers.AddLast(newDataBuffer);
            }

            return(bytesRead + bytesReadFromInnerStream);
        }