Provides a thin wrapper for a buffer that is filled by calling the provided callback.

The fields in this class and its base are not encapsulated properly for performance reasons. For example, Buffer.this along with Index should be replaced with a method like GetBufferedByte(). However, doing so costs more than 30% of the throughput in dependent classes when run on the windows phone emulator. This most likely stems form the fact that the CF JIT is only able to inline very simple methods. Apparently, even a method with the one-liner return this.buffer[this.index++]; is not eligible for inlining.

A frequent use case for this class is when a not previously known number of bytes need to be read from a stream one by one. In this case the following code tends to be much faster than calling Stream.ReadByte for each byte: void ReadFromStream(Stream stream) { var readBuffer = new ReadBuffer(stream.Read, 1024); while ((readBuffer.Index < readBuffer.Count) || readBuffer.Read()) { var theByte = readBuffer[readBuffer.Index++]; // Do something with the byte. } }

Наследование: Buffer
Пример #1
0
        public void ReadAsyncTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    var originalBytes = new byte[3];
                    this.Random.NextBytes(originalBytes);

                    // This covers the case where the read bytes are copied into the buffer in two chunks
                    using (var originalStream = new MemoryStream(originalBytes))
                    {
                        var readBuffer = new ReadBuffer((ReadAsyncCallback)originalStream.ReadAsync, 2);
                        var buffer = new byte[1];
                        int read;

                        using (var readStream = new MemoryStream())
                        {
                            while ((read = await readBuffer.ReadAsync(
                                buffer, 0, buffer.Length, CancellationToken.None)) > 0)
                            {
                                readStream.Write(buffer, 0, read);
                            }

                            var largeBuffer = new byte[readBuffer.Capacity + 1];
                            Assert.AreEqual(
                                0,
                                await readBuffer.ReadAsync(largeBuffer, 0, largeBuffer.Length, CancellationToken.None));
                            CollectionAssert.AreEqual(originalBytes, readStream.ToArray());
                        }
                    }
                });
        }
Пример #2
0
        public void ReadTest()
        {
            var originalbytes = new byte[3];
            this.Random.NextBytes(originalbytes);

            // This covers the case where the read bytes are copied into the buffer in two chunks
            using (var originalStream = new MemoryStream(originalbytes))
            {
                var readBuffer = new ReadBuffer(originalStream.Read, 2);
                var buffer = new byte[1];
                int read;

                using (var readStream = new MemoryStream())
                {
                    while ((read = readBuffer.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        readStream.Write(buffer, 0, read);
                    }

                    Assert.AreEqual(0, readBuffer.Read(new byte[readBuffer.Capacity + 1], 0, readBuffer.Capacity + 1));
                    CollectionAssert.AreEqual(originalbytes, readStream.ToArray());
                }
            }
        }
Пример #3
0
 internal MyBufferStream(ReadBuffer readBuffer, WriteBuffer writeBuffer)
     : base(readBuffer, writeBuffer)
 {
 }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Initializes a new instance of the <see cref="BufferStream"/> class.</summary>
        /// <remarks>Pass <c>null</c> for one of the buffers to create a stream that only supports reading or writing.</remarks>
        protected BufferStream(ReadBuffer readBuffer, WriteBuffer writeBuffer)
        {
            this.ReadBuffer  = readBuffer;
            this.WriteBuffer = writeBuffer;
        }
Пример #5
0
        public void FillAsyncTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    var originalBytes = new byte[3];
                    this.Random.NextBytes(originalBytes);

                    using (var originalStream = new MemoryStream(originalBytes))
                    {
                        var readBuffer = new ReadBuffer((ReadAsyncCallback)originalStream.ReadAsync, 2);
                        var readBytes = new byte[originalBytes.Length];
                        await readBuffer.FillAsync(readBytes, 0, readBytes.Length, CancellationToken.None);
                        CollectionAssert.AreEqual(originalBytes, readBytes);
                    }
                });
        }
