11 Object(PyObject *py) : mPy(py) { }
18 Object(
const std::string&);
19 Object(
const Point_2&);
22 Object(
const Bbox_2&);
24 static Object new_List(uint n, PyObject *v = 0);
25 static Object new_TupleOfLongs(
const Point_25 &v, Real s);
26 template<
typename T>
static Object new_TupleOfLongs(
const T *, uint size);
27 template<
typename T>
static Object new_ListFrom(
const std::vector<T>&,
auto&&...);
29 const Object& incRef()
const;
30 const Object& decRef()
const;
32 PyObject **o() {
return &mPy; }
33 PyObject *operator*()
const {
return mPy; }
35 Object at(uint i)
const;
36 Object elem(uint i,
const char *err = 0)
const;
37 Object item(uint i)
const;
38 Object item(
const char *name)
const;
40 void setElem(uint i,
const Object&)
const;
41 void setElem(uint i, PyObject *)
const;
42 void setItem(uint i,
const Object&)
const;
43 void setItem(uint i, PyObject *)
const;
44 void setDictItem(uint i, PyObject *)
const;
45 void setItem(
const char *name,
const Object&)
const;
46 void refItem(
const char *name,
const Object&)
const;
47 void setItem(
const char *name, PyObject *)
const;
48 void refItem(
const char *name, PyObject *)
const;
50 bool isNone()
const {
return mPy == Py_None; }
53 bool isList(uint n)
const;
54 bool hasListItem(uint i)
const;
56 bool isTuple(uint n)
const;
57 bool hasTupleElem(uint i)
const;
58 bool isTupleOrList(uint n)
const;
60 uint listSize(
const char *err =
"object is not a list")
const;
62 template<
typename T> T asIntegerContainer()
const;
63 template<
typename T> T asStringContainer()
const;
65 operator bool()
const;
67 template <
typename T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
68 operator T()
const =
delete;
71 bool isBool(
bool value)
const;
74 bool isNumber()
const;
75 bool asBool(
const char *err =
"object is not a boolean")
const;
77 double asDouble(
const char *err =
"object is not a float")
const;
78 double toDouble(
const char *err =
"object is not a number")
const;
80 long toLong(
const char *err =
"object is not a number")
const;
82 bool isString()
const;
83 std::string asString(
const char *err =
"object is not a string")
const;
84 std::string toString()
const;
85 std::string_view asStringView(
const char *err =
"object is not a string")
const;
87 bool isVector(uint n)
const;
88 bool isLongVector(uint n)
const;
89 bool isPoint_25()
const;
90 IPoint_2 asIPoint_2(
const char *err =
"object is not a 2D integer point")
const;
91 IPoint_3 asIPoint_3(
const char *err =
"object is not a 3D integer point")
const;
92 IVector_2 asIVector_2(
const char *err =
"object is not a 2D integer vector")
const;
93 IVector_3 asIVector_3(
const char *err =
"object is not a 3D integer vector")
const;
94 Vector_2 asVector_2(
const char *err =
"object is not a 2D vector")
const;
95 Point_2 asPoint_2(
const char *err =
"object is not a 2D point")
const;
96 Point_25 asPoint_25(
const char *err =
"object is not a 2.5D point")
const;
98 ::Bbox_2 asBbox_2()
const;
101 uint64_t asBitmask(uint size)
const;
109 BorrowedRef(PyObject *py = 0) : mRef(py) { }
110 Object* operator->() {
return &mRef; }
111 Object& operator*() {
return mRef; }
112 operator bool()
const {
return (
bool)mRef; }
120 ObjectRef(PyObject *, uint refs = 0);
122 void reset(PyObject *, uint refs = 0);
123 const Object* operator->()
const {
return &mRef; }
124 const Object& operator*()
const {
return mRef; }
125 PyObject *getRef()
const;
129inline ObjectRef::ObjectRef(PyObject *py, uint refs) : mRef(py)
134inline ObjectRef::~ObjectRef()
138inline PyObject *ObjectRef::getRef()
const
140 return *mRef.incRef();
142inline void ObjectRef::reset(PyObject *py, uint refs)
144 if (py && py == *mRef)
145 throw std::runtime_error(
"objectref reset object must differ");
147 throw std::runtime_error(
"objectref asked to reference 0");
156 DictIterator(PyObject *py);
163inline DictIterator::DictIterator(PyObject *py) : d(py), k(Py_None), v(Py_None)
166 throw std::invalid_argument(
"object is not a dictionary");
168inline bool DictIterator::next()
170 return PyDict_Next(*d, &pos, k.o(), v.o());
173inline Object::Object(
bool b) : mPy(PyBool_FromLong(b))
177inline Object::Object(
double d) : mPy(PyFloat_FromDouble(d))
181inline Object::Object(
long l) : mPy(PyLong_FromLong(l))
185inline Object::Object(
const char *s) : mPy(PyUnicode_FromString(s))
189inline Object::Object(
const std::string &s) : mPy(PyUnicode_FromStringAndSize(s.c_str(), s.size()))
193inline Object::Object(
const Point_2 &v) : mPy(PyTuple_New(2))
195 PyTuple_SetItem(mPy, 0, PyFloat_FromDouble(v.x()));
196 PyTuple_SetItem(mPy, 1, PyFloat_FromDouble(v.y()));
199inline Object::Object(
const Point_25 &v) : mPy(PyTuple_New(3))
201 PyTuple_SetItem(mPy, 0, PyFloat_FromDouble(v.x()));
202 PyTuple_SetItem(mPy, 1, PyFloat_FromDouble(v.y()));
203 PyTuple_SetItem(mPy, 2, PyLong_FromLong(v.z()));
206inline Object::Object(
const IPoint_3 &v) : mPy(PyTuple_New(3))
208 PyTuple_SetItem(mPy, 0, PyLong_FromLong(v.x));
209 PyTuple_SetItem(mPy, 1, PyLong_FromLong(v.y));
210 PyTuple_SetItem(mPy, 2, PyLong_FromLong(v.z));
213inline const Object& Object::incRef()
const
219inline const Object& Object::decRef()
const
226inline Object Object::new_List(uint n, PyObject *v)
228 auto py = PyList_New(n);
230 for (uint i = 0; i < n; ++i)
231 PyList_SetItem(py, i, NewRef(v));
235template<
typename T>
inline Object Object::new_ListFrom(
const std::vector<T> &data,
auto&&... args)
237 auto py = PyList_New(data.size());
238 for (uint i = 0; i < data.size(); ++i)
239 PyList_SetItem(py, i, data[i].getPy(std::forward<
decltype(args)>(args)...));
243inline Object Object::new_TupleOfLongs(
const Point_25 &v, Real s)
245 auto py = PyTuple_New(3);
246 PyTuple_SetItem(py, 0, PyFloat_FromDouble(v.x() * s));
247 PyTuple_SetItem(py, 1, PyFloat_FromDouble(v.y() * s));
248 PyTuple_SetItem(py, 2, PyLong_FromLong(v.z()));
251template<
typename T>
Object Object::new_TupleOfLongs(
const T *array, uint size)
253 auto py = PyTuple_New(size);
254 for (uint i = 0; i < size; ++i)
255 PyTuple_SetItem(py, i, PyLong_FromLong(array[i]));
259inline Object::operator bool()
const
261 return mPy && mPy != Py_None;
264inline bool Object::isBool()
const
266 return mPy && PyBool_Check(mPy);
268inline bool Object::isBool(
bool value)
const
270 return mPy == (value ? Py_True : Py_False);
273inline bool Object::isFloat()
const
275 return mPy && PyFloat_Check(mPy);
278inline bool Object::isLong()
const
280 return mPy && PyLong_Check(mPy);
283inline bool Object::isNumber()
const
285 return mPy && PyNumber_Check(mPy);
288inline bool Object::asBool(
const char *err)
const
290 if (err && !isBool())
291 throw std::invalid_argument(err);
292 return Py_IsTrue(mPy);
295inline bool Object::toBool()
const
297 return mPy && Py_IsTrue(mPy);
300inline double Object::asDouble(
const char *err)
const
303 throw std::invalid_argument(err);
304 return PyFloat_AsDouble(mPy);
307inline double Object::toDouble(
const char *err)
const
309 if (err && !isNumber())
310 throw std::invalid_argument(err);
313 auto F = PyNumber_Float(mPy);
316 return std::numeric_limits<double>::quiet_NaN();
317 auto d = PyFloat_AsDouble(F);
322inline long Object::asLong()
const
325 return PyLong_AsLong(mPy);
328inline long Object::toLong(
const char *err)
const
330 if (err && !PyNumber_Check(mPy))
331 throw std::invalid_argument(err);
334 auto L = PyNumber_Long(mPy);
338 auto li = PyLong_AsLong(L);
343inline bool Object::isString()
const
345 return mPy && PyUnicode_Check(mPy);
348inline std::string Object::asString(
const char *err)
const
350 if (err && !isString())
351 throw std::invalid_argument(err);
353#if PY_VERSION_HEX >= 0x03030000
354 return std::string(PyUnicode_AsUTF8(mPy));
356#error "Python version < 3.3 not supported, go upgrade!"
360inline std::string Object::toString()
const
366 return ObjectRef(PyObject_Str(mPy))->asString();
369inline std::string_view Object::asStringView(
const char *err)
const
371 if (err && !isString())
372 throw std::invalid_argument(err);
374#if PY_VERSION_HEX >= 0x03030000
376 const char *ucs = PyUnicode_AsUTF8AndSize(mPy, &size);
377 return std::string_view(ucs, size);
379#error "Python version < 3.3 not supported, go upgrade!"
383inline bool Object::isDict()
const
385 return mPy && PyDict_Check(mPy);
387inline bool Object::isList()
const
389 return mPy && PyList_Check(mPy);
391inline bool Object::isList(uint n)
const
393 return isList() && PyList_Size(mPy) == n;
395inline bool Object::hasListItem(uint i)
const
397 return isList() && PyList_Size(mPy) > i;
399inline bool Object::isTuple()
const
401 return mPy && PyTuple_Check(mPy);
403inline bool Object::isTuple(uint n)
const
405 return isTuple() && PyTuple_Size(mPy) == n;
407inline bool Object::hasTupleElem(uint i)
const
409 return isTuple() && PyTuple_Size(mPy) > i;
411inline bool Object::isTupleOrList(uint n)
const
413 return isTuple(n) || isList(n);
416template<
typename T> T Object::asIntegerContainer()
const
418 auto I = PyObject_GetIter(mPy);
420 throw std::invalid_argument(
"object is not an iterable");
422 while (
auto v = PyIter_Next(I)) {
423 if (!PyLong_Check(v))
424 throw std::invalid_argument(
"expected an iterable of integers");
425 res.insert(res.end(), PyLong_AsLong(v));
431template<
typename T> T Object::asStringContainer()
const
433 auto I = PyObject_GetIter(mPy);
435 throw std::invalid_argument(
"object is not an iterable");
437 while (
auto _v = PyIter_Next(I)) {
440 throw std::invalid_argument(
"expected an iterable of strings");
441 res.insert(res.end(), v.asString());
448inline Object Object::at(uint i)
const
453 throw std::invalid_argument(
"expected a list or tuple");
456inline Object Object::elem(uint i,
const char *err)
const
458 if (err && !hasTupleElem(i))
459 throw std::invalid_argument(err);
460 assert(hasTupleElem(i));
461 return PyTuple_GetItem(mPy, i);
463inline Object Object::item(uint i)
const
465 assert(hasListItem(i));
466 return PyList_GetItem(mPy, i);
468inline Object Object::item(
const char *name)
const
471 return PyDict_GetItemString(mPy, name);
474inline void Object::setElem(uint i,
const Object &v)
const
478inline void Object::setElem(uint i, PyObject *v)
const
480 assert(hasTupleElem(i));
481 PyTuple_SetItem(mPy, i, v);
484inline void Object::setItem(uint i,
const Object &v)
const
488inline void Object::setItem(uint i, PyObject *v)
const
490 assert(hasListItem(i));
491 PyList_SetItem(mPy, i, v);
494inline void Object::setItem(
const char *name,
const Object &v)
const
498inline void Object::setItem(
const char *name, PyObject *v)
const
502 PyDict_SetItemString(mPy, name, v);
505inline void Object::setDictItem(uint i, PyObject *v)
const
508 PyDict_SetItem(mPy, PyLong_FromLong(i), v);
511inline void Object::refItem(
const char *name, PyObject *v)
const
514 PyDict_SetItemString(mPy, name, v);
516inline void Object::refItem(
const char *name,
const Object &v)
const
521inline bool Object::isVector(uint n)
const
525 for (uint i = 0; i < n; ++i)
526 if (!elem(i).isNumber())
530inline bool Object::isLongVector(uint n)
const
534 for (uint i = 0; i < n; ++i)
535 if (!elem(i).isLong())
539inline bool Object::isPoint_25()
const
541 return isTuple(3) && elem(0).isNumber() && elem(1).isNumber() && elem(2).isLong();
544inline IPoint_2 Object::asIPoint_2(
const char *err)
const
546 if (err && !isLongVector(2))
547 throw std::invalid_argument(err);
548 return IPoint_2(elem(0).asLong(), elem(1).asLong());
551inline IPoint_3 Object::asIPoint_3(
const char *err)
const
553 if (err && !isLongVector(3))
554 throw std::invalid_argument(err);
555 return IPoint_3(elem(0).asLong(), elem(1).asLong(), elem(2).asLong());
558inline IVector_2 Object::asIVector_2(
const char *err)
const
560 if (err && !isLongVector(2))
561 throw std::invalid_argument(err);
562 return IVector_2(elem(0).asLong(), elem(1).asLong());
565inline IVector_3 Object::asIVector_3(
const char *err)
const
567 if (err && !isLongVector(3))
568 throw std::invalid_argument(err);
569 return IVector_3(elem(0).asLong(), elem(1).asLong(), elem(2).asLong());
572inline Vector_2 Object::asVector_2(
const char *err)
const
574 if (err && !isVector(2))
575 throw std::invalid_argument(err);
576 return Vector_2(elem(0).toDouble(), elem(1).toDouble());
579inline Point_2 Object::asPoint_2(
const char *err)
const
581 if (err && !isVector(2))
582 throw std::invalid_argument(
"object is not a 2D point");
583 return Point_2(elem(0).toDouble(), elem(1).toDouble());
586inline Point_25 Object::asPoint_25(
const char *err)
const
588 if (err && !isPoint_25())
589 throw std::invalid_argument(err);
590 return Point_25(elem(0).toDouble(), elem(1).toDouble(), elem(2).asLong());
593inline uint Object::listSize(
const char *err)
const
595 if (err && !PyList_Check(mPy))
596 throw std::invalid_argument(err);
597 return PyList_Size(mPy);
Definition IPoint2.hpp:37
Definition IPoint3.hpp:36
Definition IPoint2.hpp:10
Definition Geometry.hpp:131
NOTE: This does not do any automatic reference counting.
Definition PyObject.hpp:9
Definition IPoint3.hpp:60