15template<
size_t N,
char TERMINATOR_CHAR = '\n',
char IGNORE_CHAR = '\r'>
class LineReader {
17 using pos_t = std::conditional_t<(N < 0xFE), uint8_t, uint16_t>;
18 static_assert(N >= 2 && N < 0xFFFE,
"LineReader size out of range");
19 static_assert(TERMINATOR_CHAR != IGNORE_CHAR,
"LineReader terminator and ignore byte must differ");
32 this->
pos_ = pos = N + 1;
34 if (c ==
static_cast<uint8_t
>(IGNORE_CHAR)) {
37 if (c ==
static_cast<uint8_t
>(TERMINATOR_CHAR)) {
47 this->
buf_[
pos] =
static_cast<char>(c);
49 }
else if (
pos == N - 1) {
80 this->
buf_[0] =
static_cast<char>(c);
92 return this->
pos_ == N ? N - 1 : 0;
Collects bytes into NUL terminated lines of up to N - 1 characters; IGNORE_CHAR bytes are skipped and...
const char * partial()
The partial line, NUL terminated, for prompts with no line end; the first N - 1 characters on the byt...
bool overflowed() const
True only right after the feed() that found the line too long; the rest of that line is then dropped.
size_t length() const
Length of the partial line; 0 after a line is returned and while an overlong line is dropped.
char * feed(uint8_t c)
Feed one byte; returns the completed line (empty lines included), valid until the next call,...
char * feed(uint8_t c, size_t &len)
As feed(c), and sets len to the line length when a line is returned.
void reset()
Forget the partial line and start a new one with the next byte.
void restart_with(uint8_t c)
Start a new line with c, e.g. the byte that overflowed; c must not be TERMINATOR_CHAR or IGNORE_CHAR.
void log_if_overflowed(const char *tag) const
Log the shared "line dropped" warning when the last feed() overflowed.
void discard_line()
Drop everything up to and including the next terminator.
void log_line_dropped(const char *tag, size_t max_len)
Logs the shared "line dropped" warning; out of line to keep each caller small.