8#include <botan/internal/charset.h>
10#include <botan/exceptn.h>
11#include <botan/internal/loadstor.h>
17void append_utf8_for(std::string& s, uint32_t c) {
18 if(c >= 0xD800 && c < 0xE000) {
23 const uint8_t b0 =
static_cast<uint8_t
>(c);
24 s.push_back(
static_cast<char>(b0));
25 }
else if(c <= 0x7FF) {
26 const uint8_t b0 = 0xC0 |
static_cast<uint8_t
>(c >> 6);
27 const uint8_t b1 = 0x80 |
static_cast<uint8_t
>(c & 0x3F);
28 s.push_back(
static_cast<char>(b0));
29 s.push_back(
static_cast<char>(b1));
30 }
else if(c <= 0xFFFF) {
31 const uint8_t b0 = 0xE0 |
static_cast<uint8_t
>(c >> 12);
32 const uint8_t b1 = 0x80 |
static_cast<uint8_t
>((c >> 6) & 0x3F);
33 const uint8_t b2 = 0x80 |
static_cast<uint8_t
>(c & 0x3F);
34 s.push_back(
static_cast<char>(b0));
35 s.push_back(
static_cast<char>(b1));
36 s.push_back(
static_cast<char>(b2));
37 }
else if(c <= 0x10FFFF) {
38 const uint8_t b0 = 0xF0 |
static_cast<uint8_t
>(c >> 18);
39 const uint8_t b1 = 0x80 |
static_cast<uint8_t
>((c >> 12) & 0x3F);
40 const uint8_t b2 = 0x80 |
static_cast<uint8_t
>((c >> 6) & 0x3F);
41 const uint8_t b3 = 0x80 |
static_cast<uint8_t
>(c & 0x3F);
42 s.push_back(
static_cast<char>(b0));
43 s.push_back(
static_cast<char>(b1));
44 s.push_back(
static_cast<char>(b2));
45 s.push_back(
static_cast<char>(b3));
54 auto read_continuation = [&]() -> uint32_t {
55 if(pos >= utf8.size()) {
58 const uint8_t b =
static_cast<uint8_t
>(utf8[pos++]);
59 if((b & 0xC0) != 0x80) {
65 if(pos >= utf8.size()) {
68 const uint8_t lead =
static_cast<uint8_t
>(utf8[pos++]);
73 }
else if((lead & 0xE0) == 0xC0) {
74 c = (lead & 0x1F) << 6;
75 c |= read_continuation();
79 }
else if((lead & 0xF0) == 0xE0) {
80 c = (lead & 0x0F) << 12;
81 c |= read_continuation() << 6;
82 c |= read_continuation();
86 }
else if((lead & 0xF8) == 0xF0) {
87 c = (lead & 0x07) << 18;
88 c |= read_continuation() << 12;
89 c |= read_continuation() << 6;
90 c |= read_continuation();
99 throw Decoding_Error(
"UTF-8 sequence encodes value outside Unicode range");
101 if(c >= 0xD800 && c < 0xE000) {
102 throw Decoding_Error(
"UTF-8 sequence encodes surrogate code point");
111 while(pos < utf8.size()) {
122 if(ucs2.size() % 2 != 0) {
126 const size_t chars = ucs2.size() / 2;
129 for(
size_t i = 0; i != chars; ++i) {
131 append_utf8_for(s, c);
138 std::vector<uint8_t> out;
139 out.reserve(utf8.size() * 2);
142 while(pos < utf8.size()) {
147 const uint16_t val =
static_cast<uint16_t
>(c);
156 if(ucs4.size() % 4 != 0) {
160 const size_t chars = ucs4.size() / 4;
163 for(
size_t i = 0; i != chars; ++i) {
165 append_utf8_for(s, c);
172 std::vector<uint8_t> out;
173 out.reserve(utf8.size() * 4);
176 while(pos < utf8.size()) {
192 for(
const uint8_t b : chars) {
193 append_utf8_for(s,
static_cast<uint32_t
>(b));
199 const uint8_t b =
static_cast<uint8_t
>(c);
200 return b < 0x20 || b == 0x7F;
204 return cp < 0x20 || (cp >= 0x7F && cp <= 0x9F);
209 out.reserve(utf8.size());
211 const auto append_hex_escape = [&](uint8_t b) {
218 while(pos < utf8.size()) {
219 const size_t start = pos;
226 append_hex_escape(
static_cast<uint8_t
>(utf8[start]));
232 for(
size_t i = start; i < pos; ++i) {
233 append_hex_escape(
static_cast<uint8_t
>(utf8[i]));
236 out.append(utf8.substr(start, pos - start));
249 }
else if(c ==
'\n') {
251 }
else if(c ==
'\r') {
254 const auto b =
static_cast<uint8_t
>(c);
constexpr uint8_t get_byte(T input)
std::string format_char_for_display(char c)
constexpr char nibble_to_hex(uint8_t b)
bool is_unicode_control_char(uint32_t cp)
bool is_valid_utf8(std::string_view utf8)
std::string latin1_to_utf8(std::span< const uint8_t > chars)
std::vector< uint8_t > utf8_to_ucs4(std::string_view utf8)
bool is_ascii_control_char(char c)
uint32_t next_utf8_codepoint(std::string_view utf8, size_t &pos)
std::string ucs2_to_utf8(std::span< const uint8_t > ucs2)
std::string ucs4_to_utf8(std::span< const uint8_t > ucs4)
std::string escape_control_chars(std::string_view utf8)
constexpr auto load_be(ParamTs &&... params)
std::vector< uint8_t > utf8_to_ucs2(std::string_view utf8)