18static constexpr size_t Max = 4;
19static constexpr char32_t BOM = 0xfeff;
20static constexpr std::string_view
Bom =
"\xef\xbb\xbf";
21static constexpr char32_t EoF
22 = (char32_t)std::istream::traits_type::eof();
23static constexpr char32_t Null = 0;
24static constexpr char32_t Invalid = 0x110000;
29 if ((c &
char8_t(0b10000000)) ==
char8_t(0b00000000))
return 1;
30 if ((c &
char8_t(0b11100000)) ==
char8_t(0b11000000))
return 2;
31 if ((c &
char8_t(0b11110000)) ==
char8_t(0b11100000))
return 3;
32 if ((c &
char8_t(0b11111000)) ==
char8_t(0b11110000))
return 4;
37constexpr char32_t append(
char32_t c,
char8_t b)
noexcept {
return (c << 6) | (b & 0b00111111); }
40constexpr char32_t first(
char32_t c,
char32_t num)
noexcept {
return c & (0b00011111 >> (num - 2)); }
45 case 1:
return 0x000000;
46 case 2:
return 0x000080;
47 case 3:
return 0x000800;
48 case 4:
return 0x010000;
49 default:
return 0x110000;
54constexpr bool is_scalar_value(
char32_t c)
noexcept {
return c <= 0x10ffff && !(0xd800 <= c && c <= 0xdfff); }
59 return (c &
char8_t(0b11000000)) == char8_t(0b10000000) ? (c & char8_t(0b00111111)) : char8_t(-1);
66inline char32_t decode(std::istream& is) {
67 char32_t result = is.get();
68 if (result ==
EoF)
return result;
72 case 1:
return result;
76 for (
size_t i = 1; i != n; ++i)
77 if (
auto x =
is_valid234(is.get()); x !=
char8_t(-1))
94inline char32_t decode(std::string_view str,
size_t& i)
noexcept {
95 if (i >= str.size())
return EoF;
97 char32_t result = char8_t(str[i]);
99 if (n == 0 || i + n > str.size())
return ++i,
Invalid;
100 if (n == 1)
return ++i, result;
103 for (
size_t j = 1; j != n; ++j) {
105 if (x ==
char8_t(-1))
return ++i,
Invalid;
121 for (
size_t i = 0, e = str.size(); i < e; ++res)
128inline std::ostream& ao(std::ostream& os,
char32_t c32,
char32_t a = 0b00111111,
char32_t o = 0b10000000) {
129 return os << char((c32 & a) | o);
136inline bool encode(std::ostream& os,
char32_t c32) {
139 if (c32 <= 0x00007f) { ao(os, c32 , 0b11111111, 0b00000000);
return true; }
140 if (c32 <= 0x0007ff) { ao(ao(os, c32 >> 6, 0b00011111, 0b11000000), c32);
return true; }
141 if (c32 <= 0x00ffff) { ao(ao(ao(os, c32 >> 12, 0b00001111, 0b11100000), c32 >> 6), c32);
return true; }
142 if (c32 <= 0x10ffff) { ao(ao(ao(ao(os, c32 >> 18, 0b00000111, 0b11110000), c32 >> 12), c32 >> 6), c32);
return true; }
166inline bool isalnum (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isalnum (c) :
false; }
167inline bool isalpha (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isalpha (c) :
false; }
168inline bool isblank (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isblank (c) :
false; }
169inline bool iscntrl (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::iscntrl (c) :
false; }
170inline bool isdigit (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isdigit (c) :
false; }
171inline bool isgraph (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isgraph (c) :
false; }
172inline bool islower (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::islower (c) :
false; }
173inline bool isprint (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isprint (c) :
false; }
174inline bool ispunct (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::ispunct (c) :
false; }
175inline bool isspace (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isspace (c) :
false; }
176inline bool isupper (
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isupper (c) :
false; }
177inline bool isxdigit(
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::isxdigit(c) :
false; }
178inline bool isascii (
char32_t c)
noexcept {
return c <= 0x7F; }
179inline char32_t tolower(
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::tolower(c) : c; }
180inline char32_t toupper(
char32_t c)
noexcept {
return (c & ~0xFF) == 0 ? std::toupper(c) : c; }
183constexpr bool isrange(
char32_t c,
char32_t begin,
char32_t finis)
noexcept {
return begin <= c && c <= finis; }
184constexpr auto isrange(
char32_t begin,
char32_t finis)
noexcept {
return [=](
char32_t c) {
return isrange(c, begin, finis); }; }
194inline bool _any(
char32_t c,
char32_t d) {
return c == d; }
196inline bool _any(
char32_t c,
char32_t d, T... args) {
197 return c == d ||
_any(c, args...);
200inline auto any(T... args) {
201 return [=](
char32_t c) {
return _any(c, args...); };
UTF-8 helpers for decoding byte streams, encoding char32_t values, and running ASCII-style character ...
bool isalnum(char32_t c) noexcept
bool isdigit(char32_t c) noexcept
static constexpr char32_t Invalid
Sentinel returned by decode for malformed UTF-8.
bool _any(char32_t c, char32_t d)
static constexpr char32_t BOM
Byte Order Mark.
char32_t tolower(char32_t c) noexcept
static constexpr std::string_view Bom
BOM as UTF-8 bytes.
bool isascii(char32_t c) noexcept
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.
char32_t decode(std::istream &is)
Decodes the next UTF-8 sequence from is into a single char32_t.
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 char8_t is_valid234(char8_t c) noexcept
Is the 2nd, 3rd, or 4th byte of an UTF-8 byte sequence valid?
bool isprint(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.
bool isblank(char32_t c) noexcept
bool isalpha(char32_t c) noexcept
static constexpr size_t Max
Maximal number of char8_ts of an UTF-8 byte sequence.
bool isupper(char32_t c) noexcept
char32_t toupper(char32_t c) noexcept
bool iscntrl(char32_t c) noexcept
bool ispunct(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 isrange(char32_t c, char32_t begin, char32_t finis) noexcept
Is c within [begin, finis]?
bool islower(char32_t c) noexcept
constexpr bool is_scalar_value(char32_t c) noexcept
Is c a valid Unicode scalar value?
size_t num_code_points(std::string_view str) noexcept
Number of UTF-8 code points in str.
bool isspace(char32_t c) noexcept
bool isgraph(char32_t c) noexcept
static constexpr char32_t Null
U+0000 NULL returned unchanged by decode.
friend std::ostream & operator<<(std::ostream &os, Char32 c)