ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
homeassistant.h
Go to the documentation of this file.
1#pragma once
2
3#include <cctype>
4
7
9
11template<typename C> bool emit_utf8(uint32_t code_point, C &on_char) {
12 if (code_point == 0 || code_point > 0x10FFFF)
13 return false;
14 if (code_point < 0x80) {
15 on_char(static_cast<char>(code_point));
16 } else if (code_point < 0x800) {
17 on_char(static_cast<char>(0xC0 | (code_point >> 6)));
18 on_char(static_cast<char>(0x80 | (code_point & 0x3F)));
19 } else if (code_point < 0x10000) {
20 on_char(static_cast<char>(0xE0 | (code_point >> 12)));
21 on_char(static_cast<char>(0x80 | ((code_point >> 6) & 0x3F)));
22 on_char(static_cast<char>(0x80 | (code_point & 0x3F)));
23 } else {
24 on_char(static_cast<char>(0xF0 | (code_point >> 18)));
25 on_char(static_cast<char>(0x80 | ((code_point >> 12) & 0x3F)));
26 on_char(static_cast<char>(0x80 | ((code_point >> 6) & 0x3F)));
27 on_char(static_cast<char>(0x80 | (code_point & 0x3F)));
28 }
29 return true;
30}
31
39template<typename C, typename O> bool parse_python_list(StringRef src, C &&on_char, O &&on_item) {
40 const char *pos = src.c_str();
41 const char *const end = pos + src.size();
42 auto skip_spaces = [&]() {
43 while (pos < end && *pos == ' ')
44 pos++;
45 };
46
47 skip_spaces();
48 if (pos == end || *pos != '[')
49 return false;
50 pos++;
51 skip_spaces();
52 if (pos < end && *pos == ']') {
53 pos++;
54 } else {
55 while (true) {
56 skip_spaces();
57 // An enum member is shown as <Name.MEMBER: 'value'>; the quoted value is the item
58 const bool enum_member = pos < end && *pos == '<';
59 if (enum_member) {
60 pos++;
61 while (pos < end && (std::isalnum(static_cast<unsigned char>(*pos)) || *pos == '_' || *pos == '.'))
62 pos++;
63 if (pos == end || *pos != ':')
64 return false;
65 pos++;
66 skip_spaces();
67 }
68 if (pos == end || (*pos != '\'' && *pos != '"'))
69 return false;
70 const char quote = *pos++;
71 while (true) {
72 if (pos == end)
73 return false;
74 const char c = *pos++;
75 if (c == quote)
76 break;
77 if (c != '\\') {
78 on_char(c);
79 continue;
80 }
81 if (pos == end)
82 return false;
83 const char escape = *pos++;
84 switch (escape) {
85 case '\\':
86 case '\'':
87 case '"':
88 on_char(escape);
89 break;
90 case 'n':
91 on_char('\n');
92 break;
93 case 'r':
94 on_char('\r');
95 break;
96 case 't':
97 on_char('\t');
98 break;
99 case 'x':
100 case 'u':
101 case 'U': {
102 const size_t digits = escape == 'x' ? 2 : (escape == 'u' ? 4 : 8);
103 if (static_cast<size_t>(end - pos) < digits)
104 return false;
105 auto code_point = parse_hex<uint32_t>(pos, digits);
106 if (!code_point.has_value() || !emit_utf8(*code_point, on_char))
107 return false;
108 pos += digits;
109 break;
110 }
111 default:
112 return false;
113 }
114 }
115 if (enum_member) {
116 skip_spaces();
117 if (pos == end || *pos != '>')
118 return false;
119 pos++;
120 }
121 on_item();
122 skip_spaces();
123 if (pos == end)
124 return false;
125 const char separator = *pos++;
126 if (separator == ']')
127 break;
128 if (separator != ',')
129 return false;
130 }
131 }
132 skip_spaces();
133 return pos == end;
134}
135
136} // namespace esphome::homeassistant
StringRef is a reference to a string owned by something else.
Definition string_ref.h:31
bool parse_python_list(StringRef src, C &&on_char, O &&on_item)
Walk a list attribute as Home Assistant sends it: the Python repr of a list of strings,...
bool emit_utf8(uint32_t code_point, C &on_char)
Emit the UTF-8 encoding of a code point. Rejects NUL, which would end the item early.
size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count)
Parse bytes from a hex-encoded string into a byte array.
Definition helpers.cpp:370
size_t size_t pos
Definition helpers.h:1179
const void * src
Definition hal.h:68
static void uint32_t
uint8_t end[39]
Definition sun_gtil2.cpp:17