cast.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "cast.h"
  2. #include <util/generic/yexception.h>
  3. #include <util/generic/buffer.h>
  4. namespace NPyBind {
  5. PyObject* GetTrueRef(bool incref) {
  6. if (incref)
  7. Py_RETURN_TRUE;
  8. return Py_True;
  9. }
  10. PyObject* GetFalseRef(bool incref) {
  11. if (incref)
  12. Py_RETURN_FALSE;
  13. return Py_False;
  14. }
  15. PyObject* BuildPyObject(int val) {
  16. return Py_BuildValue("i", val);
  17. }
  18. PyObject* BuildPyObject(unsigned int val) {
  19. return Py_BuildValue("I", val);
  20. }
  21. PyObject* BuildPyObject(long int val) {
  22. return Py_BuildValue("l", val);
  23. }
  24. PyObject* BuildPyObject(unsigned long int val) {
  25. return Py_BuildValue("k", val);
  26. }
  27. #ifdef PY_LONG_LONG
  28. PyObject* BuildPyObject(PY_LONG_LONG val) {
  29. return Py_BuildValue("L", val);
  30. }
  31. PyObject* BuildPyObject(unsigned PY_LONG_LONG val) {
  32. return Py_BuildValue("K", val);
  33. }
  34. #endif
  35. PyObject* BuildPyObject(float val) {
  36. return Py_BuildValue("f", val);
  37. }
  38. PyObject* BuildPyObject(double val) {
  39. return Py_BuildValue("d", val);
  40. }
  41. PyObject* BuildPyObject(const TStringBuf& val) {
  42. if (!val.IsInited())
  43. Py_RETURN_NONE;
  44. PyObject* stringValue = Py_BuildValue("s#", val.data(), static_cast<int>(val.length()));
  45. if (stringValue != nullptr) {
  46. return stringValue;
  47. }
  48. if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
  49. PyErr_Clear();
  50. } else {
  51. return nullptr;
  52. }
  53. return Py_BuildValue("y#", val.data(), static_cast<int>(val.length()));
  54. }
  55. PyObject* BuildPyObject(const char* val) {
  56. if (val == nullptr)
  57. Py_RETURN_NONE;
  58. PyObject* stringValue = Py_BuildValue("s#", val, static_cast<int>(strlen(val)));
  59. if (stringValue != nullptr) {
  60. return stringValue;
  61. }
  62. if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
  63. PyErr_Clear();
  64. } else {
  65. return nullptr;
  66. }
  67. return Py_BuildValue("y#", val, static_cast<int>(strlen(val)));
  68. }
  69. PyObject* BuildPyObject(const TWtringBuf& val) {
  70. if (!val.IsInited())
  71. Py_RETURN_NONE;
  72. #if PY_VERSION_HEX < 0x03030000
  73. TPyObjectPtr result(PyUnicode_FromUnicode(nullptr, val.size()), true);
  74. Py_UNICODE* buf = PyUnicode_AS_UNICODE(result.Get());
  75. if (buf == nullptr)
  76. Py_RETURN_NONE;
  77. for (size_t i = 0; i < val.size(); ++i) {
  78. buf[i] = static_cast<Py_UNICODE>(val[i]);
  79. }
  80. #else
  81. PyObject* unicodeValue = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, val.data(), val.size());
  82. if (unicodeValue == nullptr)
  83. Py_RETURN_NONE;
  84. TPyObjectPtr result(unicodeValue, true);
  85. #endif
  86. return result.RefGet();
  87. }
  88. PyObject* BuildPyObject(const TBuffer& val) {
  89. TPyObjectPtr res(PyList_New(val.size()), true);
  90. for (size_t i = 0, size = val.Size(); i < size; ++i)
  91. PyList_SetItem(res.Get(), i, BuildPyObject(val.Data()[i]));
  92. return res.RefGet();
  93. }
  94. PyObject* BuildPyObject(bool val) {
  95. if (val)
  96. Py_RETURN_TRUE;
  97. else
  98. Py_RETURN_FALSE;
  99. }
  100. PyObject* BuildPyObject(PyObject* val) {
  101. Py_XINCREF(val);
  102. return val;
  103. }
  104. PyObject* BuildPyObject(TPyObjectPtr ptr) {
  105. return ptr.RefGet();
  106. }
  107. /* python represents (http://docs.python.org/c-api/arg.html#Py_BuildValue)
  108. * char, uchar, short, ushort, int, long as PyInt
  109. * uint, ulong as PyInt or PyLong (if exceeds sys.maxint)
  110. * longlong, ulonglong as PyLong
  111. */
  112. template <>
  113. bool FromPyObject(PyObject* obj, long& res) {
  114. if (PyLong_Check(obj)) {
  115. res = PyLong_AsLong(obj);
  116. return true;
  117. }
  118. if (PyFloat_Check(obj)) {
  119. res = static_cast<long>(PyFloat_AsDouble(obj));
  120. return true;
  121. }
  122. #if PY_MAJOR_VERSION < 3
  123. res = PyInt_AsLong(obj);
  124. #endif
  125. return -1 != res || !PyErr_Occurred();
  126. }
  127. template <>
  128. bool FromPyObject(PyObject* obj, unsigned long& res) {
  129. long lres;
  130. if (!FromPyObject(obj, lres))
  131. return false;
  132. if (lres < 0)
  133. return false;
  134. res = static_cast<unsigned long long>(lres);
  135. return true;
  136. }
  137. template <>
  138. bool FromPyObject(PyObject* obj, int& res) {
  139. long lres;
  140. if (!FromPyObject(obj, lres))
  141. return false;
  142. res = static_cast<int>(lres);
  143. return true;
  144. }
  145. template <>
  146. bool FromPyObject(PyObject* obj, unsigned char& res) {
  147. long lres;
  148. if (!FromPyObject(obj, lres))
  149. return false;
  150. res = static_cast<unsigned char>(lres);
  151. return true;
  152. }
  153. template <>
  154. bool FromPyObject(PyObject* obj, char& res) {
  155. long lres;
  156. if (!FromPyObject(obj, lres))
  157. return false;
  158. res = static_cast<char>(lres);
  159. return true;
  160. }
  161. template <>
  162. bool FromPyObject(PyObject* obj, unsigned int& res) {
  163. unsigned long lres;
  164. if (!FromPyObject(obj, lres))
  165. return false;
  166. res = static_cast<unsigned int>(lres);
  167. return true;
  168. }
  169. #ifdef HAVE_LONG_LONG
  170. template <>
  171. bool FromPyObject(PyObject* obj, long long& res) {
  172. if (PyLong_Check(obj)) {
  173. res = PyLong_AsLongLong(obj);
  174. return -1 != res || !PyErr_Occurred();
  175. }
  176. long lres;
  177. if (!FromPyObject(obj, lres))
  178. return false;
  179. res = static_cast<long long>(lres);
  180. return true;
  181. }
  182. template <>
  183. bool FromPyObject(PyObject* obj, unsigned long long& res) {
  184. if (PyLong_Check(obj)) {
  185. res = PyLong_AsUnsignedLongLong(obj);
  186. return static_cast<unsigned long long>(-1) != res || !PyErr_Occurred();
  187. }
  188. long lres;
  189. if (!FromPyObject(obj, lres))
  190. return false;
  191. res = static_cast<unsigned long long>(lres);
  192. return true;
  193. }
  194. #endif
  195. template <>
  196. bool FromPyObject(PyObject* obj, double& res) {
  197. if (PyFloat_Check(obj)) {
  198. res = PyFloat_AsDouble(obj);
  199. return true;
  200. }
  201. long long lres;
  202. if (!FromPyObject(obj, lres))
  203. return false;
  204. res = static_cast<double>(lres);
  205. return true;
  206. }
  207. template <>
  208. bool FromPyObject(PyObject* obj, float& res) {
  209. double dres;
  210. if (!FromPyObject(obj, dres))
  211. return false;
  212. res = static_cast<float>(dres);
  213. return true;
  214. }
  215. template <>
  216. bool FromPyObject(PyObject* obj, bool& res) {
  217. if (!PyBool_Check(obj))
  218. return false;
  219. if (obj == Py_True)
  220. res = true;
  221. else
  222. res = false;
  223. return true;
  224. }
  225. template <>
  226. bool FromPyObject(PyObject* obj, PyObject*& res) {
  227. Py_XINCREF(obj);
  228. res = obj;
  229. return true;
  230. }
  231. template <>
  232. bool FromPyObject(PyObject* obj, TPyObjectPtr& res) {
  233. res = TPyObjectPtr(obj);
  234. return true;
  235. }
  236. static inline bool _FromPyObject(PyObject* obj, TStringBuf& res) {
  237. char* str;
  238. Py_ssize_t len;
  239. #if PY_MAJOR_VERSION >= 3
  240. if (PyUnicode_Check(obj)) {
  241. auto buf = PyUnicode_AsUTF8AndSize(obj, &len);
  242. res = TStringBuf(buf, len);
  243. return true;
  244. }
  245. #endif
  246. if (-1 == PyBytes_AsStringAndSize(obj, &str, &len) || 0 > len)
  247. return false;
  248. res = TStringBuf(str, len);
  249. return true;
  250. }
  251. bool FromPyObject(PyObject* obj, TStringBuf& res) {
  252. return _FromPyObject(obj, res);
  253. }
  254. bool FromPyObject(PyObject* obj, TString& res) {
  255. TStringBuf str;
  256. if (!_FromPyObject(obj, str))
  257. return false;
  258. res = str;
  259. return true;
  260. }
  261. bool FromPyObject(PyObject* obj, TUtf16String& res) {
  262. if (!PyUnicode_Check(obj))
  263. return false;
  264. auto str = TPyObjectPtr(PyUnicode_AsUTF16String(obj), true);
  265. if (!str)
  266. return false;
  267. constexpr auto BOM_SIZE = 2;
  268. size_t len = (static_cast<size_t>(PyBytes_GET_SIZE(str.Get())) - BOM_SIZE) / 2;
  269. res.resize(len);
  270. memcpy(res.begin(), PyBytes_AS_STRING(str.Get()) + BOM_SIZE, len * 2);
  271. return (nullptr == PyErr_Occurred());
  272. }
  273. bool FromPyObject(PyObject* obj, TBuffer& res) {
  274. if (!PyList_Check(obj))
  275. return false;
  276. size_t cnt = PyList_Size(obj);
  277. res.Reserve(cnt);
  278. for (size_t i = 0; i < cnt; ++i) {
  279. PyObject* item = PyList_GET_ITEM(obj, i);
  280. char ch = 0;
  281. if (!FromPyObject(item, ch))
  282. return false;
  283. res.Append(ch);
  284. }
  285. return true;
  286. }
  287. }