diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 13:26:22 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-11-30 15:44:45 +0300 |
commit | 0a98fece5a9b54f16afeb3a94b3eb3105e9c3962 (patch) | |
tree | 291d72dbd7e9865399f668c84d11ed86fb190bbf /library/cpp/pybind/cast.cpp | |
parent | cb2c8d75065e5b3c47094067cb4aa407d4813298 (diff) | |
download | ydb-0a98fece5a9b54f16afeb3a94b3eb3105e9c3962.tar.gz |
YQ Connector:Use docker-compose in integrational tests
Diffstat (limited to 'library/cpp/pybind/cast.cpp')
-rw-r--r-- | library/cpp/pybind/cast.cpp | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/library/cpp/pybind/cast.cpp b/library/cpp/pybind/cast.cpp new file mode 100644 index 0000000000..60a44b0e83 --- /dev/null +++ b/library/cpp/pybind/cast.cpp @@ -0,0 +1,324 @@ +#include "cast.h" +#include <util/generic/yexception.h> +#include <util/generic/buffer.h> + +namespace NPyBind { + PyObject* GetTrueRef(bool incref) { + if (incref) + Py_RETURN_TRUE; + return Py_True; + } + + PyObject* GetFalseRef(bool incref) { + if (incref) + Py_RETURN_FALSE; + return Py_False; + } + + PyObject* BuildPyObject(int val) { + return Py_BuildValue("i", val); + } + + PyObject* BuildPyObject(unsigned int val) { + return Py_BuildValue("I", val); + } + + PyObject* BuildPyObject(long int val) { + return Py_BuildValue("l", val); + } + + PyObject* BuildPyObject(unsigned long int val) { + return Py_BuildValue("k", val); + } + +#ifdef PY_LONG_LONG + PyObject* BuildPyObject(PY_LONG_LONG val) { + return Py_BuildValue("L", val); + } + + PyObject* BuildPyObject(unsigned PY_LONG_LONG val) { + return Py_BuildValue("K", val); + } +#endif + + PyObject* BuildPyObject(float val) { + return Py_BuildValue("f", val); + } + + PyObject* BuildPyObject(double val) { + return Py_BuildValue("d", val); + } + + PyObject* BuildPyObject(const TStringBuf& val) { + if (!val.IsInited()) + Py_RETURN_NONE; + + PyObject* stringValue = Py_BuildValue("s#", val.data(), static_cast<int>(val.length())); + if (stringValue != nullptr) { + return stringValue; + } + if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + PyErr_Clear(); + } else { + return nullptr; + } + return Py_BuildValue("y#", val.data(), static_cast<int>(val.length())); + } + + PyObject* BuildPyObject(const char* val) { + if (val == nullptr) + Py_RETURN_NONE; + PyObject* stringValue = Py_BuildValue("s#", val, static_cast<int>(strlen(val))); + if (stringValue != nullptr) { + return stringValue; + } + if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + PyErr_Clear(); + } else { + return nullptr; + } + return Py_BuildValue("y#", val, static_cast<int>(strlen(val))); + } + + PyObject* BuildPyObject(const TWtringBuf& val) { + if (!val.IsInited()) + Py_RETURN_NONE; +#if PY_VERSION_HEX < 0x03030000 + TPyObjectPtr result(PyUnicode_FromUnicode(nullptr, val.size()), true); + Py_UNICODE* buf = PyUnicode_AS_UNICODE(result.Get()); + if (buf == nullptr) + Py_RETURN_NONE; + for (size_t i = 0; i < val.size(); ++i) { + buf[i] = static_cast<Py_UNICODE>(val[i]); + } +#else + PyObject* unicodeValue = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, val.data(), val.size()); + if (unicodeValue == nullptr) + Py_RETURN_NONE; + TPyObjectPtr result(unicodeValue, true); +#endif + return result.RefGet(); + } + + PyObject* BuildPyObject(const TBuffer& val) { + TPyObjectPtr res(PyList_New(val.size()), true); + for (size_t i = 0, size = val.Size(); i < size; ++i) + PyList_SetItem(res.Get(), i, BuildPyObject(val.Data()[i])); + return res.RefGet(); + } + + PyObject* BuildPyObject(bool val) { + if (val) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + } + + PyObject* BuildPyObject(PyObject* val) { + Py_XINCREF(val); + return val; + } + + PyObject* BuildPyObject(TPyObjectPtr ptr) { + return ptr.RefGet(); + } + + /* python represents (http://docs.python.org/c-api/arg.html#Py_BuildValue) + * char, uchar, short, ushort, int, long as PyInt + * uint, ulong as PyInt or PyLong (if exceeds sys.maxint) + * longlong, ulonglong as PyLong + */ + + template <> + bool FromPyObject(PyObject* obj, long& res) { + if (PyLong_Check(obj)) { + res = PyLong_AsLong(obj); + return true; + } + if (PyFloat_Check(obj)) { + res = static_cast<long>(PyFloat_AsDouble(obj)); + return true; + } +#if PY_MAJOR_VERSION < 3 + res = PyInt_AsLong(obj); +#endif + return -1 != res || !PyErr_Occurred(); + } + + template <> + bool FromPyObject(PyObject* obj, unsigned long& res) { + long lres; + if (!FromPyObject(obj, lres)) + return false; + if (lres < 0) + return false; + res = static_cast<unsigned long long>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, int& res) { + long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<int>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, unsigned char& res) { + long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<unsigned char>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, char& res) { + long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<char>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, unsigned int& res) { + unsigned long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<unsigned int>(lres); + return true; + } + +#ifdef HAVE_LONG_LONG + template <> + bool FromPyObject(PyObject* obj, long long& res) { + if (PyLong_Check(obj)) { + res = PyLong_AsLongLong(obj); + return -1 != res || !PyErr_Occurred(); + } + long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<long long>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, unsigned long long& res) { + if (PyLong_Check(obj)) { + res = PyLong_AsUnsignedLongLong(obj); + return static_cast<unsigned long long>(-1) != res || !PyErr_Occurred(); + } + long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<unsigned long long>(lres); + return true; + } +#endif + + template <> + bool FromPyObject(PyObject* obj, double& res) { + if (PyFloat_Check(obj)) { + res = PyFloat_AsDouble(obj); + return true; + } + long long lres; + if (!FromPyObject(obj, lres)) + return false; + res = static_cast<double>(lres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, float& res) { + double dres; + if (!FromPyObject(obj, dres)) + return false; + res = static_cast<float>(dres); + return true; + } + + template <> + bool FromPyObject(PyObject* obj, bool& res) { + if (!PyBool_Check(obj)) + return false; + if (obj == Py_True) + res = true; + else + res = false; + return true; + } + + template <> + bool FromPyObject(PyObject* obj, PyObject*& res) { + Py_XINCREF(obj); + res = obj; + return true; + } + + template <> + bool FromPyObject(PyObject* obj, TPyObjectPtr& res) { + res = TPyObjectPtr(obj); + return true; + } + + static inline bool _FromPyObject(PyObject* obj, TStringBuf& res) { + char* str; + Py_ssize_t len; +#if PY_MAJOR_VERSION >= 3 + if (PyUnicode_Check(obj)) { + auto buf = PyUnicode_AsUTF8AndSize(obj, &len); + res = TStringBuf(buf, len); + return true; + } +#endif + if (-1 == PyBytes_AsStringAndSize(obj, &str, &len) || 0 > len) + return false; + res = TStringBuf(str, len); + return true; + } + + bool FromPyObject(PyObject* obj, TStringBuf& res) { + return _FromPyObject(obj, res); + } + + bool FromPyObject(PyObject* obj, TString& res) { + TStringBuf str; + if (!_FromPyObject(obj, str)) + return false; + res = str; + return true; + } + + bool FromPyObject(PyObject* obj, TUtf16String& res) { + if (!PyUnicode_Check(obj)) + return false; + auto str = TPyObjectPtr(PyUnicode_AsUTF16String(obj), true); + if (!str) + return false; + constexpr auto BOM_SIZE = 2; + size_t len = (static_cast<size_t>(PyBytes_GET_SIZE(str.Get())) - BOM_SIZE) / 2; + res.resize(len); + memcpy(res.begin(), PyBytes_AS_STRING(str.Get()) + BOM_SIZE, len * 2); + return (nullptr == PyErr_Occurred()); + } + + bool FromPyObject(PyObject* obj, TBuffer& res) { + if (!PyList_Check(obj)) + return false; + size_t cnt = PyList_Size(obj); + res.Reserve(cnt); + for (size_t i = 0; i < cnt; ++i) { + PyObject* item = PyList_GET_ITEM(obj, i); + char ch = 0; + if (!FromPyObject(item, ch)) + return false; + res.Append(ch); + } + return true; + } +} |