Pchp.Library.Streams.PhpStream.ReadData C# (CSharp) Method

ReadData() public method

Reads a block of data from the stream up to length characters or up to EOLN if length is negative.
ReadData first looks for data into the readBuffers. While length is not satisfied, new data from the underlying stream are processed. The data is buffered as either string or PhpBytes but consistently. The type of the first buffer thus specifies the return type.
public ReadData ( int length, bool ending ) : TextElement
length int The number of bytes to return, when set to -1 /// reading carries on up to EOLN or EOF.
ending bool If true, the buffers are first searched for \n.
return TextElement
        public TextElement ReadData(int length, bool ending)
        {
            if (length == 0) return TextElement.Null;

            // Allow length to be -1 for ReadLine.
            Debug.Assert((length > 0) || ending);
            Debug.Assert(length >= -1);

            // Set file access to reading
            CurrentAccess = FileAccess.Read;
            if (!CanRead) return TextElement.Null;

            // If (length < 0) read up to \n, otherwise up to length bytes      
            // Unbuffered works only for Read not for ReadLine (blocks).
            if (!IsReadBuffered && (readBuffers == null))
            {
                // The stream is a "pure" unbuffered. Read just the first packet.
                var packet = TextElement.Null;
                bool done = false;
                while (!done)
                {
                    int count = (length > 0) ? length : readChunkSize;
                    packet = ReadFiltered(count);
                    if (packet.IsNull) return TextElement.Null;

                    int filteredLength = packet.Length;
                    done = filteredLength > 0;
                    readFilteredCount += filteredLength;

                    if (length < 0)
                    {
                        // If the data contains the EOLN, store the rest into the buffers, otherwise return the whole packet.
                        int eoln = FindEoln(packet, 0);
                        if (eoln > 0)
                        {
                            TextElement rv, enq;
                            SplitData(packet, eoln, out rv, out enq);
                            if (enq.Length != 0) EnqueueReadBuffer(enq);
                            return rv;
                        }
                    }
                }
                return packet;
            }

            // Try to fill the buffers with enough data (to satisfy length).
            int nlpos, buffered = ReadBufferScan(out nlpos), read = 0, newLength = length;
            TextElement data = TextElement.Null;

            if (ending && (nlpos >= readPosition))
            {
                // Found a \n in the buffered data (return the line inluding the EOLN).
                // Network-based streams may be satisfied too.
                newLength = nlpos - readPosition + 1;
            }
            else if ((length > 0) && (buffered >= length))
            {
                // Great! Just take some of the data in the buffers.
                // NOP
            }
            else if (!IsReadBuffered && (buffered > 0))
            {
                // Use the first available packet for network-based streams.
                newLength = buffered;
            }
            else
            {
                // There is not enough data in the buffers, read more.
                for (;;)
                {
                    data = ReadFiltered(readChunkSize);
                    if (data.IsNull)
                    {
                        // There is an EOF, return as much data as possible.
                        newLength = buffered;
                        break;
                    }
                    read = data.Length;
                    readFilteredCount += read;
                    if (read > 0) EnqueueReadBuffer(data);
                    buffered += read;

                    // For unbuffered streams accept the first packet and go check for EOLN.
                    if (!IsReadBuffered) newLength = buffered;

                    // First check for satisfaciton of the ending.
                    if (ending && !data.IsNull)
                    {
                        // Find the EOLN in the most recently read buffer.
                        int eoln = FindEoln(data, 0);
                        if (eoln >= 0)
                        {
                            // Read all the data up to (and including) the EOLN.
                            newLength = buffered - read + eoln + 1;
                            break;
                        }
                    }

                    // Check if there is enough data in the buffers (first packet etc).
                    if (length > 0)
                    {
                        if (buffered >= length) break;
                    }
                }
            }

            // Apply the restriction of available data size or newline position
            if ((newLength < length) || (length == -1)) length = newLength;

            // Eof?
            if ((readBuffers == null) || (readBuffers.Count == 0))
                return TextElement.Null;

            // Read the rest of the buffered data if no \n is found and there is an EOF.
            if (length < 0) length = buffered;

            if (this.IsText)
                return new TextElement(ReadTextBuffer(length));
            else
                return new TextElement(ReadBinaryBuffer(length));
            // Data may only be a string or PhpBytes (and consistently throughout all the buffers).
        }