16static constexpr size_t Max = 4;
17static constexpr char32_t BOM = 0xfeff;
18static constexpr std::string_view
Bom =
"\xef\xbb\xbf";
19static constexpr char32_t EoF
20 = (char32_t)std::istream::traits_type::eof();
21static constexpr char32_t Null = 0;
22static constexpr char32_t Invalid = 0x110000;
27 if ((c &
char8_t(0b10000000)) ==
char8_t(0b00000000))
return 1;
28 if ((c &
char8_t(0b11100000)) ==
char8_t(0b11000000))
return 2;
29 if ((c &
char8_t(0b11110000)) ==
char8_t(0b11100000))
return 3;
30 if ((c &
char8_t(0b11111000)) ==
char8_t(0b11110000))
return 4;
35constexpr char32_t append(
char32_t c,
char8_t b)
noexcept {
return (c << 6) | (b & 0b00111111); }
38constexpr char32_t first(
char32_t c,
char32_t num)
noexcept {
return c & (0b00011111 >> (num - 2)); }
43 case 1:
return 0x000000;
44 case 2:
return 0x000080;
45 case 3:
return 0x000800;
46 case 4:
return 0x010000;
47 default:
return 0x110000;
54 return (c &
char8_t(0b11000000)) == char8_t(0b10000000) ? (c & char8_t(0b00111111)) : char8_t(-1);
58constexpr bool is_scalar_value(
char32_t c)
noexcept {
return c <= 0x10ffff && !(0xd800 <= c && c <= 0xdfff); }
64inline char32_t decode(std::istream& is) {
65 char32_t result = is.get();
66 if (result ==
EoF)
return result;
70 case 1:
return result;
74 for (
size_t i = 1; i != n; ++i)
75 if (
auto x =
is_valid234(is.get()); x !=
char8_t(-1))
92inline char32_t decode(std::string_view str,
size_t& i)
noexcept {
93 if (i >= str.size())
return EoF;
95 auto c8 = char8_t(str[i]);
97 char32_t result = char32_t(c8);
98 if (n == 0 || i + n > str.size())
return ++i,
Invalid;
99 if (n == 1)
return ++i, result;
102 for (
size_t j = 1; j != n; ++j) {
104 if (x ==
char8_t(-1))
return ++i,
Invalid;
122bool encode(std::ostream& os,
char32_t c32);
142constexpr bool isascii(
char32_t c)
noexcept {
return c <= 0x7F; }
143constexpr bool isupper(
char32_t c)
noexcept {
return 'A' <= c && c <=
'Z'; }
144constexpr bool islower(
char32_t c)
noexcept {
return 'a' <= c && c <=
'z'; }
145constexpr bool isdigit(
char32_t c)
noexcept {
return '0' <= c && c <=
'9'; }
148constexpr bool isxdigit(
char32_t c)
noexcept {
return isdigit(c) || (
'A' <= c && c <=
'F') || (
'a' <= c && c <=
'f'); }
149constexpr bool iscntrl(
char32_t c)
noexcept {
return c <= 0x1F || c == 0x7F; }
150constexpr bool isblank(
char32_t c)
noexcept {
return c ==
' ' || c ==
'\t'; }
151constexpr bool isspace(
char32_t c)
noexcept {
return c ==
' ' || (
'\t' <= c && c <=
'\r'); }
152constexpr bool isgraph(
char32_t c)
noexcept {
return '!' <= c && c <=
'~'; }
153constexpr bool isprint(
char32_t c)
noexcept {
return ' ' <= c && c <=
'~'; }
155constexpr char32_t tolower(
char32_t c)
noexcept {
return isupper(c) ? c -
'A' +
'a' : c; }
156constexpr char32_t toupper(
char32_t c)
noexcept {
return islower(c) ? c -
'a' +
'A' : c; }
158constexpr bool isrange(
char32_t c,
char32_t begin,
char32_t finis)
noexcept {
return begin <= c && c <= finis; }
159constexpr auto isrange(
char32_t begin,
char32_t finis)
noexcept {
160 return [=](
char32_t c) {
return isrange(c, begin, finis); };
168constexpr bool any(
char32_t c,
char32_t d)
noexcept {
return c == d; }
170constexpr bool any(
char32_t c,
char32_t d, T... args)
noexcept {
171 return c == d || any(c, args...);
178constexpr auto any(T... args)
noexcept {
179 return [=](
char32_t c) {
return detail::any(c, args...); };
UTF-8 helpers for decoding byte streams, encoding char32_t values, and running ASCII-style character ...
constexpr bool ispunct(char32_t c) noexcept
static constexpr char32_t Invalid
Sentinel returned by decode for malformed UTF-8.
constexpr bool isprint(char32_t c) noexcept
static constexpr char32_t BOM
Byte Order Mark.
static constexpr std::string_view Bom
BOM as UTF-8 bytes.
constexpr size_t num_bytes(char8_t c) noexcept
Returns the expected number of bytes for an UTF-8 char sequence by inspecting the first byte.
constexpr bool isbdigit(char32_t c) noexcept
Is binary digit?
constexpr char32_t first(char32_t c, char32_t num) noexcept
Get relevant bits of first UTF-8 byte c of a multi-byte sequence consisting of num bytes.
constexpr bool iscntrl(char32_t c) noexcept
constexpr bool isupper(char32_t c) noexcept
char32_t decode(std::istream &is)
Decodes the next UTF-8 sequence from is into a single char32_t.
constexpr bool isxdigit(char32_t c) noexcept
bool encode(std::ostream &os, char32_t c32)
Encodes c32 as UTF-8 and writes the resulting bytes to os.
constexpr bool isblank(char32_t c) noexcept
constexpr char8_t is_valid234(char8_t c) noexcept
Is the 2nd, 3rd, or 4th byte of an UTF-8 byte sequence valid?
constexpr bool isalpha(char32_t c) noexcept
constexpr bool isodigit(char32_t c) noexcept
Is octal digit?
constexpr char32_t min_code_point(size_t num) noexcept
Minimum Unicode scalar value representable in an UTF-8 sequence of num bytes.
static constexpr size_t Max
Maximal number of char8_ts of an UTF-8 byte sequence.
constexpr bool isascii(char32_t c) noexcept
static constexpr char32_t EoF
End of stream sentinel returned by decode.
constexpr char32_t append(char32_t c, char8_t b) noexcept
Append b to c for converting UTF-8 to UTF-32.
constexpr bool isgraph(char32_t c) noexcept
constexpr bool isspace(char32_t c) noexcept
constexpr bool isdigit(char32_t c) noexcept
constexpr bool isrange(char32_t c, char32_t begin, char32_t finis) noexcept
Is c within [begin, finis]?
constexpr bool is_scalar_value(char32_t c) noexcept
Is c a valid Unicode scalar value?
constexpr bool islower(char32_t c) noexcept
size_t num_code_points(std::string_view str) noexcept
Number of UTF-8 code points in str.
constexpr char32_t toupper(char32_t c) noexcept
constexpr char32_t tolower(char32_t c) noexcept
static constexpr char32_t Null
U+0000 NULL returned unchanged by decode.
constexpr auto any(T... args) noexcept
Build a predicate that checks whether a code point matches any of the given values.
constexpr bool isalnum(char32_t c) noexcept
friend std::ostream & operator<<(std::ostream &os, Char32 c)
constexpr Char32(char32_t c) noexcept