NanoByte.Common.Streams.CircularBufferStream.Read C# (CSharp) Method

Read() public method

public Read ( byte buffer, int offset, int count ) : int
buffer byte
offset int
count int
return int
        public override int Read(byte[] buffer, int offset, int count)
        {
            #region Sanity checks
            if (buffer == null) throw new ArgumentNullException(nameof(buffer));
            if (offset < 0 || offset > buffer.Length) throw new ArgumentOutOfRangeException(nameof(offset));
            if (count + offset > buffer.Length) throw new ArgumentOutOfRangeException(nameof(count));
            #endregion

            // Bytes copied to target buffer so far
            int bytesCopied = 0;

            // Loop until the request number of bytes have been returned
            while (bytesCopied != count)
            {
                if (IsDisposed) throw new ObjectDisposedException("CircularBufferStream");

                lock (_lock)
                {
                    if (_relayedException != null) throw _relayedException;

                    // All data read and no new data coming
                    if (_doneWriting && _dataLength == 0) break;
                }

                // Block while buffer is empty
                _dataAvailable.WaitOne();

                if (IsDisposed) throw new ObjectDisposedException("CircularBufferStream");

                lock (_lock)
                {
                    // The index of the last byte currently stored in the buffer plus one
                    int dataEnd = (_dataStart + _dataLength) % _buffer.Length;

                    // Determine how many bytes can be read in one go
                    int contigousDataBytes;
                    if (_dataLength == 0) contigousDataBytes = 0; // Empty
                    else if (_dataLength == _buffer.Length) contigousDataBytes = _buffer.Length - _dataStart; // Full, potentially wrap around, partial read
                    else if (_dataStart < dataEnd) contigousDataBytes = dataEnd - _dataStart; // No wrap around, read all
                    else contigousDataBytes = _buffer.Length - _dataStart; // Wrap around, partial read
                    Debug.Assert(contigousDataBytes <= _dataLength, "Contigous data length can not exceed total data length");

                    int bytesToCopy = Math.Min(contigousDataBytes, count - bytesCopied);
                    Buffer.BlockCopy(_buffer, _dataStart, buffer, offset + bytesCopied, bytesToCopy);

                    // Update counters
                    bytesCopied += bytesToCopy;
                    _positionRead += bytesToCopy;
                    _dataLength -= bytesToCopy;
                    _dataStart += bytesToCopy;

                    // Roll over start pointer
                    _dataStart %= _buffer.Length;

                    // Start blocking when buffer becomes empty
                    if (_dataLength == 0) _dataAvailable.Reset();

                    // Stop blocking when space becomes available
                    if (_dataLength < _buffer.Length) _spaceAvailable.Set();
                }
            }

            return bytesCopied;
        }

Usage Example

Esempio n. 1
0
        public void TestSequential()
        {
            _stream.Write(new byte[] { 255, 1, 2, 3, 255 }, 1, 3);

            var result = new byte[5];

            _stream.Read(result, 1, 3);
            result.Should().Equal(0, 1, 2, 3, 0);
        }