Пример #6
0
        public void ExceptionTest()
        {
            AsyncPump.Run(
                async () =>
                {
                    AssertThrow<ArgumentNullException>(
                        () => new ReadBuffer((ReadCallback)null, 1).Ignore(),
                        () => new ReadBuffer((ReadAsyncCallback)null, 1).Ignore(),
                        () => new WriteBuffer((WriteCallback)null, 1).Ignore(),
                        () => new WriteBuffer((WriteAsyncCallback)null, 1).Ignore(),
                        () => new WriteBuffer((b, o, c) => { }, 1).WriteAsUtf8(null, 0));
                    AssertThrow<ArgumentOutOfRangeException>(() => new ReadBuffer((b, o, c) => 0, 0).Ignore());

                    using (var stream = new MemoryStream())
                    {
                        var readBuffer = new ReadBuffer(stream.Read, 1);
                        AssertThrow<EndOfStreamException>(
                            () => readBuffer.Fill(new byte[1], 0, 1),
                            () => readBuffer.Fill(new byte[2], 0, 2));
                        await AssertThrowAsync<InvalidOperationException>(
                            () => readBuffer.ReadAsync(CancellationToken.None),
                            () => readBuffer.ReadAsync(new byte[1], 0, 1, CancellationToken.None),
                            () => readBuffer.FillAsync(1, CancellationToken.None),
                            () => readBuffer.FillAsync(new byte[1], 0, 1, CancellationToken.None));

                        var asyncReadBuffer = new ReadBuffer((ReadAsyncCallback)stream.ReadAsync, 1);
                        await AssertThrowAsync<EndOfStreamException>(
                            () => asyncReadBuffer.FillAsync(new byte[1], 0, 1, CancellationToken.None),
                            () => asyncReadBuffer.FillAsync(new byte[2], 0, 2, CancellationToken.None));
                        AssertThrow<InvalidOperationException>(
                            () => asyncReadBuffer.Read(),
                            () => asyncReadBuffer.Read(new byte[1], 0, 1),
                            () => asyncReadBuffer.Fill(1),
                            () => asyncReadBuffer.Fill(new byte[1], 0, 1),
                            () => asyncReadBuffer.ReadUtf8(1));

                        var writeBuffer = new WriteBuffer(stream.Write, 1);
                        await AssertThrowAsync<InvalidOperationException>(
                            () => writeBuffer.FlushAsync(CancellationToken.None),
                            () => writeBuffer.ReserveAsync(2, CancellationToken.None),
                            () => writeBuffer.WriteAsync(new byte[3], 0, 3, CancellationToken.None));

                        var asyncWriteBuffer = new WriteBuffer(stream.WriteAsync, 1);
                        asyncWriteBuffer[asyncWriteBuffer.Count++] = 42;
                        AssertThrow<InvalidOperationException>(() => asyncWriteBuffer.Flush());
                        asyncWriteBuffer[asyncWriteBuffer.Count++] = 42;
                        AssertThrow<InvalidOperationException>(
                            () => asyncWriteBuffer.Reserve(2), () => asyncWriteBuffer.Write(new byte[3], 0, 3));
                        asyncWriteBuffer[asyncWriteBuffer.Count++] = 42;
                        var str = "Hello";
                        AssertThrow<InvalidOperationException>(
                            () => asyncWriteBuffer.WriteAsUtf8(str, Encoding.UTF8.GetByteCount(str)));
                    }
                });
        }
 internal MyBufferStream(ReadBuffer readBuffer, WriteBuffer writeBuffer)
     : base(readBuffer, writeBuffer)
 {
 }
Пример #8
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Initializes a new instance of the <see cref="BufferStream"/> class.</summary>
        /// <remarks>Pass <c>null</c> for one of the buffers to create a stream that only supports reading or writing.</remarks>
        protected BufferStream(ReadBuffer readBuffer, WriteBuffer writeBuffer)
        {
            this.ReadBuffer = readBuffer;
            this.WriteBuffer = writeBuffer;
        }
Пример #9
0
        private byte[] ReadByte(ReadBuffer readBuffer, byte[] buffer, ref int index)
        {
            var currentByte = readBuffer[readBuffer.Index++];

            switch (this.readState)
            {
                case ReadState.Data:
                    if (currentByte == Command.InterpretAsCommand)
                    {
                        this.readState = ReadState.Command;
                    }
                    else
                    {
                        buffer[index++] = currentByte;
                    }

                    return null;
                case ReadState.Command:
                    switch (currentByte)
                    {
                        case Command.Will:
                        case Command.Wont:
                        case Command.Do:
                        case Command.Dont:
                            this.readState = ReadState.OptionCode;
                            this.readCommand = currentByte;
                            break;
                        case Command.InterpretAsCommand:
                            this.readState = ReadState.Data;
                            buffer[index++] = currentByte;
                            break;
                        default:
                            this.readState = ReadState.Data;
                            break;
                    }

                    return null;
                default:
                    this.readState = ReadState.Data;
                    byte response;

                    if (currentByte == Option.SuppressGoAhead)
                    {
                        response = this.readCommand == Command.Do ? Command.Will : Command.Do;
                    }
                    else
                    {
                        response = this.readCommand == Command.Do ? Command.Wont : Command.Dont;
                    }

                    return new[] { Command.InterpretAsCommand, response, currentByte };
            }
        }