REAL
Regular Expression Algorithmic Library — constexpr C++20 regex
Loading...
Searching...
No Matches
utf8.hpp
Go to the documentation of this file.
1
9#ifndef REAL_UTF8_HPP
10#define REAL_UTF8_HPP
11
12// Internal — do not include directly.
13// Users: #include <real/real.hpp> (or the documented opt-ins <real/dfa.hpp>, <real/std/regex.hpp>).
14
15#include "real/version.hpp"
16
17#include <cstddef>
18#include <cstdint>
19#include <string_view>
20
21namespace real::detail {
22
25 {
26 std::uint32_t cp {};
27 std::size_t length {};
28 bool valid {};
29 };
30
44 constexpr decoded_codepoint decode_codepoint_strict(std::string_view text,
45 std::size_t pos)
46 {
47 const auto lead {static_cast<std::uint8_t>(text[pos])};
48 if (lead < 0x80U) {
49 return {.cp = lead, .length = 1, .valid = true}; // ASCII
50 }
51 std::size_t length {};
52 std::uint32_t cp {};
53 std::uint32_t min_cp {}; // smallest code point this length may legally encode (overlong guard)
54 if ((lead & 0xE0U) == 0xC0U) {
55 length = 2;
56 cp = lead & 0x1FU;
57 min_cp = 0x80U;
58 }
59 else if ((lead & 0xF0U) == 0xE0U) {
60 length = 3;
61 cp = lead & 0x0FU;
62 min_cp = 0x800U;
63 }
64 else if ((lead & 0xF8U) == 0xF0U) {
65 length = 4;
66 cp = lead & 0x07U;
67 min_cp = 0x10000U;
68 }
69 else {
70 return {.cp = 0, .length = 1, .valid = false}; // lone continuation, or an invalid lead (0xF8–0xFF)
71 }
72 for (std::size_t i = 1; i < length; ++i) {
73 if (pos + i >= text.size()) {
74 return {.cp = 0, .length = i, .valid = false}; // truncated sequence
75 }
76 const auto byte {static_cast<std::uint8_t>(text[pos + i])};
77 if ((byte & 0xC0U) != 0x80U) {
78 return {.cp = 0, .length = i, .valid = false}; // expected a continuation byte
79 }
80 cp = (cp << 6U) | (byte & 0x3FU);
81 }
82 if (cp < min_cp) {
83 return {.cp = cp, .length = length, .valid = false}; // overlong (covers 0xC0/0xC1 and E0/F0 …)
84 }
85 if (cp > 0x10FFFFU || (cp >= 0xD800U && cp <= 0xDFFFU)) {
86 return {.cp = cp, .length = length, .valid = false}; // out of range (incl. 0xF5+) or surrogate
87 }
88 return {.cp = cp, .length = length, .valid = true};
89 }
90
108 constexpr std::size_t codepoint_advance(std::string_view text,
109 std::size_t pos)
110 {
111 std::size_t i {pos + 1};
112 while (i < text.size() && (static_cast<unsigned>(static_cast<std::uint8_t>(text[i])) & 0xC0U) == 0x80U) {
113 ++i; // skip UTF-8 continuation bytes (10xxxxxx) to the next code-point boundary
114 }
115 return i - pos;
116 }
117} // namespace real::detail
118
119#endif // REAL_UTF8_HPP
constexpr decoded_codepoint decode_codepoint_strict(std::string_view text, std::size_t pos)
Strictly decodes and validates the UTF-8 sequence at text[pos].
Definition utf8.hpp:44
constexpr std::size_t codepoint_advance(std::string_view text, std::size_t pos)
Number of bytes from pos to the next code-point boundary, for advancing past an empty match during it...
Definition utf8.hpp:108
The result of a strict UTF-8 decode: the code point, its byte length, and validity.
Definition utf8.hpp:25
std::uint32_t cp
The decoded code point (meaningful only when valid).
Definition utf8.hpp:26
bool valid
Whether the sequence is a well-formed, canonical code point.
Definition utf8.hpp:28
std::size_t length
Bytes consumed by the sequence (1–4), or the bytes examined on failure.
Definition utf8.hpp:27
REAL's version macros and the C++20 language-standard guard.