| 670 | |
| 671 | template <typename T> |
| 672 | Status AppendUTF32(const char* data, int64_t itemsize, int byteorder, T* builder) { |
| 673 | // The binary \x00\x00\x00\x00 indicates a nul terminator in NumPy unicode, |
| 674 | // so we need to detect that here to truncate if necessary. Yep. |
| 675 | Py_ssize_t actual_length = 0; |
| 676 | for (; actual_length < itemsize / kNumPyUnicodeSize; ++actual_length) { |
| 677 | const char* code_point = data + actual_length * kNumPyUnicodeSize; |
| 678 | if ((*code_point == '\0') && (*(code_point + 1) == '\0') && |
| 679 | (*(code_point + 2) == '\0') && (*(code_point + 3) == '\0')) { |
| 680 | break; |
| 681 | } |
| 682 | } |
| 683 | |
| 684 | OwnedRef unicode_obj(PyUnicode_DecodeUTF32(data, actual_length * kNumPyUnicodeSize, |
| 685 | nullptr, &byteorder)); |
| 686 | RETURN_IF_PYERROR(); |
| 687 | OwnedRef utf8_obj(PyUnicode_AsUTF8String(unicode_obj.obj())); |
| 688 | if (utf8_obj.obj() == NULL) { |
| 689 | PyErr_Clear(); |
| 690 | return Status::Invalid("failed converting UTF32 to UTF8"); |
| 691 | } |
| 692 | |
| 693 | const int32_t length = static_cast<int32_t>(PyBytes_GET_SIZE(utf8_obj.obj())); |
| 694 | return builder->Append( |
| 695 | reinterpret_cast<const uint8_t*>(PyBytes_AS_STRING(utf8_obj.obj())), length); |
| 696 | } |
| 697 | |
| 698 | } // namespace |
| 699 |
no test coverage detected