47 this->data[this->
pos++] =
'\n';
48 }
else if (this->size > 0) {
50 this->data[this->size - 1] =
'\n';
54 void HOT
write_header(uint8_t level,
const char *tag,
int line,
const char *thread_name) {
56 if (this->
pos + MAX_HEADER_SIZE > this->size)
59 char *p = this->current_();
62 this->write_ansi_color_(p, level);
71 *p++ =
static_cast<char>(
progmem_read_byte(
reinterpret_cast<const uint8_t *
>(&LOG_LEVEL_LETTER_CHARS[level])));
78 this->copy_string_(p, tag);
83 if (line > 999) [[unlikely]] {
84 write_digit(p, line, 1000);
86 write_digit(p, line, 100);
87 write_digit(p, line, 10);
91#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST)
93 if (thread_name !=
nullptr) {
94 this->write_ansi_color_(p, 1);
96 this->copy_string_(p, thread_name);
98 this->write_ansi_color_(p, level);
108 this->format_vsnprintf_(
format, args);
113 this->format_vsnprintf_p_(
format, args);
118 const uint16_t available = this->remaining_();
119 const uint16_t copy_len = (text_length < available) ? text_length : available;
121 memcpy(this->current_(), text, copy_len);
122 this->
pos += copy_len;
128 bool full_()
const {
return this->
pos >= this->
size; }
129 uint16_t remaining_()
const {
return this->size - this->
pos; }
130 char *current_() {
return this->data + this->
pos; }
132 this->write_ansi_reset_();
134 this->data[this->full_() ? this->size - 1 : this->
pos] =
'\0';
137 static constexpr uint16_t ANSI_RESET_LEN = 4;
138 void write_ansi_reset_() {
139 if (this->remaining_() >= ANSI_RESET_LEN) {
140 char *p = this->current_();
145 this->
pos += ANSI_RESET_LEN;
148 void strip_trailing_newlines_() {
149 while (this->
pos > 0 && this->data[this->
pos - 1] ==
'\n')
152 void process_vsnprintf_result_(
int ret) {
155 const uint16_t rem = this->remaining_();
156 this->
pos += (ret >= rem) ? (rem - 1) :
static_cast<uint16_t
>(
ret);
157 this->strip_trailing_newlines_();
159 void format_vsnprintf_(
const char *
format, va_list args) {
162 this->process_vsnprintf_result_(vsnprintf(this->current_(), this->remaining_(),
format, args));
165 void format_vsnprintf_p_(PGM_P
format, va_list args) {
168 this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(),
format, args));
172 static inline void ESPHOME_ALWAYS_INLINE write_digit(
char *&p,
int &value,
int divisor) {
174 while (value >= divisor) {
182 void write_ansi_color_(
char *&p, uint8_t level) {
188 *p++ = (level == 1) ?
'1' :
'0';
191 *p++ =
static_cast<char>(
progmem_read_byte(
reinterpret_cast<const uint8_t *
>(&LOG_LEVEL_COLOR_DIGIT[level])));
196 void copy_string_(
char *&p,
const char *str) {
199 for (
size_t i = 0; i < MAX_TAG_LENGTH; i++) {
200 const char c =
static_cast<char>(
progmem_read_byte(
reinterpret_cast<const uint8_t *
>(str + i)));
206 const size_t len = strlen(str);