1 /* D-Bus Message serialization. This contains all the logic to map from
2 * Python objects to D-Bus types.
4 * Copyright (C) 2006 Collabora Ltd.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /* Return the number of variants wrapping the given object. Return 0
27 * if the object is not a D-Bus type.
30 get_variant_level(PyObject
*obj
)
32 if (DBusPythonInt_Check(obj
)) {
33 return ((DBusPythonInt
*)obj
)->variant_level
;
35 else if (DBusPythonFloat_Check(obj
)) {
36 return ((DBusPythonFloat
*)obj
)->variant_level
;
38 else if (Array_Check(obj
)) {
39 return ((Array
*)obj
)->variant_level
;
41 else if (Dict_Check(obj
)) {
42 return ((Dict
*)obj
)->variant_level
;
44 else if (DBusPythonLong_Check(obj
) ||
45 DBusPythonString_Check(obj
) ||
48 return PyInt_AsLong(PyObject_GetAttr(obj
, variant_level_const
));
55 PyDoc_STRVAR(Message_append__doc__
,
56 "set_args(*args[, **kwargs])\n\n"
57 "Set the message's arguments from the positional parameter, according to\n"
58 "the signature given by the ``signature`` keyword parameter.\n"
60 "The following type conversions are supported:\n\n"
61 "=============================== ===========================\n"
62 "D-Bus (in signature) Python\n"
63 "=============================== ===========================\n"
64 "boolean (b) any object (via bool())\n"
65 "byte (y) string of length 1\n"
67 "any integer type any integer\n"
68 "double (d) any float\n"
70 " any object (guess type as below)\n"
71 "string, signature, object path str (must be UTF-8) or unicode\n"
72 "dict (a{...}) any mapping\n"
73 "array (a...) any iterable over appropriate objects\n"
74 "struct ((...)) any iterable over appropriate objects\n"
75 "=============================== ===========================\n"
77 "Here 'any integer' means anything on which int() or long()\n"
78 "(as appropriate) will work, except for basestring subclasses.\n"
79 "'Any float' means anything on which float() will work, except\n"
80 "for basestring subclasses.\n"
82 "If there is no signature, guess from the arguments using\n"
83 "the static method `Message.guess_signature`.\n"
86 PyDoc_STRVAR(Message_guess_signature__doc__
,
87 "guess_signature(*args) -> Signature [static method]\n\n"
88 "Guess a D-Bus signature which should be used to encode the given\n"
91 "The signature is constructed as follows:\n\n"
92 "=============================== ===========================\n"
94 "=============================== ===========================\n"
95 "D-Bus type, variant_level > 0 variant (v)\n"
96 "D-Bus type, variant_level == 0 the corresponding type\n"
98 "any other int subclass int32 (i) (FIXME: make this error?)\n"
99 "any other long subclass int64 (x) (FIXME: make this error?)\n"
100 "any other float subclass double (d)\n"
101 "any other str subclass string (s)\n"
102 "any other unicode subclass string (s)\n"
103 "any other tuple subclass struct ((...)), guess contents' types\n"
104 "any other list subclass array (a...), guess contents' type\n"
105 " according to type of first item\n"
106 "any other dict subclass dict (a{...}), guess key, value type\n"
107 " according to types for an arbitrary item\n"
108 "anything else raise TypeError\n"
109 "=============================== ===========================\n"
112 /* Return a new reference. If the object is a variant and variant_level_ptr
113 * is not NULL, put the variant level in the variable pointed to, and
114 * return the contained type instead of "v". */
116 _signature_string_from_pyobject(PyObject
*obj
, long *variant_level_ptr
)
118 long variant_level
= get_variant_level(obj
);
119 if (variant_level_ptr
) {
120 *variant_level_ptr
= variant_level
;
122 else if (variant_level
> 0) {
123 return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING
);
126 /* Ordering is important: some of these are subclasses of each other. */
127 if (obj
== Py_True
|| obj
== Py_False
) {
128 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
130 else if (PyInt_Check(obj
)) {
131 if (Int16_Check(obj
))
132 return PyString_FromString(DBUS_TYPE_INT16_AS_STRING
);
133 else if (Int32_Check(obj
))
134 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
135 else if (Byte_Check(obj
))
136 return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING
);
137 else if (UInt16_Check(obj
))
138 return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING
);
139 else if (Boolean_Check(obj
))
140 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
142 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
144 else if (PyLong_Check(obj
)) {
145 if (Int64_Check(obj
))
146 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
147 else if (UInt32_Check (obj
))
148 return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING
);
149 else if (UInt64_Check (obj
))
150 return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING
);
152 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
154 else if (PyUnicode_Check(obj
))
155 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
156 else if (PyFloat_Check(obj
)) {
157 #ifdef WITH_DBUS_FLOAT32
158 if (Double_Check(obj
))
159 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
160 else if (Float_Check(obj
))
161 return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING
);
164 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
166 else if (PyString_Check(obj
)) {
167 if (ObjectPath_Check(obj
))
168 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
169 else if (Signature_Check(obj
))
170 return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING
);
171 else if (ByteArray_Check(obj
))
172 return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
173 DBUS_TYPE_BYTE_AS_STRING
);
175 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
177 else if (PyTuple_Check (obj
)) {
178 int len
= PyTuple_GET_SIZE(obj
);
179 PyObject
*list
= PyList_New(len
+ 2); /* new ref */
180 PyObject
*item
; /* temporary new ref */
181 PyObject
*empty_str
; /* temporary new ref */
185 if (!list
) return NULL
;
187 PyErr_SetString(PyExc_ValueError
, "D-Bus structs cannot be empty");
191 /* Set the first and last elements of list to be the parentheses */
192 item
= PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING
);
193 if (PyList_SetItem(list
, 0, item
) < 0) {
197 item
= PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING
);
198 if (PyList_SetItem(list
, len
+ 1, item
) < 0) {
202 if (!item
|| !PyList_GET_ITEM(list
, 0)) {
208 for (i
= 0; i
< len
; i
++) {
209 item
= PyTuple_GetItem(obj
, i
);
214 item
= _signature_string_from_pyobject(item
, NULL
);
219 if (PyList_SetItem(list
, i
+ 1, item
) < 0) {
225 empty_str
= PyString_FromString("");
227 /* really shouldn't happen */
231 ret
= PyObject_CallMethod(empty_str
, "join", "(O)", list
); /* new ref */
232 /* whether ret is NULL or not, */
233 Py_DECREF(empty_str
);
237 else if (PyList_Check(obj
)) {
239 PyObject
*ret
= PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
);
240 if (!ret
) return NULL
;
241 if (Array_Check(obj
) && PyString_Check(((Array
*)obj
)->signature
)) {
242 PyString_Concat(&ret
, ((Array
*)obj
)->signature
);
245 if (PyList_GET_SIZE(obj
) == 0) {
246 /* No items, so fail. Or should we guess "av"? */
247 PyErr_SetString (PyExc_ValueError
, "Unable to guess signature "
248 "from an empty list");
251 tmp
= PyList_GetItem(obj
, 0);
252 tmp
= _signature_string_from_pyobject(tmp
, NULL
);
253 if (!tmp
) return NULL
;
254 PyString_ConcatAndDel (&ret
, tmp
);
257 else if (PyDict_Check(obj
)) {
258 PyObject
*key
, *value
, *keysig
, *valuesig
;
260 PyObject
*ret
= NULL
;
262 if (Dict_Check(obj
) && PyString_Check(((Dict
*)obj
)->signature
)) {
263 const char *sig
= PyString_AS_STRING(((Dict
*)obj
)->signature
);
265 return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
266 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
268 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
271 if (!PyDict_Next(obj
, &pos
, &key
, &value
)) {
272 /* No items, so fail. Or should we guess "a{vv}"? */
273 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
274 "from an empty dict");
277 keysig
= _signature_string_from_pyobject(key
, NULL
);
278 valuesig
= _signature_string_from_pyobject(value
, NULL
);
279 if (keysig
&& valuesig
) {
280 ret
= PyString_FromFormat ((DBUS_TYPE_ARRAY_AS_STRING
281 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
283 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
284 PyString_AS_STRING(keysig
),
285 PyString_AS_STRING(valuesig
));
288 Py_XDECREF(valuesig
);
292 PyErr_Format(PyExc_TypeError
, "Don't know how which D-Bus type "
293 "to use to encode type \"%s\"",
294 obj
->ob_type
->tp_name
);
300 Message_guess_signature(PyObject
*unused UNUSED
, PyObject
*args
)
302 PyObject
*tmp
, *ret
= NULL
;
305 if (!PyErr_Occurred()) {
306 PyErr_BadInternalCall();
312 fprintf(stderr
, "DBG/%ld: called Message_guess_signature", (long)getpid());
313 PyObject_Print(args
, stderr
, 0);
314 fprintf(stderr
, "\n");
317 if (!PyTuple_Check(args
)) {
318 DBG("%s", "Message_guess_signature: args not a tuple");
319 PyErr_BadInternalCall();
323 /* if there were no args, easy */
324 if (PyTuple_GET_SIZE(args
) == 0) {
325 DBG("%s", "Message_guess_signature: no args, so return Signature('')");
326 return PyObject_CallFunction((PyObject
*)&SignatureType
, "(s)", "");
329 /* if there were args, the signature we want is, by construction,
330 * exactly the signature we get for the tuple args, except that we don't
331 * want the parentheses. */
332 tmp
= _signature_string_from_pyobject(args
, NULL
);
334 DBG("%s", "Message_guess_signature: failed");
337 if (!PyString_Check(tmp
) || PyString_GET_SIZE(tmp
) < 2) {
338 PyErr_SetString(PyExc_RuntimeError
, "Internal error: "
339 "_signature_string_from_pyobject returned "
344 ret
= PyObject_CallFunction((PyObject
*)&SignatureType
, "(s#)",
345 PyString_AS_STRING (tmp
) + 1,
346 PyString_GET_SIZE (tmp
) - 2);
347 DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret
,
348 ret
? PyString_AS_STRING(ret
) : "(NULL)");
353 static int _message_iter_append_pyobject(DBusMessageIter
*appender
,
354 DBusSignatureIter
*sig_iter
,
358 _message_iter_append_string(DBusMessageIter
*appender
,
359 int sig_type
, PyObject
*obj
)
363 if (PyString_Check (obj
)) {
366 /* Raise TypeError if the string has embedded NULs */
367 if (PyString_AsStringAndSize (obj
, &s
, NULL
) < 0) return -1;
368 /* Surely there's a faster stdlib way to validate UTF-8... */
369 unicode
= PyUnicode_DecodeUTF8 (s
, PyString_GET_SIZE (obj
), NULL
);
371 PyErr_SetString (PyExc_UnicodeError
, "String parameters "
372 "to be sent over D-Bus must be valid UTF-8");
378 DBG("Performing actual append: string %s", s
);
379 if (!dbus_message_iter_append_basic (appender
, sig_type
,
385 else if (PyUnicode_Check (obj
)) {
386 PyObject
*utf8
= PyUnicode_AsUTF8String (obj
);
387 if (!utf8
) return -1;
388 /* Raise TypeError if the string has embedded NULs */
389 if (PyString_AsStringAndSize (utf8
, &s
, NULL
) < 0) return -1;
390 DBG("Performing actual append: string (from unicode) %s", s
);
391 if (!dbus_message_iter_append_basic (appender
, sig_type
, &s
)) {
398 PyErr_SetString (PyExc_TypeError
,
399 "Expected a string or unicode object");
406 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
410 if (PyString_Check(obj
)) {
411 if (PyString_GET_SIZE(obj
) != 1) {
412 PyErr_Format(PyExc_ValueError
, "Expected a string of "
413 "length 1 byte, but found %d bytes",
414 PyString_GET_SIZE (obj
));
417 y
= *(unsigned char *)PyString_AS_STRING(obj
);
420 long i
= PyInt_AsLong (obj
);
422 if (i
== -1 && PyErr_Occurred()) return -1;
423 if (i
< 0 || i
> 0xff) {
424 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
425 "byte value", (int)i
);
430 DBG("Performing actual append: byte (from unicode) \\x%02x", (unsigned)y
);
431 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
439 _message_iter_append_dictentry(DBusMessageIter
*appender
,
440 DBusSignatureIter
*sig_iter
,
441 PyObject
*dict
, PyObject
*key
)
443 DBusSignatureIter sub_sig_iter
;
446 PyObject
*value
= PyObject_GetItem(dict
, key
);
448 if (!value
) return -1;
451 fprintf(stderr
, "Append dictentry: ");
452 PyObject_Print(key
, stderr
, 0);
453 fprintf(stderr
, " => ");
454 PyObject_Print(value
, stderr
, 0);
455 fprintf(stderr
, "\n");
458 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
459 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
463 s
= dbus_signature_iter_get_signature(sig_iter
);
464 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
466 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
467 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
472 DBG("%s", "Opening DICT_ENTRY container");
473 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_DICT_ENTRY
,
478 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, key
);
480 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
);
482 DBG("%s", "Closing DICT_ENTRY container");
483 if (!dbus_message_iter_close_container(appender
, &sub
)) {
493 _message_iter_append_multi(DBusMessageIter
*appender
,
494 const DBusSignatureIter
*sig_iter
,
495 int mode
, PyObject
*obj
)
497 DBusMessageIter sub_appender
;
498 DBusSignatureIter sub_sig_iter
;
501 PyObject
*iterator
= PyObject_GetIter(obj
);
503 int container
= mode
;
506 fprintf(stderr
, "Appending multiple: ");
507 PyObject_Print(obj
, stderr
, 0);
508 fprintf(stderr
, "\n");
511 if (!iterator
) return -1;
512 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
514 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
515 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
519 s
= dbus_signature_iter_get_signature(sig_iter
);
520 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
522 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
523 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
528 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
529 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
536 /* else leave sig set to NULL. */
538 DBG("Opening %c container", container
);
539 if (!dbus_message_iter_open_container(appender
, container
,
540 sig
, &sub_appender
)) {
546 while ((contents
= PyIter_Next(iterator
))) {
548 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
549 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
550 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
554 s
= dbus_signature_iter_get_signature(sig_iter
);
555 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
557 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
558 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
564 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
565 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
569 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
577 if (PyErr_Occurred()) ret
= -1;
578 /* This must be run as cleanup, even on failure. */
579 DBG("Closing %c container", container
);
580 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
586 Py_XDECREF(iterator
);
592 _message_iter_append_string_as_byte_array (DBusMessageIter
*appender
,
595 /* a bit of a faster path for byte arrays that are strings */
596 int len
= PyString_GET_SIZE(obj
);
601 s
= PyString_AS_STRING(obj
);
602 DBG("%s", "Opening ARRAY container");
603 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
604 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
608 DBG("Appending fixed array of %d bytes", len
);
609 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
616 DBG("%s", "Closing ARRAY container");
617 if (!dbus_message_iter_close_container(appender
, &sub
)) {
624 /* Encode some Python object into a D-Bus variant slot. */
626 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
628 DBusSignatureIter obj_sig_iter
;
629 const char *obj_sig_str
;
634 /* Separate the object into the contained object, and the number of
635 * variants it's wrapped in. */
636 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
637 if (!obj_sig
) return -1;
639 obj_sig_str
= PyString_AsString(obj_sig
);
640 if (!obj_sig_str
) return -1;
642 if (variant_level
< 1) {
646 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
648 { /* scope for variant_iters */
649 DBusMessageIter variant_iters
[variant_level
];
652 for (i
= 0; i
< variant_level
; i
++) {
653 DBusMessageIter
*child
= &variant_iters
[i
];
654 /* The first is a special case: its parent is the iter passed in
655 * to this function, instead of being the previous one in the
658 DBusMessageIter
*parent
= (i
== 0
660 : &(variant_iters
[i
-1]));
661 /* The last is also a special case: it contains the actual
662 * object, rather than another variant
664 const char *sig_str
= (i
== variant_level
-1
666 : DBUS_TYPE_VARIANT_AS_STRING
);
668 DBG("Opening VARIANT container %p inside %p containing '%s'",
669 child
, parent
, sig_str
);
670 if (!dbus_message_iter_open_container (parent
, DBUS_TYPE_VARIANT
,
678 /* Put the object itself into the innermost variant */
679 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
682 /* here we rely on i (and variant_level) being a signed long */
683 for (i
= variant_level
- 1; i
>= 0; i
--) {
684 DBusMessageIter
*child
= &variant_iters
[i
];
685 /* The first is a special case: its parent is the iter passed in
686 * to this function, instead of being the previous one in the
689 DBusMessageIter
*parent
= (i
== 0 ? appender
690 : &(variant_iters
[i
-1]));
692 DBG("Closing VARIANT container %p inside %p", child
, parent
);
693 if (!dbus_message_iter_close_container (parent
, child
)) {
703 Py_XDECREF (obj_sig
);
708 _message_iter_append_pyobject(DBusMessageIter
*appender
,
709 DBusSignatureIter
*sig_iter
,
712 int sig_type
= dbus_signature_iter_get_current_type (sig_iter
);
716 dbus_uint16_t uint16
;
718 dbus_uint32_t uint32
;
720 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
721 dbus_uint64_t uint64
;
728 fprintf(stderr
, "Appending object at %p: ", obj
);
729 PyObject_Print(obj
, stderr
, 0);
730 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
735 /* The numeric types are relatively simple to deal with, so are
738 case DBUS_TYPE_BOOLEAN
:
739 if (PyObject_IsTrue(obj
)) {
745 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
746 if (!dbus_message_iter_append_basic (appender
, sig_type
, &u
.b
)) {
754 case DBUS_TYPE_DOUBLE
:
755 u
.d
= PyFloat_AsDouble (obj
);
756 if (PyErr_Occurred()) {
760 DBG("Performing actual append: double(%f)", u
.d
);
761 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
769 #ifdef WITH_DBUS_FLOAT32
770 case DBUS_TYPE_FLOAT
:
771 u
.d
= PyFloat_AsDouble (obj
);
772 if (PyErr_Occurred()) {
777 DBG("Performing actual append: float(%f)", u
.f
);
778 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
787 /* The integer types are all basically the same - we delegate to
788 intNN_range_check() */
789 #define PROCESS_INTEGER(size) \
790 u.size = size##_range_check (obj);\
791 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
795 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
796 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
803 case DBUS_TYPE_INT16
:
804 PROCESS_INTEGER(int16
)
806 case DBUS_TYPE_UINT16
:
807 PROCESS_INTEGER(uint16
)
809 case DBUS_TYPE_INT32
:
810 PROCESS_INTEGER(int32
)
812 case DBUS_TYPE_UINT32
:
813 PROCESS_INTEGER(uint32
)
815 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
816 case DBUS_TYPE_INT64
:
817 PROCESS_INTEGER(int64
)
819 case DBUS_TYPE_UINT64
:
820 PROCESS_INTEGER(uint64
)
823 case DBUS_TYPE_INT64
:
824 case DBUS_TYPE_UINT64
:
825 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
826 "types are not supported on this platform");
830 #undef PROCESS_INTEGER
832 /* Now the more complicated cases, which are delegated to helper
833 * functions (although in practice, the compiler will hopefully
834 * inline them anyway). */
836 case DBUS_TYPE_STRING
:
837 case DBUS_TYPE_SIGNATURE
:
838 case DBUS_TYPE_OBJECT_PATH
:
839 ret
= _message_iter_append_string(appender
, sig_type
, obj
);
843 ret
= _message_iter_append_byte(appender
, obj
);
846 case DBUS_TYPE_ARRAY
:
847 /* 3 cases - it might actually be a dict, or it might be a byte array
848 * being copied from a string (for which we have a faster path),
849 * or it might be a generic array. */
851 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
852 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
853 ret
= _message_iter_append_multi(appender
, sig_iter
,
854 DBUS_TYPE_DICT_ENTRY
, obj
);
855 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
856 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
858 ret
= _message_iter_append_multi(appender
, sig_iter
,
859 DBUS_TYPE_ARRAY
, obj
);
860 DBG("_message_iter_append_multi(): %d", ret
);
863 case DBUS_TYPE_STRUCT
:
864 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
867 case DBUS_TYPE_VARIANT
:
868 ret
= _message_iter_append_variant(appender
, obj
);
871 case DBUS_TYPE_INVALID
:
872 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
873 "signature than in Python arguments");
878 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
879 "signature", sig_type
);
883 if (ret
< 0) return -1;
885 DBG("Advancing signature iter at %p", sig_iter
);
890 dbus_signature_iter_next(sig_iter
);
892 DBG("- result: %ld, type %02x '%c'", (long)b
,
893 (int)dbus_signature_iter_get_current_type(sig_iter
),
894 (int)dbus_signature_iter_get_current_type(sig_iter
));
902 Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
904 const char *signature
= NULL
;
905 PyObject
*signature_obj
= NULL
;
906 DBusSignatureIter sig_iter
;
907 DBusMessageIter appender
;
909 static char *argnames
[] = {"signature", NULL
};
911 if (!self
->msg
) return DBusException_UnusableMessage ();
914 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
915 PyObject_Print(args
, stderr
, 0);
917 fprintf(stderr
, ", **");
918 PyObject_Print(kwargs
, stderr
, 0);
920 fprintf(stderr
, ")\n");
923 /* only use kwargs for this step: deliberately ignore args for now */
924 if (!PyArg_ParseTupleAndKeywords(empty_tuple
, kwargs
, "|z:append",
925 argnames
, &signature
)) return NULL
;
928 DBG("%s", "No signature for message, guessing...");
929 signature_obj
= Message_guess_signature(NULL
, args
);
930 if (!signature_obj
) return NULL
;
931 signature
= PyString_AS_STRING (signature_obj
);
933 /* from here onwards, you have to do a goto rather than returning NULL
934 to make sure signature_obj gets freed */
936 /* iterate over args and the signature, together */
937 if (!dbus_signature_validate(signature
, NULL
)) {
938 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
941 dbus_signature_iter_init(&sig_iter
, signature
);
942 dbus_message_iter_init_append(self
->msg
, &appender
);
943 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
944 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
945 PyTuple_GET_ITEM (args
, i
)) < 0) {
949 if (dbus_signature_iter_get_current_type(&sig_iter
)
950 != DBUS_TYPE_INVALID
) {
951 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
952 "signature than in Python arguments");
957 Py_XDECREF(signature_obj
);
961 /* "If appending any of the arguments fails due to lack of memory,
962 * generally the message is hosed and you have to start over" -libdbus docs
963 * Enforce this by throwing away the message structure.
965 dbus_message_unref(self
->msg
);
968 Py_XDECREF(signature_obj
);
972 /* vim:set ft=c cino< sw=4 sts=4 et: */