<commit_before>﻿using System;
using System.IO;

namespace Http
{
    using System.Diagnostics.Contracts;
    using System.Threading;

    public class MessageBodyStream : Stream
    {
        private readonly Stream messageBody;
        private readonly long contentLength;
        private long position;
        private bool disposed;

        public MessageBodyStream(Stream messageBody, long contentLength)
        {
            Contract.Requires(messageBody != null);
            Contract.Requires(messageBody.Length >= 0);
            this.messageBody = messageBody;
            this.contentLength = contentLength;
        }

        /// <inheritdoc />
        public override void Flush()
        {
            try
            {
                this.messageBody.Flush();
            }
            catch (IOException ioException)
            {
                throw new IOException("An I/O error occurred while flushing the stream.", ioException);
            }
        }

        /// <inheritdoc />
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", "Precondition: buffer != null");
            }

            if ((offset + count) > buffer.Length)
            {
                throw new ArgumentException("Precondition: buffer.Length >= (offset + count)");
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", offset, "Precondition: offset >= 0");
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", count, "Precondition: count >= 0");
            }

            if (!this.CanRead)
            {
                throw new NotSupportedException("Precondition: Stream.CanRead");
            }

            lock (this.messageBody)
            {
                var position = this.Position;
                var length = this.Length;
                var available = length - position;
                int bytesRead;

                // Ensure no reading past the end of the message body
                // This step is vital: HTTP pipelining permits multiple messages on the same stream
                if (count > available)
                {
                    count = (int)available;
                }

                // Delegate read operation to the inner stream
                try
                {
                    bytesRead = this.messageBody.Read(buffer, offset, count);
                }
                catch (IOException ioException)
                {
                    throw new IOException("An I/O error occurred while reading the stream.", ioException);
                }

                // Update the position
                Interlocked.Add(ref this.position, bytesRead);

                // Return the number of bytes read
                return bytesRead;
            }
        }

        /// <inheritdoc />
        public override long Seek(long offset, SeekOrigin origin)
        {<commit_msg>Changing 'MessageBodyStream' to not cause any unnecessary read operations<commit_after>﻿using System;
using System.IO;

namespace Http
{
    using System.Diagnostics.Contracts;
    using System.Threading;

    public class MessageBodyStream : Stream
    {
        private readonly Stream messageBody;
        private readonly long contentLength;
        private long position;
        private bool disposed;

        public MessageBodyStream(Stream messageBody, long contentLength)
        {
            Contract.Requires(messageBody != null);
            Contract.Requires(messageBody.Length >= 0);
            this.messageBody = messageBody;
            this.contentLength = contentLength;
        }

        /// <inheritdoc />
        public override void Flush()
        {
            try
            {
                this.messageBody.Flush();
            }
            catch (IOException ioException)
            {
                throw new IOException("An I/O error occurred while flushing the stream.", ioException);
            }
        }

        /// <inheritdoc />
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer", "Precondition: buffer != null");
            }

            if ((offset + count) > buffer.Length)
            {
                throw new ArgumentException("Precondition: buffer.Length >= (offset + count)");
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset", offset, "Precondition: offset >= 0");
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", count, "Precondition: count >= 0");
            }

            if (!this.CanRead)
            {
                throw new NotSupportedException("Precondition: Stream.CanRead");
            }

            // Optimization: return early if the caller wants 0 bytes
            if (count == 0)
            {
                return 0;
            }


            lock (this.messageBody)
            {
                var unread = this.contentLength - this.position;

                // Optimization: return early if there are no unread bytes
                if (unread == 0)
                {
                    return 0;
                }

                // Ensure no reading past the end of the message body
                // This step is vital: HTTP pipelining permits multiple messages on the same stream
                if (count > unread)
                {
                    count = (int)unread;
                }

                // Delegate the read operation to the inner stream
                int bytesRead;
                try
                {
                    bytesRead = this.messageBody.Read(buffer, offset, count);
                }
                catch (IOException ioException)
                {
                    throw new IOException("An I/O error occurred while reading the stream.", ioException);
                }

                // Update the position
                Interlocked.Add(ref this.position, bytesRead);

                // Return the number of bytes read
                return bytesRead;
            }
        }

        /// <inheritdoc />
        public override long Seek(long offset, SeekOrigin origin)
        {
{'fraction_non_alphanumeric': 0.07861681690557115, 'fraction_numerical': 0.0022166395744052016, 'mean_word_length': 1.3091095189355169, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3076978', 'n_tokens_mistral': 1581, 'n_tokens_neox': 1468, 'n_words': 455}