ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
line_reader.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <type_traits>
6
7namespace esphome {
8
11void log_line_dropped(const char *tag, size_t max_len);
12
15template<size_t N, char TERMINATOR_CHAR = '\n', char IGNORE_CHAR = '\r'> class LineReader {
16 // pos_ is the length so far; N means "overflowed on this byte", N + 1 "dropping up to the terminator"
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");
20
21 public:
23 char *feed(uint8_t c) {
24 size_t len = 0;
25 return this->feed(c, len);
26 }
27
29 char *feed(uint8_t c, size_t &len) {
30 pos_t pos = this->pos_;
31 if (pos == N) {
32 this->pos_ = pos = N + 1;
33 }
34 if (c == static_cast<uint8_t>(IGNORE_CHAR)) {
35 return nullptr;
36 }
37 if (c == static_cast<uint8_t>(TERMINATOR_CHAR)) {
38 this->pos_ = 0;
39 if (pos > N) {
40 return nullptr;
41 }
42 this->buf_[pos] = '\0';
43 len = pos;
44 return this->buf_;
45 }
46 if (pos < N - 1) {
47 this->buf_[pos] = static_cast<char>(c);
48 this->pos_ = pos + 1;
49 } else if (pos == N - 1) {
50 this->pos_ = N;
51 }
52 return nullptr;
53 }
54
56 size_t length() const { return this->pos_ < N ? this->pos_ : 0; }
57
60 const char *partial() {
61 this->buf_[this->end_()] = '\0';
62 return this->buf_;
63 }
64
66 bool overflowed() const { return this->pos_ == N; }
67
69 void log_if_overflowed(const char *tag) const {
70 if (this->overflowed()) {
71 log_line_dropped(tag, N - 1);
72 }
73 }
74
76 void reset() { this->pos_ = 0; }
77
79 void restart_with(uint8_t c) {
80 this->buf_[0] = static_cast<char>(c);
81 this->pos_ = 1;
82 }
83
85 void discard_line() { this->pos_ = N + 1; }
86
87 protected:
88 pos_t end_() const {
89 if (this->pos_ < N) {
90 return this->pos_;
91 }
92 return this->pos_ == N ? N - 1 : 0;
93 }
94
95 char buf_[N];
96 pos_t pos_{0};
97};
98
99} // namespace esphome
Collects bytes into NUL terminated lines of up to N - 1 characters; IGNORE_CHAR bytes are skipped and...
Definition line_reader.h:15
const char * partial()
The partial line, NUL terminated, for prompts with no line end; the first N - 1 characters on the byt...
Definition line_reader.h:60
bool overflowed() const
True only right after the feed() that found the line too long; the rest of that line is then dropped.
Definition line_reader.h:66
size_t length() const
Length of the partial line; 0 after a line is returned and while an overlong line is dropped.
Definition line_reader.h:56
char * feed(uint8_t c)
Feed one byte; returns the completed line (empty lines included), valid until the next call,...
Definition line_reader.h:23
char * feed(uint8_t c, size_t &len)
As feed(c), and sets len to the line length when a line is returned.
Definition line_reader.h:29
void reset()
Forget the partial line and start a new one with the next byte.
Definition line_reader.h:76
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.
Definition line_reader.h:79
void log_if_overflowed(const char *tag) const
Log the shared "line dropped" warning when the last feed() overflowed.
Definition line_reader.h:69
pos_t end_() const
Definition line_reader.h:88
void discard_line()
Drop everything up to and including the next terminator.
Definition line_reader.h:85
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.
const void size_t len
Definition hal.h:68
size_t size_t pos
Definition helpers.h:1255