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 #define DBG_IS_TOO_VERBOSE
27 #include "types-internal.h"
28 #include "message-internal.h"
30 /* Return the number of variants wrapping the given object. Return 0
31 * if the object is not a D-Bus type.
34 get_variant_level(PyObject
*obj
)
36 if (DBusPyIntBase_Check(obj
)) {
37 return ((DBusPyIntBase
*)obj
)->variant_level
;
39 else if (DBusPyFloatBase_Check(obj
)) {
40 return ((DBusPyFloatBase
*)obj
)->variant_level
;
42 else if (DBusPyArray_Check(obj
)) {
43 return ((DBusPyArray
*)obj
)->variant_level
;
45 else if (DBusPyDict_Check(obj
)) {
46 return ((DBusPyDict
*)obj
)->variant_level
;
48 else if (DBusPyLongBase_Check(obj
) ||
49 DBusPyStrBase_Check(obj
) ||
50 DBusPyString_Check(obj
) ||
51 DBusPyStruct_Check(obj
)) {
52 return PyInt_AsLong(PyObject_GetAttr(obj
, dbus_py_variant_level_const
));
59 char dbus_py_Message_append__doc__
[] = (
60 "set_args(*args[, **kwargs])\n\n"
61 "Set the message's arguments from the positional parameter, according to\n"
62 "the signature given by the ``signature`` keyword parameter.\n"
64 "The following type conversions are supported:\n\n"
65 "=============================== ===========================\n"
66 "D-Bus (in signature) Python\n"
67 "=============================== ===========================\n"
68 "boolean (b) any object (via bool())\n"
69 "byte (y) string of length 1\n"
71 "any integer type any integer\n"
72 "double (d) any float\n"
74 " any object (guess type as below)\n"
75 "string, signature, object path str (must be UTF-8) or unicode\n"
76 "dict (a{...}) any mapping\n"
77 "array (a...) any iterable over appropriate objects\n"
78 "struct ((...)) any iterable over appropriate objects\n"
79 "=============================== ===========================\n"
81 "Here 'any integer' means anything on which int() or long()\n"
82 "(as appropriate) will work, except for basestring subclasses.\n"
83 "'Any float' means anything on which float() will work, except\n"
84 "for basestring subclasses.\n"
86 "If there is no signature, guess from the arguments using\n"
87 "the static method `Message.guess_signature`.\n"
90 char dbus_py_Message_guess_signature__doc__
[] = (
91 "guess_signature(*args) -> Signature [static method]\n\n"
92 "Guess a D-Bus signature which should be used to encode the given\n"
95 "The signature is constructed as follows:\n\n"
96 "=============================== ===========================\n"
98 "=============================== ===========================\n"
99 "D-Bus type, variant_level > 0 variant (v)\n"
100 "D-Bus type, variant_level == 0 the corresponding type\n"
102 "any other int subclass int32 (i) (FIXME: make this error?)\n"
103 "any other long subclass int64 (x) (FIXME: make this error?)\n"
104 "any other float subclass double (d)\n"
105 "any other str subclass string (s)\n"
106 "any other unicode subclass string (s)\n"
107 "any other tuple subclass struct ((...)), guess contents' types\n"
108 "any other list subclass array (a...), guess contents' type\n"
109 " according to type of first item\n"
110 "any other dict subclass dict (a{...}), guess key, value type\n"
111 " according to types for an arbitrary item\n"
112 "anything else raise TypeError\n"
113 "=============================== ===========================\n"
116 /* Return a new reference. If the object is a variant and variant_level_ptr
117 * is not NULL, put the variant level in the variable pointed to, and
118 * return the contained type instead of "v". */
120 _signature_string_from_pyobject(PyObject
*obj
, long *variant_level_ptr
)
122 long variant_level
= get_variant_level(obj
);
123 if (variant_level_ptr
) {
124 *variant_level_ptr
= variant_level
;
126 else if (variant_level
> 0) {
127 return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING
);
130 /* Ordering is important: some of these are subclasses of each other. */
131 if (obj
== Py_True
|| obj
== Py_False
) {
132 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
134 else if (PyInt_Check(obj
)) {
135 if (DBusPyInt16_Check(obj
))
136 return PyString_FromString(DBUS_TYPE_INT16_AS_STRING
);
137 else if (DBusPyInt32_Check(obj
))
138 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
139 else if (DBusPyByte_Check(obj
))
140 return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING
);
141 else if (DBusPyUInt16_Check(obj
))
142 return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING
);
143 else if (DBusPyBoolean_Check(obj
))
144 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
146 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
148 else if (PyLong_Check(obj
)) {
149 if (DBusPyInt64_Check(obj
))
150 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
151 else if (DBusPyUInt32_Check(obj
))
152 return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING
);
153 else if (DBusPyUInt64_Check(obj
))
154 return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING
);
156 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
158 else if (PyUnicode_Check(obj
))
159 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
160 else if (PyFloat_Check(obj
)) {
161 #ifdef WITH_DBUS_FLOAT32
162 if (DBusPyDouble_Check(obj
))
163 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
164 else if (DBusPyFloat_Check(obj
))
165 return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING
);
168 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
170 else if (PyString_Check(obj
)) {
171 if (DBusPyObjectPath_Check(obj
))
172 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
173 else if (DBusPySignature_Check(obj
))
174 return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING
);
175 else if (DBusPyByteArray_Check(obj
))
176 return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
177 DBUS_TYPE_BYTE_AS_STRING
);
179 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
181 else if (PyTuple_Check(obj
)) {
182 int len
= PyTuple_GET_SIZE(obj
);
183 PyObject
*list
= PyList_New(len
+ 2); /* new ref */
184 PyObject
*item
; /* temporary new ref */
185 PyObject
*empty_str
; /* temporary new ref */
189 if (!list
) return NULL
;
191 PyErr_SetString(PyExc_ValueError
, "D-Bus structs cannot be empty");
195 /* Set the first and last elements of list to be the parentheses */
196 item
= PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING
);
197 if (PyList_SetItem(list
, 0, item
) < 0) {
201 item
= PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING
);
202 if (PyList_SetItem(list
, len
+ 1, item
) < 0) {
206 if (!item
|| !PyList_GET_ITEM(list
, 0)) {
212 for (i
= 0; i
< len
; i
++) {
213 item
= PyTuple_GetItem(obj
, i
);
218 item
= _signature_string_from_pyobject(item
, NULL
);
223 if (PyList_SetItem(list
, i
+ 1, item
) < 0) {
229 empty_str
= PyString_FromString("");
231 /* really shouldn't happen */
235 ret
= PyObject_CallMethod(empty_str
, "join", "(O)", list
); /* new ref */
236 /* whether ret is NULL or not, */
237 Py_DECREF(empty_str
);
241 else if (PyList_Check(obj
)) {
243 PyObject
*ret
= PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
);
244 if (!ret
) return NULL
;
245 if (DBusPyArray_Check(obj
) && PyString_Check(((DBusPyArray
*)obj
)->signature
)) {
246 PyString_Concat(&ret
, ((DBusPyArray
*)obj
)->signature
);
249 if (PyList_GET_SIZE(obj
) == 0) {
250 /* No items, so fail. Or should we guess "av"? */
251 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
252 "from an empty list");
255 tmp
= PyList_GetItem(obj
, 0);
256 tmp
= _signature_string_from_pyobject(tmp
, NULL
);
257 if (!tmp
) return NULL
;
258 PyString_ConcatAndDel(&ret
, tmp
);
261 else if (PyDict_Check(obj
)) {
262 PyObject
*key
, *value
, *keysig
, *valuesig
;
264 PyObject
*ret
= NULL
;
266 if (DBusPyDict_Check(obj
) && PyString_Check(((DBusPyDict
*)obj
)->signature
)) {
267 const char *sig
= PyString_AS_STRING(((DBusPyDict
*)obj
)->signature
);
269 return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
270 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
272 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
275 if (!PyDict_Next(obj
, &pos
, &key
, &value
)) {
276 /* No items, so fail. Or should we guess "a{vv}"? */
277 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
278 "from an empty dict");
281 keysig
= _signature_string_from_pyobject(key
, NULL
);
282 valuesig
= _signature_string_from_pyobject(value
, NULL
);
283 if (keysig
&& valuesig
) {
284 ret
= PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
285 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
287 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
288 PyString_AS_STRING(keysig
),
289 PyString_AS_STRING(valuesig
));
292 Py_XDECREF(valuesig
);
296 PyErr_Format(PyExc_TypeError
, "Don't know how which D-Bus type "
297 "to use to encode type \"%s\"",
298 obj
->ob_type
->tp_name
);
304 dbus_py_Message_guess_signature(PyObject
*unused UNUSED
, PyObject
*args
)
306 PyObject
*tmp
, *ret
= NULL
;
309 if (!PyErr_Occurred()) {
310 PyErr_BadInternalCall();
316 fprintf(stderr
, "DBG/%ld: called Message_guess_signature", (long)getpid());
317 PyObject_Print(args
, stderr
, 0);
318 fprintf(stderr
, "\n");
321 if (!PyTuple_Check(args
)) {
322 DBG("%s", "Message_guess_signature: args not a tuple");
323 PyErr_BadInternalCall();
327 /* if there were no args, easy */
328 if (PyTuple_GET_SIZE(args
) == 0) {
329 DBG("%s", "Message_guess_signature: no args, so return Signature('')");
330 return PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s)", "");
333 /* if there were args, the signature we want is, by construction,
334 * exactly the signature we get for the tuple args, except that we don't
335 * want the parentheses. */
336 tmp
= _signature_string_from_pyobject(args
, NULL
);
338 DBG("%s", "Message_guess_signature: failed");
341 if (!PyString_Check(tmp
) || PyString_GET_SIZE(tmp
) < 2) {
342 PyErr_SetString(PyExc_RuntimeError
, "Internal error: "
343 "_signature_string_from_pyobject returned "
348 ret
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s#)",
349 PyString_AS_STRING(tmp
) + 1,
350 PyString_GET_SIZE(tmp
) - 2);
351 DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret
,
352 ret
? PyString_AS_STRING(ret
) : "(NULL)");
357 static int _message_iter_append_pyobject(DBusMessageIter
*appender
,
358 DBusSignatureIter
*sig_iter
,
362 _message_iter_append_string(DBusMessageIter
*appender
,
363 int sig_type
, PyObject
*obj
)
367 if (PyString_Check(obj
)) {
370 /* Raise TypeError if the string has embedded NULs */
371 if (PyString_AsStringAndSize(obj
, &s
, NULL
) < 0) return -1;
372 /* Surely there's a faster stdlib way to validate UTF-8... */
373 unicode
= PyUnicode_DecodeUTF8(s
, PyString_GET_SIZE(obj
), NULL
);
375 PyErr_SetString(PyExc_UnicodeError
, "String parameters "
376 "to be sent over D-Bus must be valid UTF-8");
382 DBG("Performing actual append: string %s", s
);
383 if (!dbus_message_iter_append_basic(appender
, sig_type
,
389 else if (PyUnicode_Check(obj
)) {
390 PyObject
*utf8
= PyUnicode_AsUTF8String(obj
);
391 if (!utf8
) return -1;
392 /* Raise TypeError if the string has embedded NULs */
393 if (PyString_AsStringAndSize(utf8
, &s
, NULL
) < 0) return -1;
394 DBG("Performing actual append: string (from unicode) %s", s
);
395 if (!dbus_message_iter_append_basic(appender
, sig_type
, &s
)) {
402 PyErr_SetString(PyExc_TypeError
,
403 "Expected a string or unicode object");
410 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
414 if (PyString_Check(obj
)) {
415 if (PyString_GET_SIZE(obj
) != 1) {
416 PyErr_Format(PyExc_ValueError
, "Expected a string of "
417 "length 1 byte, but found %d bytes",
418 PyString_GET_SIZE(obj
));
421 y
= *(unsigned char *)PyString_AS_STRING(obj
);
424 long i
= PyInt_AsLong(obj
);
426 if (i
== -1 && PyErr_Occurred()) return -1;
427 if (i
< 0 || i
> 0xff) {
428 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
429 "byte value", (int)i
);
434 DBG("Performing actual append: byte (from unicode) \\x%02x", (unsigned)y
);
435 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
443 _message_iter_append_dictentry(DBusMessageIter
*appender
,
444 DBusSignatureIter
*sig_iter
,
445 PyObject
*dict
, PyObject
*key
)
447 DBusSignatureIter sub_sig_iter
;
450 PyObject
*value
= PyObject_GetItem(dict
, key
);
452 if (!value
) return -1;
455 fprintf(stderr
, "Append dictentry: ");
456 PyObject_Print(key
, stderr
, 0);
457 fprintf(stderr
, " => ");
458 PyObject_Print(value
, stderr
, 0);
459 fprintf(stderr
, "\n");
462 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
463 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
467 s
= dbus_signature_iter_get_signature(sig_iter
);
468 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
470 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
471 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
476 DBG("%s", "Opening DICT_ENTRY container");
477 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_DICT_ENTRY
,
482 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, key
);
484 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
);
486 DBG("%s", "Closing DICT_ENTRY container");
487 if (!dbus_message_iter_close_container(appender
, &sub
)) {
497 _message_iter_append_multi(DBusMessageIter
*appender
,
498 const DBusSignatureIter
*sig_iter
,
499 int mode
, PyObject
*obj
)
501 DBusMessageIter sub_appender
;
502 DBusSignatureIter sub_sig_iter
;
505 PyObject
*iterator
= PyObject_GetIter(obj
);
507 int container
= mode
;
510 fprintf(stderr
, "Appending multiple: ");
511 PyObject_Print(obj
, stderr
, 0);
512 fprintf(stderr
, "\n");
515 if (!iterator
) return -1;
516 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
518 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
519 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
523 s
= dbus_signature_iter_get_signature(sig_iter
);
524 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
526 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
527 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
532 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
533 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
540 /* else leave sig set to NULL. */
542 DBG("Opening %c container", container
);
543 if (!dbus_message_iter_open_container(appender
, container
,
544 sig
, &sub_appender
)) {
550 while ((contents
= PyIter_Next(iterator
))) {
552 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
553 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
554 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
558 s
= dbus_signature_iter_get_signature(sig_iter
);
559 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
561 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
562 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
568 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
569 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
573 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
581 if (PyErr_Occurred()) ret
= -1;
582 /* This must be run as cleanup, even on failure. */
583 DBG("Closing %c container", container
);
584 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
590 Py_XDECREF(iterator
);
596 _message_iter_append_string_as_byte_array(DBusMessageIter
*appender
,
599 /* a bit of a faster path for byte arrays that are strings */
600 int len
= PyString_GET_SIZE(obj
);
605 s
= PyString_AS_STRING(obj
);
606 DBG("%s", "Opening ARRAY container");
607 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
608 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
612 DBG("Appending fixed array of %d bytes", len
);
613 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
620 DBG("%s", "Closing ARRAY container");
621 if (!dbus_message_iter_close_container(appender
, &sub
)) {
628 /* Encode some Python object into a D-Bus variant slot. */
630 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
632 DBusSignatureIter obj_sig_iter
;
633 const char *obj_sig_str
;
638 /* Separate the object into the contained object, and the number of
639 * variants it's wrapped in. */
640 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
641 if (!obj_sig
) return -1;
643 obj_sig_str
= PyString_AsString(obj_sig
);
644 if (!obj_sig_str
) return -1;
646 if (variant_level
< 1) {
650 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
652 { /* scope for variant_iters */
653 DBusMessageIter variant_iters
[variant_level
];
656 for (i
= 0; i
< variant_level
; i
++) {
657 DBusMessageIter
*child
= &variant_iters
[i
];
658 /* The first is a special case: its parent is the iter passed in
659 * to this function, instead of being the previous one in the
662 DBusMessageIter
*parent
= (i
== 0
664 : &(variant_iters
[i
-1]));
665 /* The last is also a special case: it contains the actual
666 * object, rather than another variant
668 const char *sig_str
= (i
== variant_level
-1
670 : DBUS_TYPE_VARIANT_AS_STRING
);
672 DBG("Opening VARIANT container %p inside %p containing '%s'",
673 child
, parent
, sig_str
);
674 if (!dbus_message_iter_open_container(parent
, DBUS_TYPE_VARIANT
,
682 /* Put the object itself into the innermost variant */
683 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
686 /* here we rely on i (and variant_level) being a signed long */
687 for (i
= variant_level
- 1; i
>= 0; i
--) {
688 DBusMessageIter
*child
= &variant_iters
[i
];
689 /* The first is a special case: its parent is the iter passed in
690 * to this function, instead of being the previous one in the
693 DBusMessageIter
*parent
= (i
== 0 ? appender
694 : &(variant_iters
[i
-1]));
696 DBG("Closing VARIANT container %p inside %p", child
, parent
);
697 if (!dbus_message_iter_close_container(parent
, child
)) {
712 _message_iter_append_pyobject(DBusMessageIter
*appender
,
713 DBusSignatureIter
*sig_iter
,
716 int sig_type
= dbus_signature_iter_get_current_type(sig_iter
);
720 dbus_uint16_t uint16
;
722 dbus_uint32_t uint32
;
724 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
725 dbus_uint64_t uint64
;
732 fprintf(stderr
, "Appending object at %p: ", obj
);
733 PyObject_Print(obj
, stderr
, 0);
734 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
739 /* The numeric types are relatively simple to deal with, so are
742 case DBUS_TYPE_BOOLEAN
:
743 if (PyObject_IsTrue(obj
)) {
749 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
750 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.b
)) {
758 case DBUS_TYPE_DOUBLE
:
759 u
.d
= PyFloat_AsDouble(obj
);
760 if (PyErr_Occurred()) {
764 DBG("Performing actual append: double(%f)", u
.d
);
765 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
773 #ifdef WITH_DBUS_FLOAT32
774 case DBUS_TYPE_FLOAT
:
775 u
.d
= PyFloat_AsDouble(obj
);
776 if (PyErr_Occurred()) {
781 DBG("Performing actual append: float(%f)", u
.f
);
782 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
791 /* The integer types are all basically the same - we delegate to
792 intNN_range_check() */
793 #define PROCESS_INTEGER(size) \
794 u.size = dbus_py_##size##_range_check(obj);\
795 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
799 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
800 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
807 case DBUS_TYPE_INT16
:
808 PROCESS_INTEGER(int16
)
810 case DBUS_TYPE_UINT16
:
811 PROCESS_INTEGER(uint16
)
813 case DBUS_TYPE_INT32
:
814 PROCESS_INTEGER(int32
)
816 case DBUS_TYPE_UINT32
:
817 PROCESS_INTEGER(uint32
)
819 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
820 case DBUS_TYPE_INT64
:
821 PROCESS_INTEGER(int64
)
823 case DBUS_TYPE_UINT64
:
824 PROCESS_INTEGER(uint64
)
827 case DBUS_TYPE_INT64
:
828 case DBUS_TYPE_UINT64
:
829 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
830 "types are not supported on this platform");
834 #undef PROCESS_INTEGER
836 /* Now the more complicated cases, which are delegated to helper
837 * functions (although in practice, the compiler will hopefully
838 * inline them anyway). */
840 case DBUS_TYPE_STRING
:
841 case DBUS_TYPE_SIGNATURE
:
842 case DBUS_TYPE_OBJECT_PATH
:
843 ret
= _message_iter_append_string(appender
, sig_type
, obj
);
847 ret
= _message_iter_append_byte(appender
, obj
);
850 case DBUS_TYPE_ARRAY
:
851 /* 3 cases - it might actually be a dict, or it might be a byte array
852 * being copied from a string (for which we have a faster path),
853 * or it might be a generic array. */
855 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
856 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
857 ret
= _message_iter_append_multi(appender
, sig_iter
,
858 DBUS_TYPE_DICT_ENTRY
, obj
);
859 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
860 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
862 ret
= _message_iter_append_multi(appender
, sig_iter
,
863 DBUS_TYPE_ARRAY
, obj
);
864 DBG("_message_iter_append_multi(): %d", ret
);
867 case DBUS_TYPE_STRUCT
:
868 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
871 case DBUS_TYPE_VARIANT
:
872 ret
= _message_iter_append_variant(appender
, obj
);
875 case DBUS_TYPE_INVALID
:
876 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
877 "signature than in Python arguments");
882 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
883 "signature", sig_type
);
887 if (ret
< 0) return -1;
889 DBG("Advancing signature iter at %p", sig_iter
);
894 dbus_signature_iter_next(sig_iter
);
896 DBG("- result: %ld, type %02x '%c'", (long)b
,
897 (int)dbus_signature_iter_get_current_type(sig_iter
),
898 (int)dbus_signature_iter_get_current_type(sig_iter
));
906 dbus_py_Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
908 const char *signature
= NULL
;
909 PyObject
*signature_obj
= NULL
;
910 DBusSignatureIter sig_iter
;
911 DBusMessageIter appender
;
913 static char *argnames
[] = {"signature", NULL
};
915 if (!self
->msg
) return DBusPy_RaiseUnusableMessage();
918 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
919 PyObject_Print(args
, stderr
, 0);
921 fprintf(stderr
, ", **");
922 PyObject_Print(kwargs
, stderr
, 0);
924 fprintf(stderr
, ")\n");
927 /* only use kwargs for this step: deliberately ignore args for now */
928 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
, "|z:append",
929 argnames
, &signature
)) return NULL
;
932 DBG("%s", "No signature for message, guessing...");
933 signature_obj
= dbus_py_Message_guess_signature(NULL
, args
);
934 if (!signature_obj
) return NULL
;
935 signature
= PyString_AS_STRING(signature_obj
);
937 /* from here onwards, you have to do a goto rather than returning NULL
938 to make sure signature_obj gets freed */
940 /* iterate over args and the signature, together */
941 if (!dbus_signature_validate(signature
, NULL
)) {
942 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
945 dbus_signature_iter_init(&sig_iter
, signature
);
946 dbus_message_iter_init_append(self
->msg
, &appender
);
947 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
948 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
949 PyTuple_GET_ITEM(args
, i
)) < 0) {
953 if (dbus_signature_iter_get_current_type(&sig_iter
)
954 != DBUS_TYPE_INVALID
) {
955 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
956 "signature than in Python arguments");
961 Py_XDECREF(signature_obj
);
965 /* "If appending any of the arguments fails due to lack of memory,
966 * generally the message is hosed and you have to start over" -libdbus docs
967 * Enforce this by throwing away the message structure.
969 dbus_message_unref(self
->msg
);
972 Py_XDECREF(signature_obj
);
976 /* vim:set ft=c cino< sw=4 sts=4 et: */