ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
unicode.cpp
Go to the documentation of this file.
1#include "unicode.h"
2
3namespace esphome::unicode {
4
5uint32_t extract_unicode_codepoint(const char *utf8_str, size_t *length) {
6 // Safely cast to uint8_t* for correct bitwise operations on bytes
7 const uint8_t *current = reinterpret_cast<const uint8_t *>(utf8_str);
8 uint32_t code_point = 0;
9 uint8_t c1 = *current++;
10
11 // check for end of string
12 if (c1 == 0) {
13 *length = 0;
14 return 0;
15 }
16
17 // --- 1-Byte Sequence: 0xxxxxxx (ASCII) ---
18 if (c1 < 0x80) {
19 // Valid ASCII byte.
20 code_point = c1;
21 // Optimization: No need to check for continuation bytes.
22 }
23 // --- 2-Byte Sequence: 110xxxxx 10xxxxxx ---
24 else if ((c1 & 0xE0) == 0xC0) {
25 uint8_t c2 = *current++;
26
27 // Error Check 1: Check if c2 is a valid continuation byte (10xxxxxx)
28 if ((c2 & 0xC0) != 0x80) {
29 *length = 0;
30 return 0;
31 }
32
33 code_point = (c1 & 0x1F) << 6;
34 code_point |= (c2 & 0x3F);
35
36 // Error Check 2: Overlong check (2-byte must be > 0x7F)
37 if (code_point <= 0x7F) {
38 *length = 0;
39 return 0;
40 }
41 }
42 // --- 3-Byte Sequence: 1110xxxx 10xxxxxx 10xxxxxx ---
43 else if ((c1 & 0xF0) == 0xE0) {
44 uint8_t c2 = *current++;
45 uint8_t c3 = *current++;
46
47 // Error Check 1: Check continuation bytes
48 if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
49 *length = 0;
50 return 0;
51 }
52
53 code_point = (c1 & 0x0F) << 12;
54 code_point |= (c2 & 0x3F) << 6;
55 code_point |= (c3 & 0x3F);
56
57 // Error Check 2: Overlong check (3-byte must be > 0x7FF)
58 // Also check for surrogates (0xD800-0xDFFF)
59 if (code_point <= 0x7FF || (code_point >= 0xD800 && code_point <= 0xDFFF)) {
60 *length = 0;
61 return 0;
62 }
63 }
64 // --- 4-Byte Sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx ---
65 else if ((c1 & 0xF8) == 0xF0) {
66 uint8_t c2 = *current++;
67 uint8_t c3 = *current++;
68 uint8_t c4 = *current++;
69
70 // Error Check 1: Check continuation bytes
71 if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80) || ((c4 & 0xC0) != 0x80)) {
72 *length = 0;
73 return 0;
74 }
75
76 code_point = (c1 & 0x07) << 18;
77 code_point |= (c2 & 0x3F) << 12;
78 code_point |= (c3 & 0x3F) << 6;
79 code_point |= (c4 & 0x3F);
80
81 // Error Check 2: Overlong check (4-byte must be > 0xFFFF)
82 // Also check for valid Unicode range (must be <= 0x10FFFF)
83 if (code_point <= 0xFFFF || code_point > 0x10FFFF) {
84 *length = 0;
85 return 0;
86 }
87 }
88 // --- Invalid leading byte (e.g., 10xxxxxx or 11111xxx) ---
89 else {
90 *length = 0;
91 return 0;
92 }
93 *length = current - reinterpret_cast<const uint8_t *>(utf8_str);
94 return code_point;
95}
96
97} // namespace esphome::unicode
uint32_t extract_unicode_codepoint(const char *utf8_str, size_t *length)
Attempt to extract a 32 bit Unicode codepoint from a UTF-8 string.
Definition unicode.cpp:5
static void uint32_t
uint16_t length
Definition tt21100.cpp:0