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 #include "types-internal.h"
28 /* Return the number of variants wrapping the given object. Return 0
29 * if the object is not a D-Bus type.
32 get_variant_level(PyObject
*obj
)
34 if (DBusPyIntBase_Check(obj
)) {
35 return ((DBusPyIntBase
*)obj
)->variant_level
;
37 else if (DBusPyFloatBase_Check(obj
)) {
38 return ((DBusPyFloatBase
*)obj
)->variant_level
;
40 else if (DBusPyArray_Check(obj
)) {
41 return ((DBusPyArray
*)obj
)->variant_level
;
43 else if (DBusPyDict_Check(obj
)) {
44 return ((DBusPyDict
*)obj
)->variant_level
;
46 else if (DBusPyLongBase_Check(obj
) ||
47 DBusPyStrBase_Check(obj
) ||
48 DBusPyString_Check(obj
) ||
49 DBusPyStruct_Check(obj
)) {
50 return PyInt_AsLong(PyObject_GetAttr(obj
, dbus_py_variant_level_const
));
57 PyDoc_STRVAR(Message_append__doc__
,
58 "set_args(*args[, **kwargs])\n\n"
59 "Set the message's arguments from the positional parameter, according to\n"
60 "the signature given by the ``signature`` keyword parameter.\n"
62 "The following type conversions are supported:\n\n"
63 "=============================== ===========================\n"
64 "D-Bus (in signature) Python\n"
65 "=============================== ===========================\n"
66 "boolean (b) any object (via bool())\n"
67 "byte (y) string of length 1\n"
69 "any integer type any integer\n"
70 "double (d) any float\n"
72 " any object (guess type as below)\n"
73 "string, signature, object path str (must be UTF-8) or unicode\n"
74 "dict (a{...}) any mapping\n"
75 "array (a...) any iterable over appropriate objects\n"
76 "struct ((...)) any iterable over appropriate objects\n"
77 "=============================== ===========================\n"
79 "Here 'any integer' means anything on which int() or long()\n"
80 "(as appropriate) will work, except for basestring subclasses.\n"
81 "'Any float' means anything on which float() will work, except\n"
82 "for basestring subclasses.\n"
84 "If there is no signature, guess from the arguments using\n"
85 "the static method `Message.guess_signature`.\n"
88 PyDoc_STRVAR(Message_guess_signature__doc__
,
89 "guess_signature(*args) -> Signature [static method]\n\n"
90 "Guess a D-Bus signature which should be used to encode the given\n"
93 "The signature is constructed as follows:\n\n"
94 "=============================== ===========================\n"
96 "=============================== ===========================\n"
97 "D-Bus type, variant_level > 0 variant (v)\n"
98 "D-Bus type, variant_level == 0 the corresponding type\n"
100 "any other int subclass int32 (i) (FIXME: make this error?)\n"
101 "any other long subclass int64 (x) (FIXME: make this error?)\n"
102 "any other float subclass double (d)\n"
103 "any other str subclass string (s)\n"
104 "any other unicode subclass string (s)\n"
105 "any other tuple subclass struct ((...)), guess contents' types\n"
106 "any other list subclass array (a...), guess contents' type\n"
107 " according to type of first item\n"
108 "any other dict subclass dict (a{...}), guess key, value type\n"
109 " according to types for an arbitrary item\n"
110 "anything else raise TypeError\n"
111 "=============================== ===========================\n"
114 /* Return a new reference. If the object is a variant and variant_level_ptr
115 * is not NULL, put the variant level in the variable pointed to, and
116 * return the contained type instead of "v". */
118 _signature_string_from_pyobject(PyObject
*obj
, long *variant_level_ptr
)
120 long variant_level
= get_variant_level(obj
);
121 if (variant_level_ptr
) {
122 *variant_level_ptr
= variant_level
;
124 else if (variant_level
> 0) {
125 return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING
);
128 /* Ordering is important: some of these are subclasses of each other. */
129 if (obj
== Py_True
|| obj
== Py_False
) {
130 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
132 else if (PyInt_Check(obj
)) {
133 if (DBusPyInt16_Check(obj
))
134 return PyString_FromString(DBUS_TYPE_INT16_AS_STRING
);
135 else if (DBusPyInt32_Check(obj
))
136 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
137 else if (DBusPyByte_Check(obj
))
138 return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING
);
139 else if (DBusPyUInt16_Check(obj
))
140 return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING
);
141 else if (DBusPyBoolean_Check(obj
))
142 return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING
);
144 return PyString_FromString(DBUS_TYPE_INT32_AS_STRING
);
146 else if (PyLong_Check(obj
)) {
147 if (DBusPyInt64_Check(obj
))
148 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
149 else if (DBusPyUInt32_Check (obj
))
150 return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING
);
151 else if (DBusPyUInt64_Check (obj
))
152 return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING
);
154 return PyString_FromString(DBUS_TYPE_INT64_AS_STRING
);
156 else if (PyUnicode_Check(obj
))
157 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
158 else if (PyFloat_Check(obj
)) {
159 #ifdef WITH_DBUS_FLOAT32
160 if (DBusPyDouble_Check(obj
))
161 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
162 else if (DBusPyFloat_Check(obj
))
163 return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING
);
166 return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING
);
168 else if (PyString_Check(obj
)) {
169 if (DBusPyObjectPath_Check(obj
))
170 return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING
);
171 else if (DBusPySignature_Check(obj
))
172 return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING
);
173 else if (DBusPyByteArray_Check(obj
))
174 return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
175 DBUS_TYPE_BYTE_AS_STRING
);
177 return PyString_FromString(DBUS_TYPE_STRING_AS_STRING
);
179 else if (PyTuple_Check (obj
)) {
180 int len
= PyTuple_GET_SIZE(obj
);
181 PyObject
*list
= PyList_New(len
+ 2); /* new ref */
182 PyObject
*item
; /* temporary new ref */
183 PyObject
*empty_str
; /* temporary new ref */
187 if (!list
) return NULL
;
189 PyErr_SetString(PyExc_ValueError
, "D-Bus structs cannot be empty");
193 /* Set the first and last elements of list to be the parentheses */
194 item
= PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING
);
195 if (PyList_SetItem(list
, 0, item
) < 0) {
199 item
= PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING
);
200 if (PyList_SetItem(list
, len
+ 1, item
) < 0) {
204 if (!item
|| !PyList_GET_ITEM(list
, 0)) {
210 for (i
= 0; i
< len
; i
++) {
211 item
= PyTuple_GetItem(obj
, i
);
216 item
= _signature_string_from_pyobject(item
, NULL
);
221 if (PyList_SetItem(list
, i
+ 1, item
) < 0) {
227 empty_str
= PyString_FromString("");
229 /* really shouldn't happen */
233 ret
= PyObject_CallMethod(empty_str
, "join", "(O)", list
); /* new ref */
234 /* whether ret is NULL or not, */
235 Py_DECREF(empty_str
);
239 else if (PyList_Check(obj
)) {
241 PyObject
*ret
= PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
);
242 if (!ret
) return NULL
;
243 if (DBusPyArray_Check(obj
) && PyString_Check(((DBusPyArray
*)obj
)->signature
)) {
244 PyString_Concat(&ret
, ((DBusPyArray
*)obj
)->signature
);
247 if (PyList_GET_SIZE(obj
) == 0) {
248 /* No items, so fail. Or should we guess "av"? */
249 PyErr_SetString (PyExc_ValueError
, "Unable to guess signature "
250 "from an empty list");
253 tmp
= PyList_GetItem(obj
, 0);
254 tmp
= _signature_string_from_pyobject(tmp
, NULL
);
255 if (!tmp
) return NULL
;
256 PyString_ConcatAndDel (&ret
, tmp
);
259 else if (PyDict_Check(obj
)) {
260 PyObject
*key
, *value
, *keysig
, *valuesig
;
262 PyObject
*ret
= NULL
;
264 if (DBusPyDict_Check(obj
) && PyString_Check(((DBusPyDict
*)obj
)->signature
)) {
265 const char *sig
= PyString_AS_STRING(((DBusPyDict
*)obj
)->signature
);
267 return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
268 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
270 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
273 if (!PyDict_Next(obj
, &pos
, &key
, &value
)) {
274 /* No items, so fail. Or should we guess "a{vv}"? */
275 PyErr_SetString(PyExc_ValueError
, "Unable to guess signature "
276 "from an empty dict");
279 keysig
= _signature_string_from_pyobject(key
, NULL
);
280 valuesig
= _signature_string_from_pyobject(value
, NULL
);
281 if (keysig
&& valuesig
) {
282 ret
= PyString_FromFormat ((DBUS_TYPE_ARRAY_AS_STRING
283 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
285 DBUS_DICT_ENTRY_END_CHAR_AS_STRING
),
286 PyString_AS_STRING(keysig
),
287 PyString_AS_STRING(valuesig
));
290 Py_XDECREF(valuesig
);
294 PyErr_Format(PyExc_TypeError
, "Don't know how which D-Bus type "
295 "to use to encode type \"%s\"",
296 obj
->ob_type
->tp_name
);
302 Message_guess_signature(PyObject
*unused UNUSED
, PyObject
*args
)
304 PyObject
*tmp
, *ret
= NULL
;
307 if (!PyErr_Occurred()) {
308 PyErr_BadInternalCall();
314 fprintf(stderr
, "DBG/%ld: called Message_guess_signature", (long)getpid());
315 PyObject_Print(args
, stderr
, 0);
316 fprintf(stderr
, "\n");
319 if (!PyTuple_Check(args
)) {
320 DBG("%s", "Message_guess_signature: args not a tuple");
321 PyErr_BadInternalCall();
325 /* if there were no args, easy */
326 if (PyTuple_GET_SIZE(args
) == 0) {
327 DBG("%s", "Message_guess_signature: no args, so return Signature('')");
328 return PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s)", "");
331 /* if there were args, the signature we want is, by construction,
332 * exactly the signature we get for the tuple args, except that we don't
333 * want the parentheses. */
334 tmp
= _signature_string_from_pyobject(args
, NULL
);
336 DBG("%s", "Message_guess_signature: failed");
339 if (!PyString_Check(tmp
) || PyString_GET_SIZE(tmp
) < 2) {
340 PyErr_SetString(PyExc_RuntimeError
, "Internal error: "
341 "_signature_string_from_pyobject returned "
346 ret
= PyObject_CallFunction((PyObject
*)&DBusPySignature_Type
, "(s#)",
347 PyString_AS_STRING (tmp
) + 1,
348 PyString_GET_SIZE (tmp
) - 2);
349 DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret
,
350 ret
? PyString_AS_STRING(ret
) : "(NULL)");
355 static int _message_iter_append_pyobject(DBusMessageIter
*appender
,
356 DBusSignatureIter
*sig_iter
,
360 _message_iter_append_string(DBusMessageIter
*appender
,
361 int sig_type
, PyObject
*obj
)
365 if (PyString_Check (obj
)) {
368 /* Raise TypeError if the string has embedded NULs */
369 if (PyString_AsStringAndSize (obj
, &s
, NULL
) < 0) return -1;
370 /* Surely there's a faster stdlib way to validate UTF-8... */
371 unicode
= PyUnicode_DecodeUTF8 (s
, PyString_GET_SIZE (obj
), NULL
);
373 PyErr_SetString (PyExc_UnicodeError
, "String parameters "
374 "to be sent over D-Bus must be valid UTF-8");
380 DBG("Performing actual append: string %s", s
);
381 if (!dbus_message_iter_append_basic (appender
, sig_type
,
387 else if (PyUnicode_Check (obj
)) {
388 PyObject
*utf8
= PyUnicode_AsUTF8String (obj
);
389 if (!utf8
) return -1;
390 /* Raise TypeError if the string has embedded NULs */
391 if (PyString_AsStringAndSize (utf8
, &s
, NULL
) < 0) return -1;
392 DBG("Performing actual append: string (from unicode) %s", s
);
393 if (!dbus_message_iter_append_basic (appender
, sig_type
, &s
)) {
400 PyErr_SetString (PyExc_TypeError
,
401 "Expected a string or unicode object");
408 _message_iter_append_byte(DBusMessageIter
*appender
, PyObject
*obj
)
412 if (PyString_Check(obj
)) {
413 if (PyString_GET_SIZE(obj
) != 1) {
414 PyErr_Format(PyExc_ValueError
, "Expected a string of "
415 "length 1 byte, but found %d bytes",
416 PyString_GET_SIZE (obj
));
419 y
= *(unsigned char *)PyString_AS_STRING(obj
);
422 long i
= PyInt_AsLong (obj
);
424 if (i
== -1 && PyErr_Occurred()) return -1;
425 if (i
< 0 || i
> 0xff) {
426 PyErr_Format(PyExc_ValueError
, "%d outside range for a "
427 "byte value", (int)i
);
432 DBG("Performing actual append: byte (from unicode) \\x%02x", (unsigned)y
);
433 if (!dbus_message_iter_append_basic(appender
, DBUS_TYPE_BYTE
, &y
)) {
441 _message_iter_append_dictentry(DBusMessageIter
*appender
,
442 DBusSignatureIter
*sig_iter
,
443 PyObject
*dict
, PyObject
*key
)
445 DBusSignatureIter sub_sig_iter
;
448 PyObject
*value
= PyObject_GetItem(dict
, key
);
450 if (!value
) return -1;
453 fprintf(stderr
, "Append dictentry: ");
454 PyObject_Print(key
, stderr
, 0);
455 fprintf(stderr
, " => ");
456 PyObject_Print(value
, stderr
, 0);
457 fprintf(stderr
, "\n");
460 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
461 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
465 s
= dbus_signature_iter_get_signature(sig_iter
);
466 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
468 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
469 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
474 DBG("%s", "Opening DICT_ENTRY container");
475 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_DICT_ENTRY
,
480 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, key
);
482 ret
= _message_iter_append_pyobject(&sub
, &sub_sig_iter
, value
);
484 DBG("%s", "Closing DICT_ENTRY container");
485 if (!dbus_message_iter_close_container(appender
, &sub
)) {
495 _message_iter_append_multi(DBusMessageIter
*appender
,
496 const DBusSignatureIter
*sig_iter
,
497 int mode
, PyObject
*obj
)
499 DBusMessageIter sub_appender
;
500 DBusSignatureIter sub_sig_iter
;
503 PyObject
*iterator
= PyObject_GetIter(obj
);
505 int container
= mode
;
508 fprintf(stderr
, "Appending multiple: ");
509 PyObject_Print(obj
, stderr
, 0);
510 fprintf(stderr
, "\n");
513 if (!iterator
) return -1;
514 if (mode
== DBUS_TYPE_DICT_ENTRY
) container
= DBUS_TYPE_ARRAY
;
516 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
517 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
521 s
= dbus_signature_iter_get_signature(sig_iter
);
522 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
524 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
525 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
530 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
531 sig
= dbus_signature_iter_get_signature(&sub_sig_iter
);
538 /* else leave sig set to NULL. */
540 DBG("Opening %c container", container
);
541 if (!dbus_message_iter_open_container(appender
, container
,
542 sig
, &sub_appender
)) {
548 while ((contents
= PyIter_Next(iterator
))) {
550 if (mode
== DBUS_TYPE_ARRAY
|| mode
== DBUS_TYPE_DICT_ENTRY
) {
551 DBG("Recursing signature iterator %p -> %p", sig_iter
, &sub_sig_iter
);
552 dbus_signature_iter_recurse(sig_iter
, &sub_sig_iter
);
556 s
= dbus_signature_iter_get_signature(sig_iter
);
557 DBG("Signature of parent iterator %p is %s", sig_iter
, s
);
559 s
= dbus_signature_iter_get_signature(&sub_sig_iter
);
560 DBG("Signature of sub-iterator %p is %s", &sub_sig_iter
, s
);
566 if (mode
== DBUS_TYPE_DICT_ENTRY
) {
567 ret
= _message_iter_append_dictentry(&sub_appender
, &sub_sig_iter
,
571 ret
= _message_iter_append_pyobject(&sub_appender
, &sub_sig_iter
,
579 if (PyErr_Occurred()) ret
= -1;
580 /* This must be run as cleanup, even on failure. */
581 DBG("Closing %c container", container
);
582 if (!dbus_message_iter_close_container(appender
, &sub_appender
)) {
588 Py_XDECREF(iterator
);
594 _message_iter_append_string_as_byte_array (DBusMessageIter
*appender
,
597 /* a bit of a faster path for byte arrays that are strings */
598 int len
= PyString_GET_SIZE(obj
);
603 s
= PyString_AS_STRING(obj
);
604 DBG("%s", "Opening ARRAY container");
605 if (!dbus_message_iter_open_container(appender
, DBUS_TYPE_ARRAY
,
606 DBUS_TYPE_BYTE_AS_STRING
, &sub
)) {
610 DBG("Appending fixed array of %d bytes", len
);
611 if (dbus_message_iter_append_fixed_array(&sub
, DBUS_TYPE_BYTE
, &s
, len
)) {
618 DBG("%s", "Closing ARRAY container");
619 if (!dbus_message_iter_close_container(appender
, &sub
)) {
626 /* Encode some Python object into a D-Bus variant slot. */
628 _message_iter_append_variant(DBusMessageIter
*appender
, PyObject
*obj
)
630 DBusSignatureIter obj_sig_iter
;
631 const char *obj_sig_str
;
636 /* Separate the object into the contained object, and the number of
637 * variants it's wrapped in. */
638 obj_sig
= _signature_string_from_pyobject(obj
, &variant_level
);
639 if (!obj_sig
) return -1;
641 obj_sig_str
= PyString_AsString(obj_sig
);
642 if (!obj_sig_str
) return -1;
644 if (variant_level
< 1) {
648 dbus_signature_iter_init(&obj_sig_iter
, obj_sig_str
);
650 { /* scope for variant_iters */
651 DBusMessageIter variant_iters
[variant_level
];
654 for (i
= 0; i
< variant_level
; i
++) {
655 DBusMessageIter
*child
= &variant_iters
[i
];
656 /* The first is a special case: its parent is the iter passed in
657 * to this function, instead of being the previous one in the
660 DBusMessageIter
*parent
= (i
== 0
662 : &(variant_iters
[i
-1]));
663 /* The last is also a special case: it contains the actual
664 * object, rather than another variant
666 const char *sig_str
= (i
== variant_level
-1
668 : DBUS_TYPE_VARIANT_AS_STRING
);
670 DBG("Opening VARIANT container %p inside %p containing '%s'",
671 child
, parent
, sig_str
);
672 if (!dbus_message_iter_open_container (parent
, DBUS_TYPE_VARIANT
,
680 /* Put the object itself into the innermost variant */
681 ret
= _message_iter_append_pyobject(&variant_iters
[variant_level
-1],
684 /* here we rely on i (and variant_level) being a signed long */
685 for (i
= variant_level
- 1; i
>= 0; i
--) {
686 DBusMessageIter
*child
= &variant_iters
[i
];
687 /* The first is a special case: its parent is the iter passed in
688 * to this function, instead of being the previous one in the
691 DBusMessageIter
*parent
= (i
== 0 ? appender
692 : &(variant_iters
[i
-1]));
694 DBG("Closing VARIANT container %p inside %p", child
, parent
);
695 if (!dbus_message_iter_close_container (parent
, child
)) {
705 Py_XDECREF (obj_sig
);
710 _message_iter_append_pyobject(DBusMessageIter
*appender
,
711 DBusSignatureIter
*sig_iter
,
714 int sig_type
= dbus_signature_iter_get_current_type (sig_iter
);
718 dbus_uint16_t uint16
;
720 dbus_uint32_t uint32
;
722 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
723 dbus_uint64_t uint64
;
730 fprintf(stderr
, "Appending object at %p: ", obj
);
731 PyObject_Print(obj
, stderr
, 0);
732 fprintf(stderr
, " into appender at %p, dbus wants type %c\n",
737 /* The numeric types are relatively simple to deal with, so are
740 case DBUS_TYPE_BOOLEAN
:
741 if (PyObject_IsTrue(obj
)) {
747 DBG("Performing actual append: bool(%ld)", (long)u
.b
);
748 if (!dbus_message_iter_append_basic (appender
, sig_type
, &u
.b
)) {
756 case DBUS_TYPE_DOUBLE
:
757 u
.d
= PyFloat_AsDouble (obj
);
758 if (PyErr_Occurred()) {
762 DBG("Performing actual append: double(%f)", u
.d
);
763 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.d
)) {
771 #ifdef WITH_DBUS_FLOAT32
772 case DBUS_TYPE_FLOAT
:
773 u
.d
= PyFloat_AsDouble (obj
);
774 if (PyErr_Occurred()) {
779 DBG("Performing actual append: float(%f)", u
.f
);
780 if (!dbus_message_iter_append_basic(appender
, sig_type
, &u
.f
)) {
789 /* The integer types are all basically the same - we delegate to
790 intNN_range_check() */
791 #define PROCESS_INTEGER(size) \
792 u.size = dbus_py_##size##_range_check (obj);\
793 if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
797 DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
798 if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
805 case DBUS_TYPE_INT16
:
806 PROCESS_INTEGER(int16
)
808 case DBUS_TYPE_UINT16
:
809 PROCESS_INTEGER(uint16
)
811 case DBUS_TYPE_INT32
:
812 PROCESS_INTEGER(int32
)
814 case DBUS_TYPE_UINT32
:
815 PROCESS_INTEGER(uint32
)
817 #if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
818 case DBUS_TYPE_INT64
:
819 PROCESS_INTEGER(int64
)
821 case DBUS_TYPE_UINT64
:
822 PROCESS_INTEGER(uint64
)
825 case DBUS_TYPE_INT64
:
826 case DBUS_TYPE_UINT64
:
827 PyErr_SetString(PyExc_NotImplementedError
, "64-bit integer "
828 "types are not supported on this platform");
832 #undef PROCESS_INTEGER
834 /* Now the more complicated cases, which are delegated to helper
835 * functions (although in practice, the compiler will hopefully
836 * inline them anyway). */
838 case DBUS_TYPE_STRING
:
839 case DBUS_TYPE_SIGNATURE
:
840 case DBUS_TYPE_OBJECT_PATH
:
841 ret
= _message_iter_append_string(appender
, sig_type
, obj
);
845 ret
= _message_iter_append_byte(appender
, obj
);
848 case DBUS_TYPE_ARRAY
:
849 /* 3 cases - it might actually be a dict, or it might be a byte array
850 * being copied from a string (for which we have a faster path),
851 * or it might be a generic array. */
853 sig_type
= dbus_signature_iter_get_element_type(sig_iter
);
854 if (sig_type
== DBUS_TYPE_DICT_ENTRY
)
855 ret
= _message_iter_append_multi(appender
, sig_iter
,
856 DBUS_TYPE_DICT_ENTRY
, obj
);
857 else if (sig_type
== DBUS_TYPE_BYTE
&& PyString_Check(obj
))
858 ret
= _message_iter_append_string_as_byte_array(appender
, obj
);
860 ret
= _message_iter_append_multi(appender
, sig_iter
,
861 DBUS_TYPE_ARRAY
, obj
);
862 DBG("_message_iter_append_multi(): %d", ret
);
865 case DBUS_TYPE_STRUCT
:
866 ret
= _message_iter_append_multi(appender
, sig_iter
, sig_type
, obj
);
869 case DBUS_TYPE_VARIANT
:
870 ret
= _message_iter_append_variant(appender
, obj
);
873 case DBUS_TYPE_INVALID
:
874 PyErr_SetString(PyExc_TypeError
, "Fewer items found in D-Bus "
875 "signature than in Python arguments");
880 PyErr_Format(PyExc_TypeError
, "Unknown type '\\x%x' in D-Bus "
881 "signature", sig_type
);
885 if (ret
< 0) return -1;
887 DBG("Advancing signature iter at %p", sig_iter
);
892 dbus_signature_iter_next(sig_iter
);
894 DBG("- result: %ld, type %02x '%c'", (long)b
,
895 (int)dbus_signature_iter_get_current_type(sig_iter
),
896 (int)dbus_signature_iter_get_current_type(sig_iter
));
904 Message_append(Message
*self
, PyObject
*args
, PyObject
*kwargs
)
906 const char *signature
= NULL
;
907 PyObject
*signature_obj
= NULL
;
908 DBusSignatureIter sig_iter
;
909 DBusMessageIter appender
;
911 static char *argnames
[] = {"signature", NULL
};
913 if (!self
->msg
) return DBusException_UnusableMessage ();
916 fprintf(stderr
, "DBG/%ld: called Message_append(*", (long)getpid());
917 PyObject_Print(args
, stderr
, 0);
919 fprintf(stderr
, ", **");
920 PyObject_Print(kwargs
, stderr
, 0);
922 fprintf(stderr
, ")\n");
925 /* only use kwargs for this step: deliberately ignore args for now */
926 if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple
, kwargs
, "|z:append",
927 argnames
, &signature
)) return NULL
;
930 DBG("%s", "No signature for message, guessing...");
931 signature_obj
= Message_guess_signature(NULL
, args
);
932 if (!signature_obj
) return NULL
;
933 signature
= PyString_AS_STRING (signature_obj
);
935 /* from here onwards, you have to do a goto rather than returning NULL
936 to make sure signature_obj gets freed */
938 /* iterate over args and the signature, together */
939 if (!dbus_signature_validate(signature
, NULL
)) {
940 PyErr_SetString(PyExc_ValueError
, "Corrupt type signature");
943 dbus_signature_iter_init(&sig_iter
, signature
);
944 dbus_message_iter_init_append(self
->msg
, &appender
);
945 for (i
= 0; i
< PyTuple_GET_SIZE(args
); i
++) {
946 if (_message_iter_append_pyobject(&appender
, &sig_iter
,
947 PyTuple_GET_ITEM (args
, i
)) < 0) {
951 if (dbus_signature_iter_get_current_type(&sig_iter
)
952 != DBUS_TYPE_INVALID
) {
953 PyErr_SetString(PyExc_TypeError
, "More items found in D-Bus "
954 "signature than in Python arguments");
959 Py_XDECREF(signature_obj
);
963 /* "If appending any of the arguments fails due to lack of memory,
964 * generally the message is hosed and you have to start over" -libdbus docs
965 * Enforce this by throwing away the message structure.
967 dbus_message_unref(self
->msg
);
970 Py_XDECREF(signature_obj
);
974 /* vim:set ft=c cino< sw=4 sts=4 et: */