| 21 | : start(buffer.begin()), end(buffer.end()), max_line_length(max_line_length), it(buffer.begin()) {} |
| 22 | |
| 23 | std::optional<std::string_view> LineReader::ReadLine() |
| 24 | { |
| 25 | if (it == end) { |
| 26 | return std::nullopt; |
| 27 | } |
| 28 | |
| 29 | auto line_start = it; |
| 30 | size_t count = 0; |
| 31 | while (it != end) { |
| 32 | // Read a character from the incoming buffer and increment the iterator |
| 33 | auto c = static_cast<char>(*it); |
| 34 | ++it; |
| 35 | ++count; |
| 36 | // If the character we just consumed was \n, the line is terminated. |
| 37 | // The \n itself does not count against max_line_length. |
| 38 | if (c == '\n') { |
| 39 | const std::string_view untrimmed_line(reinterpret_cast<const char*>(std::to_address(line_start)), count); |
| 40 | std::string_view line = RemoveSuffixView(untrimmed_line, "\n"); |
| 41 | return RemoveSuffixView(line, "\r"); |
| 42 | } |
| 43 | // If the character we just consumed gives us a line length greater |
| 44 | // than max_line_length, and we are not at the end of the line (or buffer) yet, |
| 45 | // that means the line we are currently reading is too long, and we throw. |
| 46 | if (count > max_line_length) { |
| 47 | // Reset iterator |
| 48 | it = line_start; |
| 49 | throw std::runtime_error("max_line_length exceeded by LineReader"); |
| 50 | } |
| 51 | } |
| 52 | // End of buffer reached without finding a \n or exceeding max_line_length. |
| 53 | // Reset the iterator so the rest of the buffer can be read granularly |
| 54 | // with ReadLength() and return null to indicate a line was not found. |
| 55 | it = line_start; |
| 56 | return std::nullopt; |
| 57 | } |
| 58 | |
| 59 | // Ignores max_line_length but won't overflow |
| 60 | std::string_view LineReader::ReadLength(size_t len) |