TIVI-320: Add dbus-python to repos to support connman-test
[profile/ivi/dbus-python.git] / _dbus_bindings / int.c
1 /* Simple D-Bus types: integers of various sizes, and ObjectPath.
2  *
3  * Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use, copy,
9  * modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25
26 #include "types-internal.h"
27
28 /* Specific types =================================================== */
29
30 /* Boolean, a subclass of DBusPythonInt ============================= */
31
32 PyDoc_STRVAR(Boolean_tp_doc,
33 "A boolean, represented as a subtype of `int` (not `bool`, because `bool`\n"
34 "cannot be subclassed).\n"
35 "\n"
36 "Constructor::\n"
37 "\n"
38 "    dbus.Boolean(value[, variant_level]) -> Boolean\n"
39 "\n"
40 "``value`` is converted to 0 or 1 as if by ``int(bool(value))``.\n"
41 "\n"
42 "``variant_level`` must be non-negative; the default is 0.\n"
43 "\n"
44 ":IVariables:\n"
45 "  `variant_level` : int\n"
46 "    Indicates how many nested Variant containers this object\n"
47 "    is contained in: if a message's wire format has a variant containing a\n"
48 "    variant containing a boolean, this is represented in Python by a\n"
49 "    Boolean with variant_level==2.\n"
50 );
51
52 static PyObject *
53 Boolean_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
54 {
55     PyObject *tuple, *self, *value = Py_None;
56     long variantness = 0;
57     static char *argnames[] = {"_", "variant_level", NULL};
58
59     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ol:__new__", argnames,
60                                      &value, &variantness)) return NULL;
61     if (variantness < 0) {
62         PyErr_SetString(PyExc_ValueError,
63                         "variant_level must be non-negative");
64         return NULL;
65     }
66     tuple = Py_BuildValue("(i)", PyObject_IsTrue(value) ? 1 : 0);
67     if (!tuple) return NULL;
68     self = (DBusPyIntBase_Type.tp_new)(cls, tuple, kwargs);
69     Py_DECREF(tuple);
70     return self;
71 }
72
73 static PyObject *
74 Boolean_tp_repr (PyObject *self)
75 {
76     long variant_level = ((DBusPyIntBase *)self)->variant_level;
77     if (variant_level > 0) {
78         return PyString_FromFormat("%s(%s, variant_level=%ld)",
79                                    self->ob_type->tp_name,
80                                    PyInt_AsLong(self) ? "True" : "False",
81                                    variant_level);
82     }
83     return PyString_FromFormat("%s(%s)",
84                                self->ob_type->tp_name,
85                                PyInt_AsLong(self) ? "True" : "False");
86 }
87
88 PyTypeObject DBusPyBoolean_Type = {
89     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
90     0,
91     "dbus.Boolean",
92     0,
93     0,
94     0,                                      /* tp_dealloc */
95     0,                                      /* tp_print */
96     0,                                      /* tp_getattr */
97     0,                                      /* tp_setattr */
98     0,                                      /* tp_compare */
99     Boolean_tp_repr,                        /* tp_repr */
100     0,                                      /* tp_as_number */
101     0,                                      /* tp_as_sequence */
102     0,                                      /* tp_as_mapping */
103     0,                                      /* tp_hash */
104     0,                                      /* tp_call */
105     0,                                      /* tp_str */
106     0,                                      /* tp_getattro */
107     0,                                      /* tp_setattro */
108     0,                                      /* tp_as_buffer */
109     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
110     Boolean_tp_doc,                         /* tp_doc */
111     0,                                      /* tp_traverse */
112     0,                                      /* tp_clear */
113     0,                                      /* tp_richcompare */
114     0,                                      /* tp_weaklistoffset */
115     0,                                      /* tp_iter */
116     0,                                      /* tp_iternext */
117     0,                                      /* tp_methods */
118     0,                                      /* tp_members */
119     0,                                      /* tp_getset */
120     DEFERRED_ADDRESS(&DBusPyIntBase_Type),  /* tp_base */
121     0,                                      /* tp_dict */
122     0,                                      /* tp_descr_get */
123     0,                                      /* tp_descr_set */
124     0,                                      /* tp_dictoffset */
125     0,                                      /* tp_init */
126     0,                                      /* tp_alloc */
127     Boolean_tp_new,                         /* tp_new */
128 };
129
130 /* Int16 ============================================================ */
131
132 PyDoc_STRVAR(Int16_tp_doc,
133 "A signed 16-bit integer between -0x8000 and +0x7FFF, represented as\n"
134 "a subtype of `int`.\n"
135 "\n"
136 "Constructor::\n"
137 "\n"
138 "    dbus.Int16(value: int[, variant_level: int]) -> Int16\n"
139 "\n"
140 "value must be within the allowed range, or OverflowError will be\n"
141 "raised.\n"
142 "\n"
143 "    variant_level must be non-negative; the default is 0.\n"
144 "\n"
145 ":IVariables:\n"
146 "  `variant_level` : int\n"
147 "    Indicates how many nested Variant containers this object\n"
148 "    is contained in: if a message's wire format has a variant containing a\n"
149 "    variant containing an int16, this is represented in Python by an\n"
150 "    Int16 with variant_level==2.\n"
151 );
152
153 dbus_int16_t
154 dbus_py_int16_range_check(PyObject *obj)
155 {
156     long i = PyInt_AsLong (obj);
157     if (i == -1 && PyErr_Occurred ()) return -1;
158     if (i < -0x8000 || i > 0x7fff) {
159         PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int16",
160                      (int)i);
161         return -1;
162     }
163     return i;
164 }
165
166 static PyObject *
167 Int16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
168 {
169     PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
170     if (self && dbus_py_int16_range_check(self) == -1 && PyErr_Occurred()) {
171         Py_DECREF(self);
172         return NULL;
173     }
174     return self;
175 }
176
177 PyTypeObject DBusPyInt16_Type = {
178     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
179     0,
180     "dbus.Int16",
181     0,
182     0,
183     0,                                      /* tp_dealloc */
184     0,                                      /* tp_print */
185     0,                                      /* tp_getattr */
186     0,                                      /* tp_setattr */
187     0,                                      /* tp_compare */
188     0,                                      /* tp_repr */
189     0,                                      /* tp_as_number */
190     0,                                      /* tp_as_sequence */
191     0,                                      /* tp_as_mapping */
192     0,                                      /* tp_hash */
193     0,                                      /* tp_call */
194     0,                                      /* tp_str */
195     0,                                      /* tp_getattro */
196     0,                                      /* tp_setattro */
197     0,                                      /* tp_as_buffer */
198     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
199     Int16_tp_doc,                           /* tp_doc */
200     0,                                      /* tp_traverse */
201     0,                                      /* tp_clear */
202     0,                                      /* tp_richcompare */
203     0,                                      /* tp_weaklistoffset */
204     0,                                      /* tp_iter */
205     0,                                      /* tp_iternext */
206     0,                                      /* tp_methods */
207     0,                                      /* tp_members */
208     0,                                      /* tp_getset */
209     DEFERRED_ADDRESS(&DBusPyIntBase_Type),  /* tp_base */
210     0,                                      /* tp_dict */
211     0,                                      /* tp_descr_get */
212     0,                                      /* tp_descr_set */
213     0,                                      /* tp_dictoffset */
214     0,                                      /* tp_init */
215     0,                                      /* tp_alloc */
216     Int16_tp_new,                           /* tp_new */
217 };
218
219 /* UInt16 =========================================================== */
220
221 PyDoc_STRVAR(UInt16_tp_doc,
222 "An unsigned 16-bit integer between 0 and 0xFFFF, represented as\n"
223 "a subtype of `int`.\n"
224 "\n"
225 "Constructor::\n"
226 "\n"
227 "    dbus.UInt16(value: int[, variant_level: int]) -> UInt16\n"
228 "\n"
229 "``value`` must be within the allowed range, or `OverflowError` will be\n"
230 "raised.\n"
231 "\n"
232 "``variant_level`` must be non-negative; the default is 0.\n"
233 "\n"
234 ":IVariables:\n"
235 "  `variant_level` : int\n"
236 "    Indicates how many nested Variant containers this object\n"
237 "    is contained in: if a message's wire format has a variant containing a\n"
238 "    variant containing a uint16, this is represented in Python by a\n"
239 "    UInt16 with variant_level==2.\n"
240 );
241
242 dbus_uint16_t
243 dbus_py_uint16_range_check(PyObject *obj)
244 {
245     long i = PyInt_AsLong(obj);
246     if (i == -1 && PyErr_Occurred()) return (dbus_uint16_t)(-1);
247     if (i < 0 || i > 0xffff) {
248         PyErr_Format(PyExc_OverflowError, "Value %d out of range for UInt16",
249                      (int)i);
250         return (dbus_uint16_t)(-1);
251     }
252     return i;
253 }
254
255 static PyObject *
256 UInt16_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
257 {
258     PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
259     if (self && dbus_py_uint16_range_check(self) == (dbus_uint16_t)(-1)
260         && PyErr_Occurred()) {
261         Py_DECREF (self);
262         return NULL;
263     }
264     return self;
265 }
266
267 PyTypeObject DBusPyUInt16_Type = {
268     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
269     0,
270     "dbus.UInt16",
271     0,
272     0,
273     0,                                      /* tp_dealloc */
274     0,                                      /* tp_print */
275     0,                                      /* tp_getattr */
276     0,                                      /* tp_setattr */
277     0,                                      /* tp_compare */
278     0,                                      /* tp_repr */
279     0,                                      /* tp_as_number */
280     0,                                      /* tp_as_sequence */
281     0,                                      /* tp_as_mapping */
282     0,                                      /* tp_hash */
283     0,                                      /* tp_call */
284     0,                                      /* tp_str */
285     0,                                      /* tp_getattro */
286     0,                                      /* tp_setattro */
287     0,                                      /* tp_as_buffer */
288     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
289     UInt16_tp_doc,                          /* tp_doc */
290     0,                                      /* tp_traverse */
291     0,                                      /* tp_clear */
292     0,                                      /* tp_richcompare */
293     0,                                      /* tp_weaklistoffset */
294     0,                                      /* tp_iter */
295     0,                                      /* tp_iternext */
296     0,                                      /* tp_methods */
297     0,                                      /* tp_members */
298     0,                                      /* tp_getset */
299     DEFERRED_ADDRESS(&DBusPyIntBase_Type),   /* tp_base */
300     0,                                      /* tp_dict */
301     0,                                      /* tp_descr_get */
302     0,                                      /* tp_descr_set */
303     0,                                      /* tp_dictoffset */
304     0,                                      /* tp_init */
305     0,                                      /* tp_alloc */
306     UInt16_tp_new,                          /* tp_new */
307 };
308
309 /* Int32 ============================================================ */
310
311 PyDoc_STRVAR(Int32_tp_doc,
312 "A signed 32-bit integer between -0x8000 0000 and +0x7FFF FFFF, represented as\n"
313 "a subtype of `int`.\n"
314 "\n"
315 "Constructor::\n"
316 "\n"
317 "    dbus.Int32(value: int[, variant_level: int]) -> Int32\n"
318 "\n"
319 "``value`` must be within the allowed range, or `OverflowError` will be\n"
320 "raised.\n"
321 "\n"
322 "``variant_level`` must be non-negative; the default is 0.\n"
323 "\n"
324 ":IVariables:\n"
325 "  `variant_level` : int\n"
326 "    Indicates how many nested Variant containers this object\n"
327 "    is contained in: if a message's wire format has a variant containing a\n"
328 "    variant containing an int32, this is represented in Python by an\n"
329 "    Int32 with variant_level==2.\n"
330 );
331
332 dbus_int32_t
333 dbus_py_int32_range_check(PyObject *obj)
334 {
335     long i = PyInt_AsLong(obj);
336     if (i == -1 && PyErr_Occurred()) return -1;
337     if (i < INT32_MIN || i > INT32_MAX) {
338         PyErr_Format(PyExc_OverflowError, "Value %d out of range for Int32",
339                      (int)i);
340         return -1;
341     }
342     return i;
343 }
344
345 static PyObject *
346 Int32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
347 {
348     PyObject *self = (DBusPyIntBase_Type.tp_new)(cls, args, kwargs);
349     if (self && dbus_py_int32_range_check(self) == -1 && PyErr_Occurred()) {
350         Py_DECREF(self);
351         return NULL;
352     }
353     return self;
354 }
355
356 PyTypeObject DBusPyInt32_Type = {
357     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
358     0,
359     "dbus.Int32",
360     0,
361     0,
362     0,                                      /* tp_dealloc */
363     0,                                      /* tp_print */
364     0,                                      /* tp_getattr */
365     0,                                      /* tp_setattr */
366     0,                                      /* tp_compare */
367     0,                                      /* tp_repr */
368     0,                                      /* tp_as_number */
369     0,                                      /* tp_as_sequence */
370     0,                                      /* tp_as_mapping */
371     0,                                      /* tp_hash */
372     0,                                      /* tp_call */
373     0,                                      /* tp_str */
374     0,                                      /* tp_getattro */
375     0,                                      /* tp_setattro */
376     0,                                      /* tp_as_buffer */
377     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
378     Int32_tp_doc,                           /* tp_doc */
379     0,                                      /* tp_traverse */
380     0,                                      /* tp_clear */
381     0,                                      /* tp_richcompare */
382     0,                                      /* tp_weaklistoffset */
383     0,                                      /* tp_iter */
384     0,                                      /* tp_iternext */
385     0,                                      /* tp_methods */
386     0,                                      /* tp_members */
387     0,                                      /* tp_getset */
388     DEFERRED_ADDRESS(&DBusPyIntBase_Type),   /* tp_base */
389     0,                                      /* tp_dict */
390     0,                                      /* tp_descr_get */
391     0,                                      /* tp_descr_set */
392     0,                                      /* tp_dictoffset */
393     0,                                      /* tp_init */
394     0,                                      /* tp_alloc */
395     Int32_tp_new,                           /* tp_new */
396 };
397
398 /* UInt32 =========================================================== */
399
400 PyDoc_STRVAR(UInt32_tp_doc,
401 "An unsigned 32-bit integer between 0 and 0xFFFF FFFF, represented as a\n"
402 "subtype of `long`.\n"
403 "\n"
404 "Note that this may be changed in future to be a subtype of `int` on\n"
405 "64-bit platforms; applications should not rely on either behaviour.\n"
406 "\n"
407 "Constructor::\n"
408 "\n"
409 "    dbus.UInt32(value: long[, variant_level: int]) -> UInt32\n"
410 "\n"
411 "``value`` must be within the allowed range, or `OverflowError` will be\n"
412 "raised.\n"
413 "\n"
414 "``variant_level`` must be non-negative; the default is 0.\n"
415 "\n"
416 ":IVariables:\n"
417 "  `variant_level` : int\n"
418 "    Indicates how many nested Variant containers this object\n"
419 "    is contained in: if a message's wire format has a variant containing a\n"
420 "    variant containing a uint32, this is represented in Python by a\n"
421 "    UInt32 with variant_level==2.\n"
422 );
423
424 dbus_uint32_t
425 dbus_py_uint32_range_check(PyObject *obj)
426 {
427     unsigned long i;
428     PyObject *long_obj = PyNumber_Long(obj);
429
430     if (!long_obj) return (dbus_uint32_t)(-1);
431     i = PyLong_AsUnsignedLong(long_obj);
432     if (i == (unsigned long)(-1) && PyErr_Occurred()) {
433         Py_DECREF(long_obj);
434         return (dbus_uint32_t)(-1);
435     }
436     if (i > UINT32_MAX) {
437         PyErr_Format(PyExc_OverflowError, "Value %d out of range for UInt32",
438                      (int)i);
439         Py_DECREF(long_obj);
440         return (dbus_uint32_t)(-1);
441     }
442     Py_DECREF(long_obj);
443     return i;
444 }
445
446 static PyObject *
447 UInt32_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
448 {
449     PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
450     if (self && dbus_py_uint32_range_check(self) == (dbus_uint32_t)(-1)
451         && PyErr_Occurred()) {
452         Py_DECREF(self);
453         return NULL;
454     }
455     return self;
456 }
457
458 PyTypeObject DBusPyUInt32_Type = {
459     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
460     0,
461     "dbus.UInt32",
462     0,
463     0,
464     0,                                      /* tp_dealloc */
465     0,                                      /* tp_print */
466     0,                                      /* tp_getattr */
467     0,                                      /* tp_setattr */
468     0,                                      /* tp_compare */
469     0,                                      /* tp_repr */
470     0,                                      /* tp_as_number */
471     0,                                      /* tp_as_sequence */
472     0,                                      /* tp_as_mapping */
473     0,                                      /* tp_hash */
474     0,                                      /* tp_call */
475     0,                                      /* tp_str */
476     0,                                      /* tp_getattro */
477     0,                                      /* tp_setattro */
478     0,                                      /* tp_as_buffer */
479     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
480     UInt32_tp_doc,                          /* tp_doc */
481     0,                                      /* tp_traverse */
482     0,                                      /* tp_clear */
483     0,                                      /* tp_richcompare */
484     0,                                      /* tp_weaklistoffset */
485     0,                                      /* tp_iter */
486     0,                                      /* tp_iternext */
487     0,                                      /* tp_methods */
488     0,                                      /* tp_members */
489     0,                                      /* tp_getset */
490     DEFERRED_ADDRESS(&DBusPyLongBase_Type),  /* tp_base */
491     0,                                      /* tp_dict */
492     0,                                      /* tp_descr_get */
493     0,                                      /* tp_descr_set */
494     0,                                      /* tp_dictoffset */
495     0,                                      /* tp_init */
496     0,                                      /* tp_alloc */
497     UInt32_tp_new,                          /* tp_new */
498 };
499
500 /* Int64 =========================================================== */
501
502 PyDoc_STRVAR(Int64_tp_doc,
503 "A signed 64-bit integer between -0x8000 0000 0000 0000 and\n"
504 "+0x7FFF FFFF FFFF FFFF, represented as a subtype of `long`.\n"
505 "\n"
506 "Note that this may be changed in future to be a subtype of `int` on\n"
507 "64-bit platforms; applications should not rely on either behaviour.\n"
508 "\n"
509 "This type only works on platforms where the C compiler has suitable\n"
510 "64-bit types, such as C99 ``long long``.\n"
511 "\n"
512 "Constructor::\n"
513 "\n"
514 "    dbus.Int64(value: long[, variant_level: int]) -> Int64\n"
515 "\n"
516 "``value`` must be within the allowed range, or `OverflowError` will be\n"
517 "raised.\n"
518 "\n"
519 "``variant_level`` must be non-negative; the default is 0.\n"
520 "\n"
521 ":IVariables:\n"
522 "  `variant_level` : int\n"
523 "    Indicates how many nested Variant containers this object\n"
524 "    is contained in: if a message's wire format has a variant containing a\n"
525 "    variant containing an int64, this is represented in Python by an\n"
526 "    Int64 with variant_level==2.\n"
527 );
528
529 #ifdef DBUS_PYTHON_64_BIT_WORKS
530 dbus_int64_t
531 dbus_py_int64_range_check(PyObject *obj)
532 {
533     PY_LONG_LONG i;
534     PyObject *long_obj = PyNumber_Long(obj);
535
536     if (!long_obj) return -1;
537     i = PyLong_AsLongLong(long_obj);
538     if (i == -1 && PyErr_Occurred()) {
539         Py_DECREF(long_obj);
540         return -1;
541     }
542     if (i < INT64_MIN || i > INT64_MAX) {
543         PyErr_SetString(PyExc_OverflowError, "Value out of range for Int64");
544         Py_DECREF(long_obj);
545         return -1;
546     }
547     Py_DECREF(long_obj);
548     return i;
549 }
550 #endif
551
552 static PyObject *
553 Int64_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
554 {
555 #ifdef DBUS_PYTHON_64_BIT_WORKS
556     PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
557     if (self && dbus_py_int64_range_check(self) == -1 && PyErr_Occurred()) {
558         Py_DECREF(self);
559         return NULL;
560     }
561     return self;
562 #else
563     PyErr_SetString(PyExc_NotImplementedError,
564                     "64-bit types are not available on this platform");
565     return NULL;
566 #endif
567 }
568
569 PyTypeObject DBusPyInt64_Type = {
570     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
571     0,
572     "dbus.Int64",
573     0,
574     0,
575     0,                                      /* tp_dealloc */
576     0,                                      /* tp_print */
577     0,                                      /* tp_getattr */
578     0,                                      /* tp_setattr */
579     0,                                      /* tp_compare */
580     0,                                      /* tp_repr */
581     0,                                      /* tp_as_number */
582     0,                                      /* tp_as_sequence */
583     0,                                      /* tp_as_mapping */
584     0,                                      /* tp_hash */
585     0,                                      /* tp_call */
586     0,                                      /* tp_str */
587     0,                                      /* tp_getattro */
588     0,                                      /* tp_setattro */
589     0,                                      /* tp_as_buffer */
590     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
591     Int64_tp_doc,                           /* tp_doc */
592     0,                                      /* tp_traverse */
593     0,                                      /* tp_clear */
594     0,                                      /* tp_richcompare */
595     0,                                      /* tp_weaklistoffset */
596     0,                                      /* tp_iter */
597     0,                                      /* tp_iternext */
598     0,                                      /* tp_methods */
599     0,                                      /* tp_members */
600     0,                                      /* tp_getset */
601     DEFERRED_ADDRESS(&DBusPyLongBase_Type),  /* tp_base */
602     0,                                      /* tp_dict */
603     0,                                      /* tp_descr_get */
604     0,                                      /* tp_descr_set */
605     0,                                      /* tp_dictoffset */
606     0,                                      /* tp_init */
607     0,                                      /* tp_alloc */
608     Int64_tp_new,                           /* tp_new */
609 };
610
611 /* UInt64 =========================================================== */
612
613 PyDoc_STRVAR(UInt64_tp_doc,
614 "An unsigned 64-bit integer between 0 and 0xFFFF FFFF FFFF FFFF,\n"
615 "represented as a subtype of `long`.\n"
616 "\n"
617 "This type only exists on platforms where the C compiler has suitable\n"
618 "64-bit types, such as C99 ``unsigned long long``.\n"
619 "\n"
620 "Constructor::\n"
621 "\n"
622 "    dbus.UInt64(value: long[, variant_level: int]) -> UInt64\n"
623 "\n"
624 "``value`` must be within the allowed range, or `OverflowError` will be\n"
625 "raised.\n"
626 "\n"
627 "``variant_level`` must be non-negative; the default is 0.\n"
628 "\n"
629 ":IVariables:\n"
630 "  `variant_level` : int\n"
631 "    Indicates how many nested Variant containers this object\n"
632 "    is contained in: if a message's wire format has a variant containing a\n"
633 "    variant containing a uint64, this is represented in Python by a\n"
634 "    UInt64 with variant_level==2.\n"
635 );
636
637 dbus_uint64_t
638 dbus_py_uint64_range_check(PyObject *obj)
639 {
640     unsigned PY_LONG_LONG i;
641     PyObject *long_obj = PyNumber_Long(obj);
642
643     if (!long_obj) return (dbus_uint64_t)(-1);
644     i = PyLong_AsUnsignedLongLong(long_obj);
645     if (i == (unsigned PY_LONG_LONG)(-1) && PyErr_Occurred()) {
646         Py_DECREF(long_obj);
647         return (dbus_uint64_t)(-1);
648     }
649     if (i > UINT64_MAX) {
650         PyErr_SetString(PyExc_OverflowError, "Value out of range for UInt64");
651         Py_DECREF(long_obj);
652         return (dbus_uint64_t)(-1);
653     }
654     Py_DECREF(long_obj);
655     return i;
656 }
657
658 static PyObject *
659 UInt64_tp_new (PyTypeObject *cls, PyObject *args, PyObject *kwargs)
660 {
661 #ifdef DBUS_PYTHON_64_BIT_WORKS
662     PyObject *self = (DBusPyLongBase_Type.tp_new)(cls, args, kwargs);
663     if (self && dbus_py_uint64_range_check(self) == (dbus_uint64_t)(-1)
664         && PyErr_Occurred()) {
665         Py_DECREF(self);
666         return NULL;
667     }
668     return self;
669 #else
670     PyErr_SetString(PyExc_NotImplementedError,
671                     "64-bit integer types are not supported on this platform");
672     return NULL;
673 #endif
674 }
675
676 PyTypeObject DBusPyUInt64_Type = {
677     PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
678     0,
679     "dbus.UInt64",
680     0,
681     0,
682     0,                                      /* tp_dealloc */
683     0,                                      /* tp_print */
684     0,                                      /* tp_getattr */
685     0,                                      /* tp_setattr */
686     0,                                      /* tp_compare */
687     0,                                      /* tp_repr */
688     0,                                      /* tp_as_number */
689     0,                                      /* tp_as_sequence */
690     0,                                      /* tp_as_mapping */
691     0,                                      /* tp_hash */
692     0,                                      /* tp_call */
693     0,                                      /* tp_str */
694     0,                                      /* tp_getattro */
695     0,                                      /* tp_setattro */
696     0,                                      /* tp_as_buffer */
697     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
698     UInt64_tp_doc,                          /* tp_doc */
699     0,                                      /* tp_traverse */
700     0,                                      /* tp_clear */
701     0,                                      /* tp_richcompare */
702     0,                                      /* tp_weaklistoffset */
703     0,                                      /* tp_iter */
704     0,                                      /* tp_iternext */
705     0,                                      /* tp_methods */
706     0,                                      /* tp_members */
707     0,                                      /* tp_getset */
708     DEFERRED_ADDRESS(&DBusPyLongBase_Type),  /* tp_base */
709     0,                                      /* tp_dict */
710     0,                                      /* tp_descr_get */
711     0,                                      /* tp_descr_set */
712     0,                                      /* tp_dictoffset */
713     0,                                      /* tp_init */
714     0,                                      /* tp_alloc */
715     UInt64_tp_new,                          /* tp_new */
716 };
717
718 dbus_bool_t
719 dbus_py_init_int_types(void)
720 {
721     DBusPyInt16_Type.tp_base = &DBusPyIntBase_Type;
722     if (PyType_Ready(&DBusPyInt16_Type) < 0) return 0;
723     /* disable the tp_print copied from PyInt_Type, so tp_repr gets called as
724     desired */
725     DBusPyInt16_Type.tp_print = NULL;
726
727     DBusPyUInt16_Type.tp_base = &DBusPyIntBase_Type;
728     if (PyType_Ready(&DBusPyUInt16_Type) < 0) return 0;
729     DBusPyUInt16_Type.tp_print = NULL;
730
731     DBusPyInt32_Type.tp_base = &DBusPyIntBase_Type;
732     if (PyType_Ready(&DBusPyInt32_Type) < 0) return 0;
733     DBusPyInt32_Type.tp_print = NULL;
734
735     DBusPyUInt32_Type.tp_base = &DBusPyLongBase_Type;
736     if (PyType_Ready(&DBusPyUInt32_Type) < 0) return 0;
737     DBusPyUInt32_Type.tp_print = NULL;
738
739 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
740     DBusPyInt64_Type.tp_base = &DBusPyLongBase_Type;
741     if (PyType_Ready(&DBusPyInt64_Type) < 0) return 0;
742     DBusPyInt64_Type.tp_print = NULL;
743
744     DBusPyUInt64_Type.tp_base = &DBusPyLongBase_Type;
745     if (PyType_Ready(&DBusPyUInt64_Type) < 0) return 0;
746     DBusPyUInt64_Type.tp_print = NULL;
747 #endif
748     return 1;
749 }
750
751 dbus_bool_t
752 dbus_py_insert_int_types(PyObject *this_module)
753 {
754     Py_INCREF(&DBusPyInt16_Type);
755     Py_INCREF(&DBusPyUInt16_Type);
756     Py_INCREF(&DBusPyInt32_Type);
757     Py_INCREF(&DBusPyUInt32_Type);
758     Py_INCREF(&DBusPyInt64_Type);
759     Py_INCREF(&DBusPyUInt64_Type);
760     Py_INCREF(&DBusPyBoolean_Type);
761     if (PyModule_AddObject(this_module, "Int16",
762                            (PyObject *)&DBusPyInt16_Type) < 0) return 0;
763     if (PyModule_AddObject(this_module, "UInt16",
764                            (PyObject *)&DBusPyUInt16_Type) < 0) return 0;
765     if (PyModule_AddObject(this_module, "Int32",
766                            (PyObject *)&DBusPyInt32_Type) < 0) return 0;
767     if (PyModule_AddObject(this_module, "UInt32",
768                            (PyObject *)&DBusPyUInt32_Type) < 0) return 0;
769     if (PyModule_AddObject(this_module, "Int64",
770                            (PyObject *)&DBusPyInt64_Type) < 0) return 0;
771     if (PyModule_AddObject(this_module, "UInt64",
772                            (PyObject *)&DBusPyUInt64_Type) < 0) return 0;
773     if (PyModule_AddObject(this_module, "Boolean",
774                            (PyObject *)&DBusPyBoolean_Type) < 0) return 0;
775
776     return 1;
777 }
778
779 /* vim:set ft=c cino< sw=4 sts=4 et: */