/// <summary>
 /// Read the next line of text.
 /// </summary>
 /// <param name="stream">The stream to read from.</param>
 /// <param name="async">
 /// Whether to invoke the operation asynchronously.
 /// </param>
 /// <param name="cancellationToken">
 /// Optional <see cref="CancellationToken"/> to propagate notifications
 /// that the operation should be cancelled.
 /// </param>
 /// <returns>The next line of text.</returns>
 internal static async Task <string> ReadLineAsync(
     this BufferedReadStream stream,
     bool async,
     CancellationToken cancellationToken) =>
 async ?
 await stream.ReadLineAsync(BatchConstants.ResponseLineSize, cancellationToken).ConfigureAwait(false) :
 stream.ReadLine(BatchConstants.ResponseLineSize);
Esempio n. 2
0
    public override int Read(byte[] buffer, int offset, int count)
    {
        if (_finished)
        {
            return(0);
        }

        PositionInnerStream();
        if (!_innerStream.EnsureBuffered(_boundary.FinalBoundaryLength))
        {
            throw new IOException("Unexpected end of Stream, the content may have already been read by another component. ");
        }
        var bufferedData = _innerStream.BufferedData;

        // scan for a boundary match, full or partial.
        int read;

        if (SubMatch(bufferedData, _boundary.BoundaryBytes, out var matchOffset, out var matchCount))
        {
            // We found a possible match, return any data before it.
            if (matchOffset > bufferedData.Offset)
            {
                read = _innerStream.Read(buffer, offset, Math.Min(count, matchOffset - bufferedData.Offset));
                return(UpdatePosition(read));
            }

            var length = _boundary.BoundaryBytes.Length;
            Debug.Assert(matchCount == length);

            // "The boundary may be followed by zero or more characters of
            // linear whitespace. It is then terminated by either another CRLF"
            // or -- for the final boundary.
            var boundary = _bytePool.Rent(length);
            read = _innerStream.Read(boundary, 0, length);
            _bytePool.Return(boundary);
            Debug.Assert(read == length);                            // It should have all been buffered

            var remainder = _innerStream.ReadLine(lengthLimit: 100); // Whitespace may exceed the buffer.
            remainder = remainder.Trim();
            if (string.Equals("--", remainder, StringComparison.Ordinal))
            {
                FinalBoundaryFound = true;
            }
            Debug.Assert(FinalBoundaryFound || string.Equals(string.Empty, remainder, StringComparison.Ordinal), "Un-expected data found on the boundary line: " + remainder);
            _finished = true;
            return(0);
        }

        // No possible boundary match within the buffered data, return the data from the buffer.
        read = _innerStream.Read(buffer, offset, Math.Min(count, bufferedData.Count));
        return(UpdatePosition(read));
    }