Imported Upstream version 1.64.0
[platform/upstream/boost.git] / 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