| 390 | } |
| 391 | |
| 392 | static inline bool UTF8DecodeReverse(const uint8_t** data, uint32_t* codepoint) { |
| 393 | const uint8_t* str = *data; |
| 394 | if (*str < 0x80) { // ascii |
| 395 | *codepoint = *str--; |
| 396 | } else { |
| 397 | if (ARROW_PREDICT_FALSE(!Utf8IsContinuation(*str))) { |
| 398 | return false; |
| 399 | } |
| 400 | uint8_t code_unit_N = (*str--) & 0x3F; // take last 6 bits |
| 401 | if (Utf8Is2ByteStart(*str)) { |
| 402 | uint8_t code_unit_1 = (*str--) & 0x1F; // take last 5 bits |
| 403 | *codepoint = (code_unit_1 << 6) + code_unit_N; |
| 404 | } else { |
| 405 | if (ARROW_PREDICT_FALSE(!Utf8IsContinuation(*str))) { |
| 406 | return false; |
| 407 | } |
| 408 | uint8_t code_unit_Nmin1 = (*str--) & 0x3F; // take last 6 bits |
| 409 | if (Utf8Is3ByteStart(*str)) { |
| 410 | uint8_t code_unit_1 = (*str--) & 0x0F; // take last 4 bits |
| 411 | *codepoint = (code_unit_1 << 12) + (code_unit_Nmin1 << 6) + code_unit_N; |
| 412 | } else { |
| 413 | if (ARROW_PREDICT_FALSE(!Utf8IsContinuation(*str))) { |
| 414 | return false; |
| 415 | } |
| 416 | uint8_t code_unit_Nmin2 = (*str--) & 0x3F; // take last 6 bits |
| 417 | if (ARROW_PREDICT_TRUE(Utf8Is4ByteStart(*str))) { |
| 418 | uint8_t code_unit_1 = (*str--) & 0x07; // take last 3 bits |
| 419 | *codepoint = (code_unit_1 << 18) + (code_unit_Nmin2 << 12) + |
| 420 | (code_unit_Nmin1 << 6) + code_unit_N; |
| 421 | } else { |
| 422 | return false; |
| 423 | } |
| 424 | } |
| 425 | } |
| 426 | } |
| 427 | *data = str; |
| 428 | return true; |
| 429 | } |
| 430 | |
| 431 | template <class UnaryOperation> |
| 432 | static inline bool UTF8Transform(const uint8_t* first, const uint8_t* last, |