comparison oct-py-types.cc @ 402:c4b78e449c62

maint: indent functions declared in the pytave namespace * oct-py-eval.cc, oct-py-eval.h, oct-py-types.cc, oct-py-types.h, oct-py-util.cc, oct-py-util.h: Indent functions declared in the pytave namespace, adjust line wrap where necessary.
author Mike Miller <mtmiller@octave.org>
date Fri, 28 Apr 2017 14:07:57 -0700
parents 6c316b5f30f7
children 3644df6564bc
comparison
equal deleted inserted replaced
401:3a64a336d214 402:c4b78e449c62
38 #include "python_to_octave.h" 38 #include "python_to_octave.h"
39 39
40 namespace pytave 40 namespace pytave
41 { 41 {
42 42
43 PyObject * 43 PyObject *
44 make_py_bool (bool value) 44 make_py_bool (bool value)
45 { 45 {
46 if (value) 46 if (value)
47 Py_RETURN_TRUE; 47 Py_RETURN_TRUE;
48 else 48 else
49 Py_RETURN_FALSE; 49 Py_RETURN_FALSE;
50 } 50 }
51 51
52 PyObject * 52 PyObject *
53 make_py_complex (std::complex<double> value) 53 make_py_complex (std::complex<double> value)
54 { 54 {
55 Py_complex& py_complex_value = reinterpret_cast<Py_complex&> (value); 55 Py_complex& py_complex_value = reinterpret_cast<Py_complex&> (value);
56 return PyComplex_FromCComplex (py_complex_value); 56 return PyComplex_FromCComplex (py_complex_value);
57 } 57 }
58 58
59 PyObject * 59 PyObject *
60 make_py_float (double value) 60 make_py_float (double value)
61 { 61 {
62 return PyFloat_FromDouble (value); 62 return PyFloat_FromDouble (value);
63 } 63 }
64 64
65 bool 65 bool
66 extract_py_bool (PyObject *obj) 66 extract_py_bool (PyObject *obj)
67 { 67 {
68 if (! obj) 68 if (! obj)
69 throw object_convert_exception ("failed to extract boolean: null object"); 69 throw object_convert_exception ("failed to extract boolean: null object");
70 70
71 if (! PyBool_Check (obj)) 71 if (! PyBool_Check (obj))
72 throw object_convert_exception ("failed to extract boolean: wrong type"); 72 throw object_convert_exception ("failed to extract boolean: wrong type");
73 73
74 return (obj == Py_True); 74 return (obj == Py_True);
75 } 75 }
76 76
77 std::complex<double> 77 std::complex<double>
78 extract_py_complex (PyObject *obj) 78 extract_py_complex (PyObject *obj)
79 { 79 {
80 if (! obj) 80 if (! obj)
81 throw object_convert_exception ("failed to extract complex: null object"); 81 throw object_convert_exception ("failed to extract complex: null object");
82 82
83 if (! PyComplex_Check (obj)) 83 if (! PyComplex_Check (obj))
84 throw object_convert_exception ("failed to extract complex: wrong type"); 84 throw object_convert_exception ("failed to extract complex: wrong type");
85 85
86 Py_complex value = PyComplex_AsCComplex (obj); 86 Py_complex value = PyComplex_AsCComplex (obj);
87 return reinterpret_cast<std::complex<double>&> (value); 87 return reinterpret_cast<std::complex<double>&> (value);
88 } 88 }
89 89
90 double 90 double
91 extract_py_float (PyObject *obj) 91 extract_py_float (PyObject *obj)
92 { 92 {
93 if (! obj) 93 if (! obj)
94 throw object_convert_exception ("failed to extract float: null object"); 94 throw object_convert_exception ("failed to extract float: null object");
95 95
96 if (! PyFloat_Check (obj)) 96 if (! PyFloat_Check (obj))
97 throw object_convert_exception ("failed to extract float: wrong type"); 97 throw object_convert_exception ("failed to extract float: wrong type");
98 98
99 return PyFloat_AsDouble (obj); 99 return PyFloat_AsDouble (obj);
100 } 100 }
101 101
102 PyObject * 102 PyObject *
103 make_py_int (int32_t value) 103 make_py_int (int32_t value)
104 { 104 {
105 #if PY_VERSION_HEX >= 0x03000000 105 #if PY_VERSION_HEX >= 0x03000000
106 return PyLong_FromLong (value); 106 return PyLong_FromLong (value);
107 #else 107 #else
108 return PyInt_FromLong (value); 108 return PyInt_FromLong (value);
109 #endif 109 #endif
110 } 110 }
111 111
112 PyObject * 112 PyObject *
113 make_py_int (uint32_t value) 113 make_py_int (uint32_t value)
114 { 114 {
115 return PyLong_FromUnsignedLong (value); 115 return PyLong_FromUnsignedLong (value);
116 } 116 }
117 117
118 PyObject * 118 PyObject *
119 make_py_int (int64_t value) 119 make_py_int (int64_t value)
120 { 120 {
121 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG)) 121 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG))
122 return PyLong_FromLongLong (value); 122 return PyLong_FromLongLong (value);
123 #else 123 #else
124 return PyLong_FromLong (value); 124 return PyLong_FromLong (value);
125 #endif 125 #endif
126 } 126 }
127 127
128 PyObject * 128 PyObject *
129 make_py_int (uint64_t value) 129 make_py_int (uint64_t value)
130 { 130 {
131 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG)) 131 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG > SIZEOF_LONG))
132 return PyLong_FromUnsignedLongLong (value); 132 return PyLong_FromUnsignedLongLong (value);
133 #else 133 #else
134 return PyLong_FromUnsignedLong (value); 134 return PyLong_FromUnsignedLong (value);
135 #endif 135 #endif
136 } 136 }
137 137
138 PyObject * 138 PyObject *
139 make_py_array (const void *data, size_t len, char typecode) 139 make_py_array (const void *data, size_t len, char typecode)
140 { 140 {
141 if (! typecode) 141 if (! typecode)
142 throw object_convert_exception ("unable to create array from Octave data"); 142 throw object_convert_exception
143 143 ("unable to create array from Octave data");
144 std::string arg { typecode }; 144
145 PyObject *array = py_call_function ("array.array", ovl (arg)); 145 std::string arg { typecode };
146 146 PyObject *array = py_call_function ("array.array", ovl (arg));
147 if (len > 0) 147
148 { 148 if (len > 0)
149 // create a byte buffer containing a copy of the array binary data 149 {
150 const char *cdata = reinterpret_cast<const char *> (data); 150 // create a byte buffer containing a copy of the array binary data
151 PyObject *buf = PyBytes_FromStringAndSize (cdata, len); 151 const char *cdata = reinterpret_cast<const char *> (data);
152 if (! buf) 152 PyObject *buf = PyBytes_FromStringAndSize (cdata, len);
153 octave_throw_bad_alloc (); 153 if (! buf)
154 154 octave_throw_bad_alloc ();
155 PyObject *frombytes = (PyObject_HasAttrString (array, "frombytes") ? 155
156 PyObject_GetAttrString (array, "frombytes") : 156 PyObject *frombytes = (PyObject_HasAttrString (array, "frombytes") ?
157 PyObject_GetAttrString (array, "fromstring")); 157 PyObject_GetAttrString (array, "frombytes") :
158 PyObject *args = PyTuple_Pack (1, buf); 158 PyObject_GetAttrString (array, "fromstring"));
159 py_call_function (frombytes, args); 159 PyObject *args = PyTuple_Pack (1, buf);
160 Py_DECREF (args); 160 py_call_function (frombytes, args);
161 Py_DECREF (buf); 161 Py_DECREF (args);
162 } 162 Py_DECREF (buf);
163 163 }
164 return array; 164
165 } 165 return array;
166 166 }
167 // Prefer the 'q' and 'Q' typecodes if they are available (if Python 3 and 167
168 // built with support for long long integers) 168 // Prefer the 'q' and 'Q' typecodes if they are available (if Python 3 and
169 // built with support for long long integers)
169 170
170 #if (PY_VERSION_HEX >= 0x03000000) && defined (HAVE_LONG_LONG) 171 #if (PY_VERSION_HEX >= 0x03000000) && defined (HAVE_LONG_LONG)
171 # define ARRAY_INT64_TYPECODE 'q' 172 # define ARRAY_INT64_TYPECODE 'q'
172 # define ARRAY_UINT64_TYPECODE 'Q' 173 # define ARRAY_UINT64_TYPECODE 'Q'
173 #elif (SIZEOF_LONG == 8) 174 #elif (SIZEOF_LONG == 8)
176 #else 177 #else
177 # define ARRAY_INT64_TYPECODE 0 178 # define ARRAY_INT64_TYPECODE 0
178 # define ARRAY_UINT64_TYPECODE 0 179 # define ARRAY_UINT64_TYPECODE 0
179 #endif 180 #endif
180 181
181 template <typename T> 182 template <typename T>
182 struct py_array_info { }; 183 struct py_array_info { };
183 184
184 template <> 185 template <>
185 struct py_array_info<octave_int8> { static const char typecode = 'b'; }; 186 struct py_array_info<octave_int8> { static const char typecode = 'b'; };
186 187
187 template <> 188 template <>
188 struct py_array_info<octave_int16> { static const char typecode = 'h'; }; 189 struct py_array_info<octave_int16> { static const char typecode = 'h'; };
189 190
190 template <> 191 template <>
191 struct py_array_info<octave_int32> { static const char typecode = 'i'; }; 192 struct py_array_info<octave_int32> { static const char typecode = 'i'; };
192 193
193 template <> 194 template <>
194 struct py_array_info<octave_int64> 195 struct py_array_info<octave_int64>
195 { 196 {
196 static const char typecode = ARRAY_INT64_TYPECODE; 197 static const char typecode = ARRAY_INT64_TYPECODE;
197 }; 198 };
198 199
199 template <> 200 template <>
200 struct py_array_info<octave_uint8> { static const char typecode = 'B'; }; 201 struct py_array_info<octave_uint8> { static const char typecode = 'B'; };
201 202
202 template <> 203 template <>
203 struct py_array_info<octave_uint16> { static const char typecode = 'H'; }; 204 struct py_array_info<octave_uint16> { static const char typecode = 'H'; };
204 205
205 template <> 206 template <>
206 struct py_array_info<octave_uint32> { static const char typecode = 'I'; }; 207 struct py_array_info<octave_uint32> { static const char typecode = 'I'; };
207 208
208 template <> 209 template <>
209 struct py_array_info<octave_uint64> { 210 struct py_array_info<octave_uint64> {
210 static const char typecode = ARRAY_UINT64_TYPECODE; 211 static const char typecode = ARRAY_UINT64_TYPECODE;
211 }; 212 };
212 213
213 PyObject * 214 PyObject *
214 make_py_array (const NDArray& nda) 215 make_py_array (const NDArray& nda)
215 { 216 {
216 return make_py_array (nda.data (), nda.numel () * sizeof (double), 'd'); 217 return make_py_array (nda.data (), nda.numel () * sizeof (double), 'd');
218 }
219
220 PyObject *
221 make_py_array (const FloatNDArray& nda)
222 {
223 return make_py_array (nda.data (), nda.numel () * sizeof (float), 'f');
224 }
225
226 template <typename T>
227 PyObject *
228 make_py_array (const intNDArray<T>& nda)
229 {
230 return make_py_array (nda.data (), nda.numel () * sizeof (T),
231 py_array_info<T>::typecode);
232 }
233
234 // Instantiate all possible integer array template functions needed
235
236 template PyObject * make_py_array<octave_int8> (const int8NDArray&);
237 template PyObject * make_py_array<octave_int16> (const int16NDArray&);
238 template PyObject * make_py_array<octave_int32> (const int32NDArray&);
239 template PyObject * make_py_array<octave_int64> (const int64NDArray&);
240 template PyObject * make_py_array<octave_uint8> (const uint8NDArray&);
241 template PyObject * make_py_array<octave_uint16> (const uint16NDArray&);
242 template PyObject * make_py_array<octave_uint32> (const uint32NDArray&);
243 template PyObject * make_py_array<octave_uint64> (const uint64NDArray&);
244
245 PyObject *
246 make_py_numeric_value (const octave_value& value)
247 {
248 if (value.is_scalar_type ())
249 {
250 if (value.is_bool_type ())
251 return make_py_bool (value.bool_value ());
252
253 else if (value.is_int8_type ())
254 return make_py_int (value.int8_scalar_value ().value ());
255 else if (value.is_int16_type ())
256 return make_py_int (value.int16_scalar_value ().value ());
257 else if (value.is_int32_type ())
258 return make_py_int (value.int32_scalar_value ().value ());
259 else if (value.is_int64_type ())
260 return make_py_int (value.int64_scalar_value ().value ());
261
262 else if (value.is_uint8_type ())
263 return make_py_int (value.uint8_scalar_value ().value ());
264 else if (value.is_uint16_type ())
265 return make_py_int (value.uint16_scalar_value ().value ());
266 else if (value.is_uint32_type ())
267 return make_py_int (value.uint32_scalar_value ().value ());
268 else if (value.is_uint64_type ())
269 return make_py_int (value.uint64_scalar_value ().value ());
270
271 else if (value.is_complex_type ())
272 return make_py_complex (value.complex_value ());
273 else if (value.is_float_type ())
274 return make_py_float (value.double_value ());
275 }
276
277 throw value_convert_exception ("unhandled scalar type");
278 return 0;
279 }
280
281 PyObject *
282 make_py_array (const octave_value& value)
283 {
284 if (value.is_numeric_type () && ! value.is_complex_type ()
285 && value.ndims () == 2 && (value.columns () <= 1 || value.rows () <= 1))
286 {
287 if (value.is_double_type ())
288 return make_py_array (value.array_value ());
289 else if (value.is_single_type ())
290 return make_py_array (value.float_array_value ());
291
292 else if (value.is_int8_type ())
293 return make_py_array (value.int8_array_value ());
294 else if (value.is_int16_type ())
295 return make_py_array (value.int16_array_value ());
296 else if (value.is_int32_type ())
297 return make_py_array (value.int32_array_value ());
298 else if (value.is_int64_type ())
299 return make_py_array (value.int64_array_value ());
300
301 else if (value.is_uint8_type ())
302 return make_py_array (value.uint8_array_value ());
303 else if (value.is_uint16_type ())
304 return make_py_array (value.uint16_array_value ());
305 else if (value.is_uint32_type ())
306 return make_py_array (value.uint32_array_value ());
307 else if (value.is_uint64_type ())
308 return make_py_array (value.uint64_array_value ());
309 }
310
311 throw value_convert_exception ("unhandled Octave numeric vector type");
312 return 0;
313 }
314
315 inline PyObject *
316 wrap_octvalue_to_pyobj (const octave_value& value)
317 {
318 boost::python::object obj;
319 octvalue_to_pyobj (obj, value);
320 PyObject *ptr = obj.ptr ();
321 Py_INCREF (ptr);
322 return ptr;
323 }
324
325 inline octave_value
326 wrap_pyobj_to_octvalue (PyObject *obj)
327 {
328 boost::python::object objref
329 { boost::python::handle<> (boost::python::borrowed (obj)) };
330 octave_value value;
331 pyobj_to_octvalue (value, objref);
332 return value;
333 }
334
335 octave_scalar_map
336 extract_py_scalar_map (PyObject *obj)
337 {
338 if (! obj)
339 throw object_convert_exception ("failed to extract map: null object");
340
341 if (! PyDict_Check (obj))
342 throw object_convert_exception ("failed to extract map: wrong type");
343
344 octave_scalar_map map;
345
346 Py_ssize_t pos = 0;
347 PyObject *py_key = 0;
348 PyObject *py_value = 0;
349
350 while (PyDict_Next (obj, &pos, &py_key, &py_value))
351 {
352 if (! PyBytes_Check (py_key) && ! PyUnicode_Check (py_key))
353 throw object_convert_exception
354 ("failed to extract map: bad key type");
355
356 std::string key = extract_py_str (py_key);
357 octave_value value = wrap_pyobj_to_octvalue (py_value);
358 map.setfield (key, value);
359 }
360
361 return map;
362 }
363
364 PyObject *
365 make_py_dict (const octave_scalar_map& map)
366 {
367 PyObject *dict = PyDict_New ();
368 if (! dict)
369 octave_throw_bad_alloc ();
370
371 for (auto p = map.begin (); p != map.end (); ++p)
372 {
373 PyObject *key = make_py_str (map.key (p));
374 if (! key)
375 octave_throw_bad_alloc ();
376
377 PyObject *item = wrap_octvalue_to_pyobj (map.contents (p));
378
379 if (PyDict_SetItem (dict, key, item) < 0)
380 throw boost::python::error_already_set ();
381 }
382
383 return dict;
384 }
385
386 int64_t
387 extract_py_int64 (PyObject *obj)
388 {
389 if (! obj)
390 throw object_convert_exception ("failed to extract integer: null object");
391
392 if (PyLong_Check (obj))
393 {
394 int overflow = 0;
395 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
396 PY_LONG_LONG value = PyLong_AsLongLongAndOverflow (obj, &overflow);
397 #else
398 long value = PyLong_AsLongAndOverflow (obj, &overflow);
399 #endif
400 if (overflow)
401 if (overflow > 0)
402 value = std::numeric_limits<int64_t>::max ();
403 else
404 value = std::numeric_limits<int64_t>::min ();
405 return static_cast<int64_t> (value);
406 }
407 #if PY_VERSION_HEX < 0x03000000
408 else if (PyInt_Check (obj))
409 return PyInt_AsLong (obj);
410 #endif
411 else
412 throw object_convert_exception ("failed to extract integer: wrong type");
413
414 return 0;
415 }
416
417 uint64_t
418 extract_py_uint64 (PyObject *obj)
419 {
420 if (! obj)
421 throw object_convert_exception ("failed to extract integer: null object");
422
423 if (PyLong_Check (obj))
424 {
425 // FIXME: if (value < 0), may be very implementation dependent
426 if (Py_SIZE (obj) < 0)
427 return 0;
428
429 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
430 unsigned PY_LONG_LONG value = PyLong_AsUnsignedLongLong (obj);
431 bool overflow = (value == static_cast<unsigned PY_LONG_LONG> (-1));
432 #else
433 unsigned long value = PyLong_AsUnsignedLong (obj);
434 bool overflow = (value == static_cast<unsigned long> (-1));
435 #endif
436 if (overflow)
437 {
438 value = std::numeric_limits<uint64_t>::max ();
439 PyErr_Clear ();
440 }
441
442 return static_cast<uint64_t> (value);
443 }
444 #if PY_VERSION_HEX < 0x03000000
445 else if (PyInt_Check (obj))
446 return static_cast<uint64_t> (PyInt_AsLong (obj));
447 #endif
448 else
449 throw object_convert_exception ("failed to extract integer: wrong type");
450
451 return 0;
452 }
453
454 PyObject *
455 make_py_tuple (const Cell& cell)
456 {
457 if (! (cell.is_empty () || cell.is_vector ()))
458 throw value_convert_exception (
459 "unable to convert multidimensional cell array into Python tuple");
460
461 octave_idx_type size = cell.numel ();
462 PyObject *tuple = PyTuple_New (size);
463 if (! tuple)
464 octave_throw_bad_alloc ();
465
466 for (octave_idx_type i = 0; i < size; ++i)
467 {
468 PyObject *item = wrap_octvalue_to_pyobj (cell.xelem (i));
469 PyTuple_SET_ITEM (tuple, i, item);
470 }
471
472 return tuple;
473 }
474
475 std::string
476 extract_py_str (PyObject *obj)
477 {
478 std::string retval;
479
480 if (! obj)
481 throw object_convert_exception ("failed to extract string: null object");
482 if (PyBytes_Check (obj))
483 {
484 retval.assign (PyBytes_AsString (obj), PyBytes_Size (obj));
485 }
486 else if (PyUnicode_Check (obj))
487 {
488 bool ok = false;
489 PyObject *enc = PyUnicode_AsUTF8String (obj);
490 if (enc)
491 {
492 if (PyBytes_Check (enc))
493 {
494 ok = true;
495 retval.assign (PyBytes_AsString (enc), PyBytes_Size (enc));
496 }
497 Py_DECREF (enc);
498 }
499 if (! ok)
500 throw object_convert_exception
501 ("failed to extract string: UTF-8 error");
502 }
503 else
504 throw object_convert_exception ("failed to extract string: wrong type");
505
506 return retval;
507 }
508
509 PyObject *
510 make_py_str (const std::string& str)
511 {
512 #if PY_VERSION_HEX >= 0x03000000
513 return PyUnicode_FromStringAndSize (str.data (), str.size ());
514 #else
515 return PyString_FromStringAndSize (str.data (), str.size ());
516 #endif
517 }
518
217 } 519 }
218
219 PyObject *
220 make_py_array (const FloatNDArray& nda)
221 {
222 return make_py_array (nda.data (), nda.numel () * sizeof (float), 'f');
223 }
224
225 template <typename T>
226 PyObject *
227 make_py_array (const intNDArray<T>& nda)
228 {
229 return make_py_array (nda.data (), nda.numel () * sizeof (T),
230 py_array_info<T>::typecode);
231 }
232
233 // Instantiate all possible integer array template functions needed
234
235 template PyObject * make_py_array<octave_int8> (const int8NDArray&);
236 template PyObject * make_py_array<octave_int16> (const int16NDArray&);
237 template PyObject * make_py_array<octave_int32> (const int32NDArray&);
238 template PyObject * make_py_array<octave_int64> (const int64NDArray&);
239 template PyObject * make_py_array<octave_uint8> (const uint8NDArray&);
240 template PyObject * make_py_array<octave_uint16> (const uint16NDArray&);
241 template PyObject * make_py_array<octave_uint32> (const uint32NDArray&);
242 template PyObject * make_py_array<octave_uint64> (const uint64NDArray&);
243
244 PyObject *
245 make_py_numeric_value (const octave_value& value)
246 {
247 if (value.is_scalar_type ())
248 {
249 if (value.is_bool_type ())
250 return make_py_bool (value.bool_value ());
251
252 else if (value.is_int8_type ())
253 return make_py_int (value.int8_scalar_value ().value ());
254 else if (value.is_int16_type ())
255 return make_py_int (value.int16_scalar_value ().value ());
256 else if (value.is_int32_type ())
257 return make_py_int (value.int32_scalar_value ().value ());
258 else if (value.is_int64_type ())
259 return make_py_int (value.int64_scalar_value ().value ());
260
261 else if (value.is_uint8_type ())
262 return make_py_int (value.uint8_scalar_value ().value ());
263 else if (value.is_uint16_type ())
264 return make_py_int (value.uint16_scalar_value ().value ());
265 else if (value.is_uint32_type ())
266 return make_py_int (value.uint32_scalar_value ().value ());
267 else if (value.is_uint64_type ())
268 return make_py_int (value.uint64_scalar_value ().value ());
269
270 else if (value.is_complex_type ())
271 return make_py_complex (value.complex_value ());
272 else if (value.is_float_type ())
273 return make_py_float (value.double_value ());
274 }
275
276 throw value_convert_exception ("unhandled scalar type");
277 return 0;
278 }
279
280 PyObject *
281 make_py_array (const octave_value& value)
282 {
283 if (value.is_numeric_type () && ! value.is_complex_type ()
284 && value.ndims () == 2 && (value.columns () <= 1 || value.rows () <= 1))
285 {
286 if (value.is_double_type ())
287 return make_py_array (value.array_value ());
288 else if (value.is_single_type ())
289 return make_py_array (value.float_array_value ());
290
291 else if (value.is_int8_type ())
292 return make_py_array (value.int8_array_value ());
293 else if (value.is_int16_type ())
294 return make_py_array (value.int16_array_value ());
295 else if (value.is_int32_type ())
296 return make_py_array (value.int32_array_value ());
297 else if (value.is_int64_type ())
298 return make_py_array (value.int64_array_value ());
299
300 else if (value.is_uint8_type ())
301 return make_py_array (value.uint8_array_value ());
302 else if (value.is_uint16_type ())
303 return make_py_array (value.uint16_array_value ());
304 else if (value.is_uint32_type ())
305 return make_py_array (value.uint32_array_value ());
306 else if (value.is_uint64_type ())
307 return make_py_array (value.uint64_array_value ());
308 }
309
310 throw value_convert_exception ("unhandled Octave numeric vector type");
311 return 0;
312 }
313
314 inline PyObject *
315 wrap_octvalue_to_pyobj (const octave_value& value)
316 {
317 boost::python::object obj;
318 octvalue_to_pyobj (obj, value);
319 PyObject *ptr = obj.ptr ();
320 Py_INCREF (ptr);
321 return ptr;
322 }
323
324 inline octave_value
325 wrap_pyobj_to_octvalue (PyObject *obj)
326 {
327 boost::python::object objref { boost::python::handle<> (boost::python::borrowed (obj)) };
328 octave_value value;
329 pyobj_to_octvalue (value, objref);
330 return value;
331 }
332
333 octave_scalar_map
334 extract_py_scalar_map (PyObject *obj)
335 {
336 if (! obj)
337 throw object_convert_exception ("failed to extract map: null object");
338
339 if (! PyDict_Check (obj))
340 throw object_convert_exception ("failed to extract map: wrong type");
341
342 octave_scalar_map map;
343
344 Py_ssize_t pos = 0;
345 PyObject *py_key = 0;
346 PyObject *py_value = 0;
347
348 while (PyDict_Next (obj, &pos, &py_key, &py_value))
349 {
350 if (! PyBytes_Check (py_key) && ! PyUnicode_Check (py_key))
351 throw object_convert_exception ("failed to extract map: bad key type");
352
353 std::string key = extract_py_str (py_key);
354 octave_value value = wrap_pyobj_to_octvalue (py_value);
355 map.setfield (key, value);
356 }
357
358 return map;
359 }
360
361 PyObject *
362 make_py_dict (const octave_scalar_map& map)
363 {
364 PyObject *dict = PyDict_New ();
365 if (! dict)
366 octave_throw_bad_alloc ();
367
368 for (auto p = map.begin (); p != map.end (); ++p)
369 {
370 PyObject *key = make_py_str (map.key (p));
371 if (! key)
372 octave_throw_bad_alloc ();
373
374 PyObject *item = wrap_octvalue_to_pyobj (map.contents (p));
375
376 if (PyDict_SetItem (dict, key, item) < 0)
377 throw boost::python::error_already_set ();
378 }
379
380 return dict;
381 }
382
383 int64_t
384 extract_py_int64 (PyObject *obj)
385 {
386 if (! obj)
387 throw object_convert_exception ("failed to extract integer: null object");
388
389 if (PyLong_Check (obj))
390 {
391 int overflow = 0;
392 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
393 PY_LONG_LONG value = PyLong_AsLongLongAndOverflow (obj, &overflow);
394 #else
395 long value = PyLong_AsLongAndOverflow (obj, &overflow);
396 #endif
397 if (overflow)
398 if (overflow > 0)
399 value = std::numeric_limits<int64_t>::max ();
400 else
401 value = std::numeric_limits<int64_t>::min ();
402 return static_cast<int64_t> (value);
403 }
404 #if PY_VERSION_HEX < 0x03000000
405 else if (PyInt_Check (obj))
406 return PyInt_AsLong (obj);
407 #endif
408 else
409 throw object_convert_exception ("failed to extract integer: wrong type");
410
411 return 0;
412 }
413
414 uint64_t
415 extract_py_uint64 (PyObject *obj)
416 {
417 if (! obj)
418 throw object_convert_exception ("failed to extract integer: null object");
419
420 if (PyLong_Check (obj))
421 {
422 // FIXME: if (value < 0), may be very implementation dependent
423 if (Py_SIZE (obj) < 0)
424 return 0;
425
426 #if (defined (HAVE_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
427 unsigned PY_LONG_LONG value = PyLong_AsUnsignedLongLong (obj);
428 bool overflow = (value == static_cast<unsigned PY_LONG_LONG> (-1));
429 #else
430 unsigned long value = PyLong_AsUnsignedLong (obj);
431 bool overflow = (value == static_cast<unsigned long> (-1));
432 #endif
433 if (overflow)
434 {
435 value = std::numeric_limits<uint64_t>::max ();
436 PyErr_Clear ();
437 }
438
439 return static_cast<uint64_t> (value);
440 }
441 #if PY_VERSION_HEX < 0x03000000
442 else if (PyInt_Check (obj))
443 return static_cast<uint64_t> (PyInt_AsLong (obj));
444 #endif
445 else
446 throw object_convert_exception ("failed to extract integer: wrong type");
447
448 return 0;
449 }
450
451 PyObject *
452 make_py_tuple (const Cell& cell)
453 {
454 if (! (cell.is_empty () || cell.is_vector ()))
455 throw value_convert_exception (
456 "unable to convert multidimensional cell array into Python tuple");
457
458 octave_idx_type size = cell.numel ();
459 PyObject *tuple = PyTuple_New (size);
460 if (! tuple)
461 octave_throw_bad_alloc ();
462
463 for (octave_idx_type i = 0; i < size; ++i)
464 {
465 PyObject *item = wrap_octvalue_to_pyobj (cell.xelem (i));
466 PyTuple_SET_ITEM (tuple, i, item);
467 }
468
469 return tuple;
470 }
471
472 std::string
473 extract_py_str (PyObject *obj)
474 {
475 std::string retval;
476
477 if (! obj)
478 throw object_convert_exception ("failed to extract string: null object");
479 if (PyBytes_Check (obj))
480 {
481 retval.assign (PyBytes_AsString (obj), PyBytes_Size (obj));
482 }
483 else if (PyUnicode_Check (obj))
484 {
485 bool ok = false;
486 PyObject *enc = PyUnicode_AsUTF8String (obj);
487 if (enc)
488 {
489 if (PyBytes_Check (enc))
490 {
491 ok = true;
492 retval.assign (PyBytes_AsString (enc), PyBytes_Size (enc));
493 }
494 Py_DECREF (enc);
495 }
496 if (! ok)
497 throw object_convert_exception ("failed to extract string: UTF-8 error");
498 }
499 else
500 throw object_convert_exception ("failed to extract string: wrong type");
501
502 return retval;
503 }
504
505 PyObject *
506 make_py_str (const std::string& str)
507 {
508 #if PY_VERSION_HEX >= 0x03000000
509 return PyUnicode_FromStringAndSize (str.data (), str.size ());
510 #else
511 return PyString_FromStringAndSize (str.data (), str.size ());
512 #endif
513 }
514
515 }