Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
nsReadLine.h File Reference

Functions to read complete lines from an input stream. More...

#include "prmem.h"
#include "nsIInputStream.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  nsLineBuffer< CharT >

Defines

#define kLineBufferSize   1024

Functions

template<typename CharT >
nsresult NS_InitLineBuffer (nsLineBuffer< CharT > **aBufferPtr)
 Initialize a line buffer for use with NS_ReadLine.
template<typename CharT , class StreamType , class StringType >
nsresult NS_ReadLine (StreamType *aStream, nsLineBuffer< CharT > *aBuffer, StringType &aLine, PRBool *more)
 Read a line from an input stream.

Detailed Description

Functions to read complete lines from an input stream.

To properly use the helper function in here (NS_ReadLine) the caller needs to declare a pointer to an nsLineBuffer, call NS_InitLineBuffer on it, and pass it to NS_ReadLine every time it wants a line out.

When done, the pointer should be freed using PR_Free.

Definition in file nsReadLine.h.


Class Documentation

class nsLineBuffer

template<typename CharT>
class nsLineBuffer< CharT >

Line buffer structure, buffers data from an input stream.

Definition at line 71 of file nsReadLine.h.

Inheritance diagram for nsLineBuffer< CharT >:
Collaboration diagram for nsLineBuffer< CharT >:
Class Members
CharT buf
CharT * current
PRBool empty
CharT * end
CharT * start

Define Documentation

#define kLineBufferSize   1024

Buffer size. This many bytes will be buffered. If a line is longer than this, the partial line will be appended to the out parameter of NS_ReadLine and the buffer will be emptied.

Definition at line 64 of file nsReadLine.h.


Function Documentation

template<typename CharT >
nsresult NS_InitLineBuffer ( nsLineBuffer< CharT > **  aBufferPtr)

Initialize a line buffer for use with NS_ReadLine.

Parameters:
aBufferPtrPointer to pointer to a line buffer. Upon successful return, *aBufferPtr will contain a valid pointer to a line buffer, for use with NS_ReadLine. Use PR_Free when the buffer is no longer needed.
Return values:
NS_OKSuccess.
NS_ERROR_OUT_OF_MEMORYNot enough memory to allocate the line buffer.
Example:
    nsLineBuffer* lb;
    rv = NS_InitLineBuffer(&lb);
    if (NS_SUCCEEDED(rv)) {
      // do stuff...
      PR_Free(lb);
    }

Definition at line 103 of file nsReadLine.h.

                                                      {
  *aBufferPtr = PR_NEW(nsLineBuffer<CharT>);
  if (!(*aBufferPtr))
    return NS_ERROR_OUT_OF_MEMORY;

  (*aBufferPtr)->start = (*aBufferPtr)->current = (*aBufferPtr)->end = (*aBufferPtr)->buf;
  (*aBufferPtr)->empty = PR_TRUE;
  return NS_OK;
}
template<typename CharT , class StreamType , class StringType >
nsresult NS_ReadLine ( StreamType *  aStream,
nsLineBuffer< CharT > *  aBuffer,
StringType &  aLine,
PRBool more 
)

Read a line from an input stream.

Lines are separated by '' (0x0D) or '
' (0x0A), or "\r\n" or "\n\r".

Parameters:
aStreamThe stream to read from
aBufferThe line buffer to use. Must have been inited with NS_InitLineBuffer before. A single line buffer must not be used with different input streams.
aLine[out] The string where the line will be stored.
more[out] Whether more data is available in the buffer. If true, NS_ReadLine may be called again to read further lines. Otherwise, further calls to NS_ReadLine will return an error.
Return values:
NS_OKRead successful
errorInput stream returned an error upon read. See nsIInputStream::read.

Definition at line 138 of file nsReadLine.h.

                                               {
  nsresult rv = NS_OK;
  PRUint32 bytesRead;
  *more = PR_TRUE;
  PRBool eolStarted = PR_FALSE;
  CharT eolchar = '\0';
  aLine.Truncate();
  while (1) { // will be returning out of this loop on eol or eof
    if (aBuffer->empty) { // buffer is empty.  Read into it.
      rv = aStream->Read(aBuffer->buf, kLineBufferSize, &bytesRead);
      if (NS_FAILED(rv)) // read failed
        return rv;
      if (bytesRead == 0) { // end of file
        *more = PR_FALSE;
        return NS_OK;
      }
      aBuffer->end = aBuffer->buf + bytesRead;
      aBuffer->empty = PR_FALSE;
      *(aBuffer->end) = '\0'; // null-terminate this thing
    }
    // walk the buffer looking for an end-of-line
    while (aBuffer->current < aBuffer->end) {
      if (eolStarted) {
          if ((eolchar == '\n' && *(aBuffer->current) == '\r') ||
              (eolchar == '\r' && *(aBuffer->current) == '\n')) { // line end
            (aBuffer->current)++;
            aBuffer->start = aBuffer->current;
          }
          eolStarted = PR_FALSE;
          return NS_OK;
      } else if (*(aBuffer->current) == '\n' ||
                 *(aBuffer->current) == '\r') { // line end
        eolStarted = PR_TRUE;
        eolchar = *(aBuffer->current);
        *(aBuffer->current) = '\0';
        aLine.Append(aBuffer->start);
        (aBuffer->current)++;
        aBuffer->start = aBuffer->current;
      } else {
        eolStarted = PR_FALSE;
        (aBuffer->current)++;
      }
    }

    // append whatever we currently have to the string
    aLine.Append(aBuffer->start);

    // we've run out of buffer.  Begin anew
    aBuffer->current = aBuffer->start = aBuffer->buf;
    aBuffer->empty = PR_TRUE;
    
    if (eolStarted) {  // have to read another char and possibly skip over it
      rv = aStream->Read(aBuffer->buf, 1, &bytesRead);
      if (NS_FAILED(rv)) // read failed
        return rv;
      if (bytesRead == 0) { // end of file
        *more = PR_FALSE;
        return NS_OK;
      }
      if ((eolchar == '\n' && *(aBuffer->buf) == '\r') ||
          (eolchar == '\r' && *(aBuffer->buf) == '\n')) {
        // Just return and all is good -- we've skipped the extra newline char
        return NS_OK;
      } else {
        // we have a byte that we should look at later
        aBuffer->empty = PR_FALSE;
        aBuffer->end = aBuffer->buf + 1;
        *(aBuffer->end) = '\0';
      }
    }
  }
}