| 223 | }; |
| 224 | |
| 225 | static std::string codepoint_to_utf8(uint32_t cp) { |
| 226 | std::string result; |
| 227 | if (/* 0x00 <= cp && */ cp <= 0x7f) { |
| 228 | result.push_back(cp); |
| 229 | } |
| 230 | else if (0x80 <= cp && cp <= 0x7ff) { |
| 231 | result.push_back(0xc0 | ((cp >> 6) & 0x1f)); |
| 232 | result.push_back(0x80 | (cp & 0x3f)); |
| 233 | } |
| 234 | else if (0x800 <= cp && cp <= 0xffff) { |
| 235 | result.push_back(0xe0 | ((cp >> 12) & 0x0f)); |
| 236 | result.push_back(0x80 | ((cp >> 6) & 0x3f)); |
| 237 | result.push_back(0x80 | (cp & 0x3f)); |
| 238 | } |
| 239 | else if (0x10000 <= cp && cp <= 0x10ffff) { |
| 240 | result.push_back(0xf0 | ((cp >> 18) & 0x07)); |
| 241 | result.push_back(0x80 | ((cp >> 12) & 0x3f)); |
| 242 | result.push_back(0x80 | ((cp >> 6) & 0x3f)); |
| 243 | result.push_back(0x80 | (cp & 0x3f)); |
| 244 | } |
| 245 | else { |
| 246 | throw std::invalid_argument("invalid codepoint"); |
| 247 | } |
| 248 | return result; |
| 249 | } |
| 250 | |
| 251 | static std::string codepoints_to_utf8(const std::vector<uint32_t> & cps) { |
| 252 | std::string result; |