Bug 1861709 replace AudioCallbackDriver::ThreadRunning() assertions that mean to...
[gecko.git] / netwerk / base / nsReadLine.h
blobf1e4693f92b1969f056e8c31c1524d1dacf990bd
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef nsReadLine_h__
8 #define nsReadLine_h__
10 #include "nsIInputStream.h"
11 #include "mozilla/Likely.h"
13 /**
14 * @file
15 * Functions to read complete lines from an input stream.
17 * To properly use the helper function in here (NS_ReadLine) the caller should
18 * create a nsLineBuffer<T> with new, and pass it to NS_ReadLine every time it
19 * wants a line out.
21 * When done, the object should be deleted.
24 /**
25 * @internal
26 * Buffer size. This many bytes will be buffered. If a line is longer than this,
27 * the partial line will be appended to the out parameter of NS_ReadLine and the
28 * buffer will be emptied.
29 * Note: if you change this constant, please update the regression test in
30 * netwerk/test/unit/test_readline.js accordingly (bug 397850).
32 #define kLineBufferSize 4096
34 /**
35 * @internal
36 * Line buffer structure, buffers data from an input stream.
37 * The buffer is empty when |start| == |end|.
38 * Invariant: |start| <= |end|
40 template <typename CharT>
41 class nsLineBuffer {
42 public:
43 nsLineBuffer() : start(buf), end(buf) {}
45 CharT buf[kLineBufferSize + 1];
46 CharT* start;
47 CharT* end;
50 /**
51 * Read a line from an input stream. Lines are separated by '\r' (0x0D) or '\n'
52 * (0x0A), or "\r\n" or "\n\r".
54 * @param aStream
55 * The stream to read from
56 * @param aBuffer
57 * The line buffer to use. A single line buffer must not be used with
58 * different input streams.
59 * @param aLine [out]
60 * The string where the line will be stored.
61 * @param more [out]
62 * Whether more data is available in the buffer. If true, NS_ReadLine may
63 * be called again to read further lines. Otherwise, further calls to
64 * NS_ReadLine will return an error.
66 * @retval NS_OK
67 * Read successful
68 * @retval error
69 * Input stream returned an error upon read. See
70 * nsIInputStream::read.
72 template <typename CharT, class StreamType, class StringType>
73 nsresult NS_ReadLine(StreamType* aStream, nsLineBuffer<CharT>* aBuffer,
74 StringType& aLine, bool* more) {
75 CharT eolchar = 0; // the first eol char or 1 after \r\n or \n\r is found
77 aLine.Truncate();
79 while (true) { // will be returning out of this loop on eol or eof
80 if (aBuffer->start == aBuffer->end) { // buffer is empty. Read into it.
81 uint32_t bytesRead;
82 nsresult rv = aStream->Read(aBuffer->buf, kLineBufferSize, &bytesRead);
83 if (NS_FAILED(rv) || MOZ_UNLIKELY(bytesRead == 0)) {
84 *more = false;
85 return rv;
87 aBuffer->start = aBuffer->buf;
88 aBuffer->end = aBuffer->buf + bytesRead;
89 *(aBuffer->end) = '\0';
93 * Walk the buffer looking for an end-of-line.
94 * There are 3 cases to consider:
95 * 1. the eol char is the last char in the buffer
96 * 2. the eol char + one more char at the end of the buffer
97 * 3. the eol char + two or more chars at the end of the buffer
98 * we need at least one char after the first eol char to determine if
99 * it's a \r\n or \n\r sequence (and skip over it), and we need one
100 * more char after the end-of-line to set |more| correctly.
102 CharT* current = aBuffer->start;
103 if (MOZ_LIKELY(eolchar == 0)) {
104 for (; current < aBuffer->end; ++current) {
105 if (*current == '\n' || *current == '\r') {
106 eolchar = *current;
107 *current++ = '\0';
108 aLine.Append(aBuffer->start);
109 break;
113 if (MOZ_LIKELY(eolchar != 0)) {
114 for (; current < aBuffer->end; ++current) {
115 if ((eolchar == '\r' && *current == '\n') ||
116 (eolchar == '\n' && *current == '\r')) {
117 eolchar = 1;
118 continue;
120 aBuffer->start = current;
121 *more = true;
122 return NS_OK;
126 if (eolchar == 0) aLine.Append(aBuffer->start);
127 aBuffer->start = aBuffer->end; // mark the buffer empty
131 #endif // nsReadLine_h__