summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/py_utils.cc70
1 files changed, 52 insertions, 18 deletions
diff --git a/src/py_utils.cc b/src/py_utils.cc
index fee1d659..704237d6 100644
--- a/src/py_utils.cc
+++ b/src/py_utils.cc
@@ -110,31 +110,65 @@ struct string_from_python
(data)->storage.bytes;
new (storage) string(value);
data->convertible = storage;
- } else {
+ return;
+ }
#endif
- VERIFY(PyUnicode_Check(obj_ptr));
-
- Py_ssize_t size = PyUnicode_GET_SIZE(obj_ptr);
- const Py_UNICODE* value = PyUnicode_AS_UNICODE(obj_ptr);
+ VERIFY(PyUnicode_Check(obj_ptr));
- string str;
+ string str;
+#if PY_MAJOR_VERSION < 3
+ Py_ssize_t size = PyUnicode_GET_SIZE(obj_ptr);
+ const Py_UNICODE* value = PyUnicode_AS_UNICODE(obj_ptr);
#if Py_UNICODE_SIZE == 2 // UTF-16
- utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
+ utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
#elif Py_UNICODE_SIZE == 4 // UTF-32
- utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
+ utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
+#else
+ assert("Py_UNICODE has an unexpected size" == NULL);
+#endif // Py_UNICODE_SIZE
+#else // PY_MAJOR_VERSION >= 3
+ Py_ssize_t size =
+#if PY_MINOR_VERSION >= 3
+ PyUnicode_GET_LENGTH(obj_ptr);
#else
- assert("Py_UNICODE has an unexpected size" == NULL);
+ PyUnicode_GET_SIZE(obj_ptr);
#endif
-
- if (value == 0) throw_error_already_set();
- void* storage =
- reinterpret_cast<converter::rvalue_from_python_storage<string> *>
- (data)->storage.bytes;
- new (storage) string(str);
- data->convertible = storage;
-#if PY_MAJOR_VERSION < 3
- }
+#if PY_MINOR_VERSION < 12
+ PyUnicode_READY(obj_ptr);
+#endif
+ const char* value;
+ switch (PyUnicode_KIND(obj_ptr)) {
+ case PyUnicode_1BYTE_KIND:
+ value = (const char*)PyUnicode_1BYTE_DATA(obj_ptr);
+ // FIXME: It seems wrong to use `utf16to8` on 1BYTE_DATA, yet without this call
+ // the tests fail with: libc++abi: terminating with uncaught exception of type int
+ utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
+ break;
+#if PY_MINOR_VERSION < 12 && Py_UNICODE_SIZE == 2
+ case PyUnicode_WCHAR_KIND:
+#endif
+ case PyUnicode_2BYTE_KIND:
+ value = (const char*)PyUnicode_2BYTE_DATA(obj_ptr);
+ utf8::unchecked::utf16to8(value, value + size, std::back_inserter(str));
+ break;
+#if PY_MINOR_VERSION < 12 && Py_UNICODE_SIZE == 4
+ case PyUnicode_WCHAR_KIND:
#endif
+ case PyUnicode_4BYTE_KIND:
+ value = (const char*)PyUnicode_4BYTE_DATA(obj_ptr);
+ utf8::unchecked::utf32to8(value, value + size, std::back_inserter(str));
+ break;
+ default:
+ assert("PyUnicode_KIND returned an unexpected kind" == NULL);
+ }
+#endif // PY_MAJOR_VERSION
+
+ if (value == 0) throw_error_already_set();
+ void* storage =
+ reinterpret_cast<converter::rvalue_from_python_storage<string> *>
+ (data)->storage.bytes;
+ new (storage) string(str);
+ data->convertible = storage;
}
};