vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
utf8.h
1#pragma once
2
3#include <cstddef>
4#include <string>
5#include <string_view>
6
7namespace Vkm::Engine::Utf8 {
8
10constexpr char32_t REPLACEMENT = 0xFFFD;
11
22inline char32_t next(std::string_view text, std::size_t& at) {
23 const unsigned char lead = static_cast<unsigned char>(text[at]);
24 if (lead < 0x80) {
25 ++at;
26 return lead;
27 }
28
29 std::size_t length = 0;
30 char32_t value = 0;
31 char32_t least = 0; // the smallest codepoint this length may carry
32 if ((lead & 0xE0) == 0xC0) {
33 length = 2;
34 value = lead & 0x1F;
35 least = 0x80;
36 } else if ((lead & 0xF0) == 0xE0) {
37 length = 3;
38 value = lead & 0x0F;
39 least = 0x800;
40 } else if ((lead & 0xF8) == 0xF0) {
41 length = 4;
42 value = lead & 0x07;
43 least = 0x10000;
44 } else {
45 ++at;
46 return REPLACEMENT;
47 }
48
49 if (at + length > text.size()) {
50 ++at;
51 return REPLACEMENT;
52 }
53 for (std::size_t i = 1; i < length; ++i) {
54 const unsigned char byte = static_cast<unsigned char>(text[at + i]);
55 if ((byte & 0xC0) != 0x80) {
56 ++at;
57 return REPLACEMENT;
58 }
59 value = (value << 6) | (byte & 0x3F);
60 }
61 if (value < least || value > 0x10FFFF || (value >= 0xD800 && value <= 0xDFFF)) {
62 ++at;
63 return REPLACEMENT;
64 }
65 at += length;
66 return value;
67}
68
76inline void append(std::string& text, char32_t codepoint) {
77 if (codepoint > 0x10FFFF || (codepoint >= 0xD800 && codepoint <= 0xDFFF)) codepoint = REPLACEMENT;
78
79 if (codepoint < 0x80) {
80 text.push_back(static_cast<char>(codepoint));
81 } else if (codepoint < 0x800) {
82 text.push_back(static_cast<char>(0xC0 | (codepoint >> 6)));
83 text.push_back(static_cast<char>(0x80 | (codepoint & 0x3F)));
84 } else if (codepoint < 0x10000) {
85 text.push_back(static_cast<char>(0xE0 | (codepoint >> 12)));
86 text.push_back(static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F)));
87 text.push_back(static_cast<char>(0x80 | (codepoint & 0x3F)));
88 } else {
89 text.push_back(static_cast<char>(0xF0 | (codepoint >> 18)));
90 text.push_back(static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F)));
91 text.push_back(static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F)));
92 text.push_back(static_cast<char>(0x80 | (codepoint & 0x3F)));
93 }
94}
95
106inline std::size_t previous(std::string_view text, std::size_t at) {
107 if (at == 0) return 0;
108 if (at > text.size()) at = text.size();
109 // At most three continuation bytes precede a lead byte.
110 std::size_t start = at - 1;
111 for (int step = 0; step < 3 && start > 0; ++step) {
112 if ((static_cast<unsigned char>(text[start]) & 0xC0) != 0x80) break;
113 --start;
114 }
115 std::size_t end = start;
116 next(text, end);
117 return end == at ? start : at - 1;
118}
119
120} // namespace Vkm::Engine::Utf8
float value()
Uniform float in [0, 1), from the per-thread generator.
Definition random.h:126