]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/python/src/converter/builtin_converters.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / python / src / converter / builtin_converters.cpp
1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/python/handle.hpp>
7 #include <boost/python/type_id.hpp>
8 #include <boost/python/errors.hpp>
9 #include <boost/python/refcount.hpp>
10
11 #include <boost/python/detail/config.hpp>
12 #include <boost/python/detail/wrap_python.hpp>
13
14 #include <boost/python/converter/builtin_converters.hpp>
15 #include <boost/python/converter/rvalue_from_python_data.hpp>
16 #include <boost/python/converter/registry.hpp>
17 #include <boost/python/converter/registrations.hpp>
18 #include <boost/python/converter/shared_ptr_deleter.hpp>
19 #include <boost/python/converter/pytype_function.hpp>
20
21 #include <boost/cast.hpp>
22 #include <string>
23 #include <complex>
24
25 namespace boost { namespace python { namespace converter {
26
27 shared_ptr_deleter::shared_ptr_deleter(handle<> owner)
28 : owner(owner)
29 {}
30
31 shared_ptr_deleter::~shared_ptr_deleter() {}
32
33 void shared_ptr_deleter::operator()(void const*)
34 {
35 owner.reset();
36 }
37
38 namespace
39 {
40
41 // An lvalue conversion function which extracts a char const* from a
42 // Python String.
43 #if PY_VERSION_HEX < 0x03000000
44 void* convert_to_cstring(PyObject* obj)
45 {
46 return PyString_Check(obj) ? PyString_AsString(obj) : 0;
47 }
48 #else
49 void* convert_to_cstring(PyObject* obj)
50 {
51 return PyUnicode_Check(obj) ? _PyUnicode_AsString(obj) : 0;
52 }
53 #endif
54
55 // Given a target type and a SlotPolicy describing how to perform a
56 // given conversion, registers from_python converters which use the
57 // SlotPolicy to extract the type.
58 template <class T, class SlotPolicy>
59 struct slot_rvalue_from_python
60 {
61 public:
62 slot_rvalue_from_python()
63 {
64 registry::insert(
65 &slot_rvalue_from_python<T,SlotPolicy>::convertible
66 , &slot_rvalue_from_python<T,SlotPolicy>::construct
67 , type_id<T>()
68 , &SlotPolicy::get_pytype
69 );
70 }
71
72 private:
73 static void* convertible(PyObject* obj)
74 {
75 unaryfunc* slot = SlotPolicy::get_slot(obj);
76 return slot && *slot ? slot : 0;
77 }
78
79 static void construct(PyObject* obj, rvalue_from_python_stage1_data* data)
80 {
81 // Get the (intermediate) source object
82 unaryfunc creator = *static_cast<unaryfunc*>(data->convertible);
83 handle<> intermediate(creator(obj));
84
85 // Get the location in which to construct
86 void* storage = ((rvalue_from_python_storage<T>*)data)->storage.bytes;
87 # ifdef _MSC_VER
88 # pragma warning(push)
89 # pragma warning(disable:4244)
90 # endif
91 new (storage) T( SlotPolicy::extract(intermediate.get()) );
92
93 # ifdef _MSC_VER
94 # pragma warning(pop)
95 # endif
96 // record successful construction
97 data->convertible = storage;
98 }
99 };
100
101 // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
102 // "slot" which just returns its argument.
103 extern "C" PyObject* identity_unaryfunc(PyObject* x)
104 {
105 Py_INCREF(x);
106 return x;
107 }
108 unaryfunc py_object_identity = identity_unaryfunc;
109
110 #if PY_VERSION_HEX >= 0x03000000
111 // As in Python 3 there is only one integer type, we can have much
112 // simplified logic.
113 // XXX(bhy) maybe the code will work with 2.6 or even 2.5?
114 struct int_rvalue_from_python_base
115 {
116 static unaryfunc* get_slot(PyObject* obj)
117 {
118 return PyLong_Check(obj) ? &py_object_identity : 0;
119 }
120 static PyTypeObject const* get_pytype() {return &PyLong_Type;}
121 };
122
123 template <class T>
124 struct signed_int_rvalue_from_python : int_rvalue_from_python_base
125 {
126 static T extract(PyObject* intermediate)
127 {
128 long x = PyLong_AsLong(intermediate);
129 if (PyErr_Occurred())
130 throw_error_already_set();
131 return numeric_cast<T>(x);
132 }
133 };
134
135 template <class T>
136 struct unsigned_int_rvalue_from_python : int_rvalue_from_python_base
137 {
138 static T extract(PyObject* intermediate)
139 {
140 unsigned long x = PyLong_AsUnsignedLong(intermediate);
141 if (PyErr_Occurred())
142 throw_error_already_set();
143 return numeric_cast<T>(x);
144 }
145 };
146 #else // PY_VERSION_HEX >= 0x03000000
147 // A SlotPolicy for extracting signed integer types from Python objects
148 struct signed_int_rvalue_from_python_base
149 {
150 static unaryfunc* get_slot(PyObject* obj)
151 {
152 PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
153 if (number_methods == 0)
154 return 0;
155
156 return (
157 #if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
158 !PyBool_Check(obj) &&
159 #endif
160 (PyInt_Check(obj) || PyLong_Check(obj)))
161
162 ? &number_methods->nb_int : 0;
163 }
164 static PyTypeObject const* get_pytype() { return &PyInt_Type;}
165 };
166
167 template <class T>
168 struct signed_int_rvalue_from_python : signed_int_rvalue_from_python_base
169 {
170 static T extract(PyObject* intermediate)
171 {
172 long x = PyInt_AsLong(intermediate);
173 if (PyErr_Occurred())
174 throw_error_already_set();
175 return numeric_cast<T>(x);
176 }
177 };
178
179 // A SlotPolicy for extracting unsigned integer types from Python objects
180 struct unsigned_int_rvalue_from_python_base
181 {
182 static unaryfunc* get_slot(PyObject* obj)
183 {
184 PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
185 if (number_methods == 0)
186 return 0;
187
188 return (
189 #if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
190 !PyBool_Check(obj) &&
191 #endif
192 (PyInt_Check(obj) || PyLong_Check(obj)))
193 ? &py_object_identity : 0;
194 }
195 static PyTypeObject const* get_pytype() { return &PyInt_Type;}
196 };
197
198 template <class T>
199 struct unsigned_int_rvalue_from_python : unsigned_int_rvalue_from_python_base
200 {
201 static T extract(PyObject* intermediate)
202 {
203 if (PyLong_Check(intermediate)) {
204 // PyLong_AsUnsignedLong() checks for negative overflow, so no
205 // need to check it here.
206 unsigned long result = PyLong_AsUnsignedLong(intermediate);
207 if (PyErr_Occurred())
208 throw_error_already_set();
209 return numeric_cast<T>(result);
210 } else {
211 // None of PyInt_AsUnsigned*() functions check for negative
212 // overflow, so use PyInt_AS_LONG instead and check if number is
213 // negative, issuing the exception appropriately.
214 long result = PyInt_AS_LONG(intermediate);
215 if (PyErr_Occurred())
216 throw_error_already_set();
217 if (result < 0) {
218 PyErr_SetString(PyExc_OverflowError, "can't convert negative"
219 " value to unsigned");
220 throw_error_already_set();
221 }
222 return numeric_cast<T>(result);
223 }
224 }
225 };
226 #endif // PY_VERSION_HEX >= 0x03000000
227
228 // Checking Python's macro instead of Boost's - we don't seem to get
229 // the config right all the time. Furthermore, Python's is defined
230 // when long long is absent but __int64 is present.
231
232 #ifdef HAVE_LONG_LONG
233 // A SlotPolicy for extracting long long types from Python objects
234
235 struct long_long_rvalue_from_python_base
236 {
237 static unaryfunc* get_slot(PyObject* obj)
238 {
239 #if PY_VERSION_HEX >= 0x03000000
240 return PyLong_Check(obj) ? &py_object_identity : 0;
241 #else
242 PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
243 if (number_methods == 0)
244 return 0;
245
246 // Return the identity conversion slot to avoid creating a
247 // new object. We'll handle that in the extract function
248 if (PyInt_Check(obj))
249 return &number_methods->nb_int;
250 else if (PyLong_Check(obj))
251 return &number_methods->nb_long;
252 else
253 return 0;
254 #endif
255 }
256 static PyTypeObject const* get_pytype() { return &PyLong_Type;}
257 };
258
259 struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
260 {
261 static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
262 {
263 #if PY_VERSION_HEX < 0x03000000
264 if (PyInt_Check(intermediate))
265 {
266 return PyInt_AS_LONG(intermediate);
267 }
268 else
269 #endif
270 {
271 BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate);
272
273 if (PyErr_Occurred())
274 throw_error_already_set();
275
276 return result;
277 }
278 }
279 };
280
281 struct unsigned_long_long_rvalue_from_python : long_long_rvalue_from_python_base
282 {
283 static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
284 {
285 #if PY_VERSION_HEX < 0x03000000
286 if (PyInt_Check(intermediate))
287 {
288 return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate));
289 }
290 else
291 #endif
292 {
293 unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate);
294
295 if (PyErr_Occurred())
296 throw_error_already_set();
297
298 return result;
299 }
300 }
301 };
302 #endif
303
304 // A SlotPolicy for extracting bool from a Python object
305 struct bool_rvalue_from_python
306 {
307 static unaryfunc* get_slot(PyObject* obj)
308 {
309 #if PY_VERSION_HEX >= 0x03000000
310 return obj == Py_None || PyLong_Check(obj) ? &py_object_identity : 0;
311 #elif PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
312 return obj == Py_None || PyBool_Check(obj) ? &py_object_identity : 0;
313 #else
314 return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0;
315 #endif
316 }
317
318 static bool extract(PyObject* intermediate)
319 {
320 return PyObject_IsTrue(intermediate);
321 }
322
323 static PyTypeObject const* get_pytype()
324 {
325 #if PY_VERSION_HEX >= 0x02030000
326 return &PyBool_Type;
327 #else
328 return &PyInt_Type;
329 #endif
330 }
331 };
332
333 // A SlotPolicy for extracting floating types from Python objects.
334 struct float_rvalue_from_python
335 {
336 static unaryfunc* get_slot(PyObject* obj)
337 {
338 PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
339 if (number_methods == 0)
340 return 0;
341
342 // For integer types, return the tp_int conversion slot to avoid
343 // creating a new object. We'll handle that below
344 #if PY_VERSION_HEX < 0x03000000
345 if (PyInt_Check(obj))
346 return &number_methods->nb_int;
347 #endif
348
349 return (PyLong_Check(obj) || PyFloat_Check(obj))
350 ? &number_methods->nb_float : 0;
351 }
352
353 static double extract(PyObject* intermediate)
354 {
355 #if PY_VERSION_HEX < 0x03000000
356 if (PyInt_Check(intermediate))
357 {
358 return PyInt_AS_LONG(intermediate);
359 }
360 else
361 #endif
362 {
363 return PyFloat_AS_DOUBLE(intermediate);
364 }
365 }
366 static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
367 };
368
369 #if PY_VERSION_HEX >= 0x03000000
370 unaryfunc py_unicode_as_string_unaryfunc = PyUnicode_AsUTF8String;
371 #endif
372
373 // A SlotPolicy for extracting C++ strings from Python objects.
374 struct string_rvalue_from_python
375 {
376 // If the underlying object is "string-able" this will succeed
377 static unaryfunc* get_slot(PyObject* obj)
378 {
379 #if PY_VERSION_HEX >= 0x03000000
380 return (PyUnicode_Check(obj)) ? &py_unicode_as_string_unaryfunc :
381 PyBytes_Check(obj) ? &py_object_identity : 0;
382 #else
383 return (PyString_Check(obj)) ? &obj->ob_type->tp_str : 0;
384
385 #endif
386 };
387
388 // Remember that this will be used to construct the result object
389 #if PY_VERSION_HEX >= 0x03000000
390 static std::string extract(PyObject* intermediate)
391 {
392 return std::string(PyBytes_AsString(intermediate),PyBytes_Size(intermediate));
393 }
394 static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
395 #else
396 static std::string extract(PyObject* intermediate)
397 {
398 return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
399 }
400 static PyTypeObject const* get_pytype() { return &PyString_Type;}
401 #endif
402 };
403
404 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
405 // encode_string_unaryfunc/py_encode_string -- manufacture a unaryfunc
406 // "slot" which encodes a Python string using the default encoding
407 extern "C" PyObject* encode_string_unaryfunc(PyObject* x)
408 {
409 return PyUnicode_FromEncodedObject( x, 0, 0 );
410 }
411 unaryfunc py_encode_string = encode_string_unaryfunc;
412
413 // A SlotPolicy for extracting C++ strings from Python objects.
414 struct wstring_rvalue_from_python
415 {
416 // If the underlying object is "string-able" this will succeed
417 static unaryfunc* get_slot(PyObject* obj)
418 {
419 return PyUnicode_Check(obj)
420 ? &py_object_identity
421 #if PY_VERSION_HEX >= 0x03000000
422 : PyBytes_Check(obj)
423 #else
424 : PyString_Check(obj)
425 #endif
426 ? &py_encode_string
427 : 0;
428 };
429
430 // Remember that this will be used to construct the result object
431 static std::wstring extract(PyObject* intermediate)
432 {
433 // On Windows, with Python >= 3.3, PyObject_Length cannot be used to get
434 // the size of the wchar_t string, because it will count the number of
435 // *code points*, but some characters not on the BMP will use two UTF-16
436 // *code units* (surrogate pairs).
437 // This is not a problem on Unix, since wchar_t is 32-bit.
438 #if defined(_WIN32) && PY_VERSION_HEX >= 0x03030000
439 BOOST_STATIC_ASSERT(sizeof(wchar_t) == 2);
440
441 Py_ssize_t size = 0;
442 wchar_t *buf = PyUnicode_AsWideCharString(intermediate, &size);
443 if (buf == NULL) {
444 boost::python::throw_error_already_set();
445 }
446 std::wstring result(buf, size);
447 PyMem_Free(buf);
448 #else
449 std::wstring result(::PyObject_Length(intermediate), L' ');
450 if (!result.empty())
451 {
452 int err = PyUnicode_AsWideChar(
453 #if PY_VERSION_HEX < 0x03020000
454 (PyUnicodeObject *)
455 #endif
456 intermediate
457 , &result[0]
458 , result.size());
459
460 if (err == -1)
461 throw_error_already_set();
462 }
463 #endif
464 return result;
465 }
466 static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
467 };
468 #endif
469
470 struct complex_rvalue_from_python
471 {
472 static unaryfunc* get_slot(PyObject* obj)
473 {
474 if (PyComplex_Check(obj))
475 return &py_object_identity;
476 else
477 return float_rvalue_from_python::get_slot(obj);
478 }
479
480 static std::complex<double> extract(PyObject* intermediate)
481 {
482 if (PyComplex_Check(intermediate))
483 {
484 return std::complex<double>(
485 PyComplex_RealAsDouble(intermediate)
486 , PyComplex_ImagAsDouble(intermediate));
487 }
488 #if PY_VERSION_HEX < 0x03000000
489 else if (PyInt_Check(intermediate))
490 {
491 return PyInt_AS_LONG(intermediate);
492 }
493 #endif
494 else
495 {
496 return PyFloat_AS_DOUBLE(intermediate);
497 }
498 }
499 static PyTypeObject const* get_pytype() { return &PyComplex_Type;}
500 };
501 }
502
503 BOOST_PYTHON_DECL PyObject* do_return_to_python(char x)
504 {
505 #if PY_VERSION_HEX >= 0x03000000
506 return PyUnicode_FromStringAndSize(&x, 1);
507 #else
508 return PyString_FromStringAndSize(&x, 1);
509 #endif
510 }
511
512 BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x)
513 {
514 #if PY_VERSION_HEX >= 0x03000000
515 return x ? PyUnicode_FromString(x) : boost::python::detail::none();
516 #else
517 return x ? PyString_FromString(x) : boost::python::detail::none();
518 #endif
519 }
520
521 BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x)
522 {
523 return x ? x : boost::python::detail::none();
524 }
525
526 BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject* x)
527 {
528 if (x == 0)
529 return boost::python::detail::none();
530
531 Py_INCREF(x);
532 return x;
533 }
534
535 #define REGISTER_INT_CONVERTERS(signedness, U) \
536 slot_rvalue_from_python< \
537 signedness U \
538 ,signedness##_int_rvalue_from_python<signedness U> \
539 >()
540
541 #define REGISTER_INT_CONVERTERS2(U) \
542 REGISTER_INT_CONVERTERS(signed, U); \
543 REGISTER_INT_CONVERTERS(unsigned, U)
544
545 void initialize_builtin_converters()
546 {
547 // booleans
548 slot_rvalue_from_python<bool,bool_rvalue_from_python>();
549
550 // integer types
551 REGISTER_INT_CONVERTERS2(char);
552 REGISTER_INT_CONVERTERS2(short);
553 REGISTER_INT_CONVERTERS2(int);
554 REGISTER_INT_CONVERTERS2(long);
555
556 // using Python's macro instead of Boost's - we don't seem to get the
557 // config right all the time.
558 # ifdef HAVE_LONG_LONG
559 slot_rvalue_from_python<signed BOOST_PYTHON_LONG_LONG,long_long_rvalue_from_python>();
560 slot_rvalue_from_python<unsigned BOOST_PYTHON_LONG_LONG,unsigned_long_long_rvalue_from_python>();
561 # endif
562
563 // floating types
564 slot_rvalue_from_python<float,float_rvalue_from_python>();
565 slot_rvalue_from_python<double,float_rvalue_from_python>();
566 slot_rvalue_from_python<long double,float_rvalue_from_python>();
567
568 slot_rvalue_from_python<std::complex<float>,complex_rvalue_from_python>();
569 slot_rvalue_from_python<std::complex<double>,complex_rvalue_from_python>();
570 slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
571
572 // Add an lvalue converter for char which gets us char const*
573 #if PY_VERSION_HEX < 0x03000000
574 registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
575 #else
576 registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyUnicode_Type>::get_pytype);
577 #endif
578
579 // Register by-value converters to std::string, std::wstring
580 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
581 slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
582 # endif
583 slot_rvalue_from_python<std::string, string_rvalue_from_python>();
584
585 }
586
587 }}} // namespace boost::python::converter