| 257 | } |
| 258 | |
| 259 | static uint32_t codepoint_from_utf8(const std::string & utf8, size_t & offset) { |
| 260 | assert(offset < utf8.size()); |
| 261 | if (!(utf8[offset + 0] & 0x80)) { |
| 262 | auto result = utf8[offset + 0]; |
| 263 | offset += 1; |
| 264 | return result; |
| 265 | } |
| 266 | else if (!(utf8[offset + 0] & 0x40)) { |
| 267 | throw std::invalid_argument("invalid character"); |
| 268 | } |
| 269 | else if (!(utf8[offset + 0] & 0x20)) { |
| 270 | if (offset + 1 >= utf8.size() || ! ((utf8[offset + 1] & 0xc0) == 0x80)) |
| 271 | throw std::invalid_argument("invalid character"); |
| 272 | auto result = ((utf8[offset + 0] & 0x1f) << 6) | (utf8[offset + 1] & 0x3f); |
| 273 | offset += 2; |
| 274 | return result; |
| 275 | } |
| 276 | else if (!(utf8[offset + 0] & 0x10)) { |
| 277 | if (offset + 2 >= utf8.size() || ! ((utf8[offset + 1] & 0xc0) == 0x80) || ! ((utf8[offset + 2] & 0xc0) == 0x80)) |
| 278 | throw std::invalid_argument("invalid character"); |
| 279 | auto result = ((utf8[offset + 0] & 0x0f) << 12) | ((utf8[offset + 1] & 0x3f) << 6) | (utf8[offset + 2] & 0x3f); |
| 280 | offset += 3; |
| 281 | return result; |
| 282 | } |
| 283 | else if (!(utf8[offset + 0] & 0x08)) { |
| 284 | if (offset + 3 >= utf8.size() || ! ((utf8[offset + 1] & 0xc0) == 0x80) || ! ((utf8[offset + 2] & 0xc0) == 0x80) || !((utf8[offset + 3] & 0xc0) == 0x80)) |
| 285 | throw std::invalid_argument("invalid character"); |
| 286 | auto result = ((utf8[offset + 0] & 0x07) << 18) | ((utf8[offset + 1] & 0x3f) << 12) | ((utf8[offset + 2] & 0x3f) << 6) | (utf8[offset + 3] & 0x3f); |
| 287 | offset += 4; |
| 288 | return result; |
| 289 | } |
| 290 | throw std::invalid_argument("invalid string"); |
| 291 | } |
| 292 | |
| 293 | static std::vector<uint32_t> codepoints_from_utf8(const std::string & utf8) { |
| 294 | std::vector<uint32_t> result; |
no test coverage detected