internal override void EndOfStream()

in cs/src/io/unsafe/InputStream.cs [97:204]


        internal override void EndOfStream(int count)
        {
            // The unread bytes left in the buffer. May be negative, which
            // indicates that this stream has been advanced beyond where we
            // are in the underlying stream and some bytes will need to be
            // skipped.
            var remaining = end - position;

            bool failed = false;
            byte[][] tempBuffers = EmptyTempBuffers;

            // Check whether we need to read in chunks to avoid allocating a
            // ton of memory ahead of time.
            if ((count > buffer.Length && (count - buffer.Length > ActiveAllocationChunk)))
            {
                // Calculate number of temp buffers; we round down since the
                // last chunk is read directly into final buffer. Note:
                // Difference is adjusted by -1 to round down correctly in
                // cases where the difference is exactly a multiple of the
                // allocation chunk size.
                int numTempBuffers = (count - buffer.Length - 1) / ActiveAllocationChunk;

                tempBuffers = new byte[numTempBuffers][];

                for (int i = 0; i < tempBuffers.Length; i++)
                {
                    tempBuffers[i] = new byte[ActiveAllocationChunk];

                    if (remaining < 0)
                    {
                        // We need to skip ahead in the underlying stream.
                        // Borrow the buffer to do the skipping before we do
                        // the real read.

                        // Only should happen for the first iteration, as we
                        // reset remaining.
                        Debug.Assert(i == 0);

                        AdvanceUnderlyingStream(-remaining, tempBuffers[i]);
                        remaining = 0;
                    }

                    var bytesRead = stream.Read(tempBuffers[i], 0, ActiveAllocationChunk);
                    if (bytesRead != ActiveAllocationChunk)
                    {
                        failed = true;
                        break;
                    }
                }
            }

            if (!failed)
            {
                var oldBuffer = buffer;

                if (!canReuseBuffer || count > buffer.Length)
                {
                    buffer = new byte[Math.Max(bufferLength, count)];
                    canReuseBuffer = true;
                }

                int offset;

                if (remaining > 0)
                {
                    // Copy any remaining bytes from the old buffer into the
                    // final buffer. This may just move the bytes to the
                    // beginning of the buffer.
                    Buffer.BlockCopy(oldBuffer, position, buffer, 0, remaining);
                    offset = remaining;
                }
                else if (remaining < 0)
                {
                    // Nothing in the old buffer, but we need to skip ahead
                    // in the underlying stream.
                    AdvanceUnderlyingStream(-remaining, buffer);
                    offset = 0;
                }
                else
                {
                    // The stars are aligned, so just start at the beginning
                    // of the final buffer.
                    offset = 0;
                }

                // Copy from any temp buffers into the final buffer. In the
                // common case, there are no temp buffers.
                foreach (byte[] tempBuffer in tempBuffers)
                {
                    Buffer.BlockCopy(
                        tempBuffer,
                        0,
                        buffer,
                        offset,
                        tempBuffer.Length);
                    offset += tempBuffer.Length;
                }

                // Read the final block; update valid length and position.
                end = offset + stream.Read(buffer, offset, buffer.Length - offset);
                position = 0;
            }

            if (count > end)
            {
                base.EndOfStream(count - end);
            }
        }