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. <http://www.collabora.co.uk/>
6
* Permission is hereby granted, free of charge, to any person
7
* obtaining a copy of this software and associated documentation
8
* files (the "Software"), to deal in the Software without
9
* restriction, including without limitation the rights to use, copy,
10
* modify, merge, publish, distribute, sublicense, and/or sell copies
11
* of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
14
* The above copyright notice and this permission notice shall be
15
* included in all copies or substantial portions of the Software.
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
* DEALINGS IN THE SOFTWARE.
31
#define DBG_IS_TOO_VERBOSE
32
#include "types-internal.h"
33
#include "message-internal.h"
35
/* Return the number of variants wrapping the given object. Return 0
36
* if the object is not a D-Bus type.
39
get_variant_level(PyObject *obj)
41
if (DBusPyIntBase_Check(obj)) {
42
return ((DBusPyIntBase *)obj)->variant_level;
44
else if (DBusPyFloatBase_Check(obj)) {
45
return ((DBusPyFloatBase *)obj)->variant_level;
47
else if (DBusPyArray_Check(obj)) {
48
return ((DBusPyArray *)obj)->variant_level;
50
else if (DBusPyDict_Check(obj)) {
51
return ((DBusPyDict *)obj)->variant_level;
53
else if (DBusPyString_Check(obj)) {
54
return ((DBusPyString *)obj)->variant_level;
56
else if (DBusPyLongBase_Check(obj) ||
57
DBusPyStrBase_Check(obj) ||
58
DBusPyStruct_Check(obj)) {
59
return dbus_py_variant_level_get(obj);
66
char dbus_py_Message_append__doc__[] = (
67
"set_args(*args[, **kwargs])\n\n"
68
"Set the message's arguments from the positional parameter, according to\n"
69
"the signature given by the ``signature`` keyword parameter.\n"
71
"The following type conversions are supported:\n\n"
72
"=============================== ===========================\n"
73
"D-Bus (in signature) Python\n"
74
"=============================== ===========================\n"
75
"boolean (b) any object (via bool())\n"
76
"byte (y) string of length 1\n"
78
"any integer type any integer\n"
79
"double (d) any float\n"
80
"object path anything with a __dbus_object_path__ attribute\n"
81
"string, signature, object path str (must be UTF-8) or unicode\n"
82
"dict (a{...}) any mapping\n"
83
"array (a...) any iterable over appropriate objects\n"
84
"struct ((...)) any iterable over appropriate objects\n"
85
"variant any object above (guess type as below)\n"
86
"=============================== ===========================\n"
88
"Here 'any integer' means anything on which int() or long()\n"
89
"(as appropriate) will work, except for basestring subclasses.\n"
90
"'Any float' means anything on which float() will work, except\n"
91
"for basestring subclasses.\n"
93
"If there is no signature, guess from the arguments using\n"
94
"the static method `Message.guess_signature`.\n"
97
char dbus_py_Message_guess_signature__doc__[] = (
98
"guess_signature(*args) -> Signature [static method]\n\n"
99
"Guess a D-Bus signature which should be used to encode the given\n"
102
"The signature is constructed as follows:\n\n"
103
"+-------------------------------+---------------------------+\n"
105
"+===============================+===========================+\n"
106
"|D-Bus type, variant_level > 0 |variant (v) |\n"
107
"+-------------------------------+---------------------------+\n"
108
"|D-Bus type, variant_level == 0 |the corresponding type |\n"
109
"+-------------------------------+---------------------------+\n"
110
"|anything with a |object path |\n"
111
"|__dbus_object_path__ attribute | |\n"
112
"+-------------------------------+---------------------------+\n"
113
"|bool |boolean (y) |\n"
114
"+-------------------------------+---------------------------+\n"
115
"|any other int subclass |int32 (i) |\n"
116
"+-------------------------------+---------------------------+\n"
117
"|any other long subclass |int64 (x) |\n"
118
"+-------------------------------+---------------------------+\n"
119
"|any other float subclass |double (d) |\n"
120
"+-------------------------------+---------------------------+\n"
121
"|any other str subclass |string (s) |\n"
122
"+-------------------------------+---------------------------+\n"
123
"|any other unicode subclass |string (s) |\n"
124
"+-------------------------------+---------------------------+\n"
125
"|any other tuple subclass |struct ((...)) |\n"
126
"+-------------------------------+---------------------------+\n"
127
"|any other list subclass |array (a...), guess |\n"
128
"| |contents' type according to|\n"
129
"| |type of first item |\n"
130
"+-------------------------------+---------------------------+\n"
131
"|any other dict subclass |dict (a{...}), guess key, |\n"
132
"| |value type according to |\n"
133
"| |types for an arbitrary item|\n"
134
"+-------------------------------+---------------------------+\n"
135
"|anything else |raise TypeError |\n"
136
"+-------------------------------+---------------------------+\n"
139
/* return a new reference, possibly to None */
141
get_object_path(PyObject *obj)
143
PyObject *magic_attr = PyObject_GetAttr(obj, dbus_py__dbus_object_path__const);
146
if (PyString_Check(magic_attr)) {
150
Py_CLEAR(magic_attr);
151
PyErr_SetString(PyExc_TypeError, "__dbus_object_path__ must be "
157
/* Ignore exceptions, except for SystemExit and KeyboardInterrupt */
158
if (PyErr_ExceptionMatches(PyExc_SystemExit) ||
159
PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
166
/* Return a new reference. If the object is a variant and variant_level_ptr
167
* is not NULL, put the variant level in the variable pointed to, and
168
* return the contained type instead of "v". */
170
_signature_string_from_pyobject(PyObject *obj, long *variant_level_ptr)
172
PyObject *magic_attr;
173
long variant_level = get_variant_level(obj);
174
if (variant_level_ptr) {
175
*variant_level_ptr = variant_level;
177
else if (variant_level > 0) {
178
return PyString_FromString(DBUS_TYPE_VARIANT_AS_STRING);
181
if (obj == Py_True || obj == Py_False) {
182
return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING);
185
magic_attr = get_object_path(obj);
188
if (magic_attr != Py_None) {
189
Py_CLEAR(magic_attr);
190
return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING);
192
Py_CLEAR(magic_attr);
194
/* Ordering is important: some of these are subclasses of each other. */
195
if (PyInt_Check(obj)) {
196
if (DBusPyInt16_Check(obj))
197
return PyString_FromString(DBUS_TYPE_INT16_AS_STRING);
198
else if (DBusPyInt32_Check(obj))
199
return PyString_FromString(DBUS_TYPE_INT32_AS_STRING);
200
else if (DBusPyByte_Check(obj))
201
return PyString_FromString(DBUS_TYPE_BYTE_AS_STRING);
202
else if (DBusPyUInt16_Check(obj))
203
return PyString_FromString(DBUS_TYPE_UINT16_AS_STRING);
204
else if (DBusPyBoolean_Check(obj))
205
return PyString_FromString(DBUS_TYPE_BOOLEAN_AS_STRING);
207
return PyString_FromString(DBUS_TYPE_INT32_AS_STRING);
209
else if (PyLong_Check(obj)) {
210
if (DBusPyInt64_Check(obj))
211
return PyString_FromString(DBUS_TYPE_INT64_AS_STRING);
212
else if (DBusPyUInt32_Check(obj))
213
return PyString_FromString(DBUS_TYPE_UINT32_AS_STRING);
214
else if (DBusPyUInt64_Check(obj))
215
return PyString_FromString(DBUS_TYPE_UINT64_AS_STRING);
217
return PyString_FromString(DBUS_TYPE_INT64_AS_STRING);
219
else if (PyUnicode_Check(obj))
220
return PyString_FromString(DBUS_TYPE_STRING_AS_STRING);
221
#if defined(DBUS_TYPE_UNIX_FD)
222
else if (DBusPyUnixFd_Check(obj))
223
return PyString_FromString(DBUS_TYPE_UNIX_FD_AS_STRING);
225
else if (PyFloat_Check(obj)) {
226
#ifdef WITH_DBUS_FLOAT32
227
if (DBusPyDouble_Check(obj))
228
return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING);
229
else if (DBusPyFloat_Check(obj))
230
return PyString_FromString(DBUS_TYPE_FLOAT_AS_STRING);
233
return PyString_FromString(DBUS_TYPE_DOUBLE_AS_STRING);
235
else if (PyString_Check(obj)) {
236
if (DBusPyObjectPath_Check(obj))
237
return PyString_FromString(DBUS_TYPE_OBJECT_PATH_AS_STRING);
238
else if (DBusPySignature_Check(obj))
239
return PyString_FromString(DBUS_TYPE_SIGNATURE_AS_STRING);
240
else if (DBusPyByteArray_Check(obj))
241
return PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING
242
DBUS_TYPE_BYTE_AS_STRING);
244
return PyString_FromString(DBUS_TYPE_STRING_AS_STRING);
246
else if (PyTuple_Check(obj)) {
247
Py_ssize_t len = PyTuple_GET_SIZE(obj);
248
PyObject *list = PyList_New(len + 2); /* new ref */
249
PyObject *item; /* temporary new ref */
250
PyObject *empty_str; /* temporary new ref */
254
if (!list) return NULL;
256
PyErr_SetString(PyExc_ValueError, "D-Bus structs cannot be empty");
260
/* Set the first and last elements of list to be the parentheses */
261
item = PyString_FromString(DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
262
if (PyList_SetItem(list, 0, item) < 0) {
266
item = PyString_FromString(DBUS_STRUCT_END_CHAR_AS_STRING);
267
if (PyList_SetItem(list, len + 1, item) < 0) {
271
if (!item || !PyList_GET_ITEM(list, 0)) {
277
for (i = 0; i < len; i++) {
278
item = PyTuple_GetItem(obj, i);
283
item = _signature_string_from_pyobject(item, NULL);
288
if (PyList_SetItem(list, i + 1, item) < 0) {
294
empty_str = PyString_FromString("");
296
/* really shouldn't happen */
300
ret = PyObject_CallMethod(empty_str, "join", "(O)", list); /* new ref */
301
/* whether ret is NULL or not, */
306
else if (PyList_Check(obj)) {
308
PyObject *ret = PyString_FromString(DBUS_TYPE_ARRAY_AS_STRING);
309
if (!ret) return NULL;
310
if (DBusPyArray_Check(obj) && PyString_Check(((DBusPyArray *)obj)->signature)) {
311
PyString_Concat(&ret, ((DBusPyArray *)obj)->signature);
314
if (PyList_GET_SIZE(obj) == 0) {
315
/* No items, so fail. Or should we guess "av"? */
316
PyErr_SetString(PyExc_ValueError, "Unable to guess signature "
317
"from an empty list");
320
tmp = PyList_GetItem(obj, 0);
321
tmp = _signature_string_from_pyobject(tmp, NULL);
322
if (!tmp) return NULL;
323
PyString_ConcatAndDel(&ret, tmp);
326
else if (PyDict_Check(obj)) {
327
PyObject *key, *value, *keysig, *valuesig;
329
PyObject *ret = NULL;
331
if (DBusPyDict_Check(obj) && PyString_Check(((DBusPyDict *)obj)->signature)) {
332
const char *sig = PyString_AS_STRING(((DBusPyDict *)obj)->signature);
334
return PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
335
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
337
DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
340
if (!PyDict_Next(obj, &pos, &key, &value)) {
341
/* No items, so fail. Or should we guess "a{vv}"? */
342
PyErr_SetString(PyExc_ValueError, "Unable to guess signature "
343
"from an empty dict");
346
keysig = _signature_string_from_pyobject(key, NULL);
347
valuesig = _signature_string_from_pyobject(value, NULL);
348
if (keysig && valuesig) {
349
ret = PyString_FromFormat((DBUS_TYPE_ARRAY_AS_STRING
350
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
352
DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
353
PyString_AS_STRING(keysig),
354
PyString_AS_STRING(valuesig));
361
PyErr_Format(PyExc_TypeError, "Don't know how which D-Bus type "
362
"to use to encode type \"%s\"",
363
obj->ob_type->tp_name);
369
dbus_py_Message_guess_signature(PyObject *unused UNUSED, PyObject *args)
371
PyObject *tmp, *ret = NULL;
374
if (!PyErr_Occurred()) {
375
PyErr_BadInternalCall();
381
fprintf(stderr, "DBG/%ld: called Message_guess_signature", (long)getpid());
382
PyObject_Print(args, stderr, 0);
383
fprintf(stderr, "\n");
386
if (!PyTuple_Check(args)) {
387
DBG("%s", "Message_guess_signature: args not a tuple");
388
PyErr_BadInternalCall();
392
/* if there were no args, easy */
393
if (PyTuple_GET_SIZE(args) == 0) {
394
DBG("%s", "Message_guess_signature: no args, so return Signature('')");
395
return PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s)", "");
398
/* if there were args, the signature we want is, by construction,
399
* exactly the signature we get for the tuple args, except that we don't
400
* want the parentheses. */
401
tmp = _signature_string_from_pyobject(args, NULL);
403
DBG("%s", "Message_guess_signature: failed");
406
if (!PyString_Check(tmp) || PyString_GET_SIZE(tmp) < 2) {
407
PyErr_SetString(PyExc_RuntimeError, "Internal error: "
408
"_signature_string_from_pyobject returned "
413
ret = PyObject_CallFunction((PyObject *)&DBusPySignature_Type, "(s#)",
414
PyString_AS_STRING(tmp) + 1,
415
PyString_GET_SIZE(tmp) - 2);
416
DBG("Message_guess_signature: returning Signature at %p \"%s\"", ret,
417
ret ? PyString_AS_STRING(ret) : "(NULL)");
422
static int _message_iter_append_pyobject(DBusMessageIter *appender,
423
DBusSignatureIter *sig_iter,
426
static int _message_iter_append_variant(DBusMessageIter *appender,
430
_message_iter_append_string(DBusMessageIter *appender,
431
int sig_type, PyObject *obj,
432
dbus_bool_t allow_object_path_attr)
436
if (sig_type == DBUS_TYPE_OBJECT_PATH && allow_object_path_attr) {
437
PyObject *object_path = get_object_path (obj);
439
if (object_path == Py_None) {
440
Py_CLEAR(object_path);
442
else if (!object_path) {
446
int ret = _message_iter_append_string(appender, sig_type,
448
Py_CLEAR(object_path);
453
if (PyString_Check(obj)) {
456
/* Raise TypeError if the string has embedded NULs */
457
if (PyString_AsStringAndSize(obj, &s, NULL) < 0) return -1;
458
/* Surely there's a faster stdlib way to validate UTF-8... */
459
unicode = PyUnicode_DecodeUTF8(s, PyString_GET_SIZE(obj), NULL);
461
PyErr_SetString(PyExc_UnicodeError, "String parameters "
462
"to be sent over D-Bus must be valid UTF-8");
467
DBG("Performing actual append: string %s", s);
468
if (!dbus_message_iter_append_basic(appender, sig_type,
474
else if (PyUnicode_Check(obj)) {
475
PyObject *utf8 = PyUnicode_AsUTF8String(obj);
476
if (!utf8) return -1;
477
/* Raise TypeError if the string has embedded NULs */
478
if (PyString_AsStringAndSize(utf8, &s, NULL) < 0) return -1;
479
DBG("Performing actual append: string (from unicode) %s", s);
480
if (!dbus_message_iter_append_basic(appender, sig_type, &s)) {
487
PyErr_SetString(PyExc_TypeError,
488
"Expected a string or unicode object");
495
_message_iter_append_byte(DBusMessageIter *appender, PyObject *obj)
499
if (PyString_Check(obj)) {
500
if (PyString_GET_SIZE(obj) != 1) {
501
PyErr_Format(PyExc_ValueError, "Expected a string of "
502
"length 1 byte, but found %d bytes",
503
(int) PyString_GET_SIZE(obj));
506
y = *(unsigned char *)PyString_AS_STRING(obj);
509
long i = PyInt_AsLong(obj);
511
if (i == -1 && PyErr_Occurred()) return -1;
512
if (i < 0 || i > 0xff) {
513
PyErr_Format(PyExc_ValueError, "%d outside range for a "
514
"byte value", (int)i);
519
DBG("Performing actual append: byte \\x%02x", (unsigned)y);
520
if (!dbus_message_iter_append_basic(appender, DBUS_TYPE_BYTE, &y)) {
528
dbuspy_message_iter_close_container(DBusMessageIter *iter,
529
DBusMessageIter *sub,
532
#ifdef HAVE_DBUS_MESSAGE_ITER_ABANDON_CONTAINER
534
dbus_message_iter_abandon_container(iter, sub);
540
return dbus_message_iter_close_container(iter, sub);
543
#if defined(DBUS_TYPE_UNIX_FD)
545
_message_iter_append_unixfd(DBusMessageIter *appender, PyObject *obj)
549
if (PyInt_Check(obj)) {
550
fd = PyInt_AsLong(obj);
551
} else if (PyObject_IsInstance(obj, (PyObject*) &DBusPyUnixFd_Type)) {
552
fd = dbus_py_unix_fd_get_fd(obj);
557
DBG("Performing actual append: fd %d", fd);
558
if (!dbus_message_iter_append_basic(appender, DBUS_TYPE_UNIX_FD, &fd)) {
567
_message_iter_append_dictentry(DBusMessageIter *appender,
568
DBusSignatureIter *sig_iter,
569
PyObject *dict, PyObject *key)
571
DBusSignatureIter sub_sig_iter;
574
PyObject *value = PyObject_GetItem(dict, key);
577
if (!value) return -1;
580
fprintf(stderr, "Append dictentry: ");
581
PyObject_Print(key, stderr, 0);
582
fprintf(stderr, " => ");
583
PyObject_Print(value, stderr, 0);
584
fprintf(stderr, "\n");
587
DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
588
dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
592
s = dbus_signature_iter_get_signature(sig_iter);
593
DBG("Signature of parent iterator %p is %s", sig_iter, s);
595
s = dbus_signature_iter_get_signature(&sub_sig_iter);
596
DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
601
DBG("%s", "Opening DICT_ENTRY container");
602
if (!dbus_message_iter_open_container(appender, DBUS_TYPE_DICT_ENTRY,
607
ret = _message_iter_append_pyobject(&sub, &sub_sig_iter, key, &more);
609
ret = _message_iter_append_pyobject(&sub, &sub_sig_iter, value, &more);
611
DBG("%s", "Closing DICT_ENTRY container");
612
if (!dbuspy_message_iter_close_container(appender, &sub, (ret == 0))) {
622
_message_iter_append_multi(DBusMessageIter *appender,
623
const DBusSignatureIter *sig_iter,
624
int mode, PyObject *obj)
626
DBusMessageIter sub_appender;
627
DBusSignatureIter sub_sig_iter;
630
PyObject *iterator = PyObject_GetIter(obj);
632
int container = mode;
633
dbus_bool_t is_byte_array = DBusPyByteArray_Check(obj);
637
assert(mode == DBUS_TYPE_DICT_ENTRY || mode == DBUS_TYPE_ARRAY ||
638
mode == DBUS_TYPE_STRUCT);
641
fprintf(stderr, "Appending multiple: ");
642
PyObject_Print(obj, stderr, 0);
643
fprintf(stderr, "\n");
646
if (!iterator) return -1;
647
if (mode == DBUS_TYPE_DICT_ENTRY) container = DBUS_TYPE_ARRAY;
649
DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
650
dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
654
s = dbus_signature_iter_get_signature(sig_iter);
655
DBG("Signature of parent iterator %p is %s", sig_iter, s);
657
s = dbus_signature_iter_get_signature(&sub_sig_iter);
658
DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
662
inner_type = dbus_signature_iter_get_current_type(&sub_sig_iter);
664
if (mode == DBUS_TYPE_ARRAY || mode == DBUS_TYPE_DICT_ENTRY) {
665
sig = dbus_signature_iter_get_signature(&sub_sig_iter);
672
/* else leave sig set to NULL. */
674
DBG("Opening %c container", container);
675
if (!dbus_message_iter_open_container(appender, container,
676
sig, &sub_appender)) {
683
while ((contents = PyIter_Next(iterator))) {
685
if (mode == DBUS_TYPE_ARRAY || mode == DBUS_TYPE_DICT_ENTRY) {
686
DBG("Recursing signature iterator %p -> %p", sig_iter, &sub_sig_iter);
687
dbus_signature_iter_recurse(sig_iter, &sub_sig_iter);
691
s = dbus_signature_iter_get_signature(sig_iter);
692
DBG("Signature of parent iterator %p is %s", sig_iter, s);
694
s = dbus_signature_iter_get_signature(&sub_sig_iter);
695
DBG("Signature of sub-iterator %p is %s", &sub_sig_iter, s);
702
PyErr_Format(PyExc_TypeError, "Fewer items found in struct's "
703
"D-Bus signature than in Python arguments ");
709
if (mode == DBUS_TYPE_DICT_ENTRY) {
710
ret = _message_iter_append_dictentry(&sub_appender, &sub_sig_iter,
713
else if (mode == DBUS_TYPE_ARRAY && is_byte_array
714
&& inner_type == DBUS_TYPE_VARIANT) {
715
/* Subscripting a ByteArray gives a str of length 1, but if the
716
* container is a ByteArray and the parameter is an array of
717
* variants, we want to produce an array of variants containing
718
* bytes, not strings.
720
PyObject *args = Py_BuildValue("(O)", contents);
725
byte = PyObject_Call((PyObject *)&DBusPyByte_Type, args, NULL);
729
ret = _message_iter_append_variant(&sub_appender, byte);
733
/* advances sub_sig_iter and sets more on success - for array
734
* this doesn't matter, for struct it's essential */
735
ret = _message_iter_append_pyobject(&sub_appender, &sub_sig_iter,
745
if (PyErr_Occurred()) {
748
else if (mode == DBUS_TYPE_STRUCT && more) {
749
PyErr_Format(PyExc_TypeError, "More items found in struct's D-Bus "
750
"signature than in Python arguments ");
754
/* This must be run as cleanup, even on failure. */
755
DBG("Closing %c container", container);
756
if (!dbuspy_message_iter_close_container(appender, &sub_appender, (ret == 0))) {
768
_message_iter_append_string_as_byte_array(DBusMessageIter *appender,
771
/* a bit of a faster path for byte arrays that are strings */
772
Py_ssize_t len = PyString_GET_SIZE(obj);
777
s = PyString_AS_STRING(obj);
778
DBG("%s", "Opening ARRAY container");
779
if (!dbus_message_iter_open_container(appender, DBUS_TYPE_ARRAY,
780
DBUS_TYPE_BYTE_AS_STRING, &sub)) {
784
DBG("Appending fixed array of %d bytes", len);
785
if (dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &s, len)) {
792
DBG("%s", "Closing ARRAY container");
793
if (!dbus_message_iter_close_container(appender, &sub)) {
800
/* Encode some Python object into a D-Bus variant slot. */
802
_message_iter_append_variant(DBusMessageIter *appender, PyObject *obj)
804
DBusSignatureIter obj_sig_iter;
805
const char *obj_sig_str;
811
/* Separate the object into the contained object, and the number of
812
* variants it's wrapped in. */
813
obj_sig = _signature_string_from_pyobject(obj, &variant_level);
814
if (!obj_sig) return -1;
816
obj_sig_str = PyString_AsString(obj_sig);
817
if (!obj_sig_str) return -1;
819
if (variant_level < 1) {
823
dbus_signature_iter_init(&obj_sig_iter, obj_sig_str);
825
{ /* scope for variant_iters */
826
DBusMessageIter variant_iters[variant_level];
829
for (i = 0; i < variant_level; i++) {
830
DBusMessageIter *child = &variant_iters[i];
831
/* The first is a special case: its parent is the iter passed in
832
* to this function, instead of being the previous one in the
835
DBusMessageIter *parent = (i == 0
837
: &(variant_iters[i-1]));
838
/* The last is also a special case: it contains the actual
839
* object, rather than another variant
841
const char *sig_str = (i == variant_level-1
843
: DBUS_TYPE_VARIANT_AS_STRING);
845
DBG("Opening VARIANT container %p inside %p containing '%s'",
846
child, parent, sig_str);
847
if (!dbus_message_iter_open_container(parent, DBUS_TYPE_VARIANT,
855
/* Put the object itself into the innermost variant */
856
ret = _message_iter_append_pyobject(&variant_iters[variant_level-1],
857
&obj_sig_iter, obj, &dummy);
859
/* here we rely on i (and variant_level) being a signed long */
860
for (i = variant_level - 1; i >= 0; i--) {
861
DBusMessageIter *child = &variant_iters[i];
862
/* The first is a special case: its parent is the iter passed in
863
* to this function, instead of being the previous one in the
866
DBusMessageIter *parent = (i == 0 ? appender
867
: &(variant_iters[i-1]));
869
DBG("Closing VARIANT container %p inside %p", child, parent);
870
if (!dbus_message_iter_close_container(parent, child)) {
884
/* On success, *more is set to whether there's more in the signature. */
886
_message_iter_append_pyobject(DBusMessageIter *appender,
887
DBusSignatureIter *sig_iter,
891
int sig_type = dbus_signature_iter_get_current_type(sig_iter);
895
dbus_uint16_t uint16;
897
dbus_uint32_t uint32;
899
#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
900
dbus_uint64_t uint64;
907
fprintf(stderr, "Appending object at %p: ", obj);
908
PyObject_Print(obj, stderr, 0);
909
fprintf(stderr, " into appender at %p, dbus wants type %c\n",
914
/* The numeric types are relatively simple to deal with, so are
917
case DBUS_TYPE_BOOLEAN:
918
if (PyObject_IsTrue(obj)) {
924
DBG("Performing actual append: bool(%ld)", (long)u.b);
925
if (!dbus_message_iter_append_basic(appender, sig_type, &u.b)) {
933
case DBUS_TYPE_DOUBLE:
934
u.d = PyFloat_AsDouble(obj);
935
if (PyErr_Occurred()) {
939
DBG("Performing actual append: double(%f)", u.d);
940
if (!dbus_message_iter_append_basic(appender, sig_type, &u.d)) {
948
#ifdef WITH_DBUS_FLOAT32
949
case DBUS_TYPE_FLOAT:
950
u.d = PyFloat_AsDouble(obj);
951
if (PyErr_Occurred()) {
956
DBG("Performing actual append: float(%f)", u.f);
957
if (!dbus_message_iter_append_basic(appender, sig_type, &u.f)) {
966
/* The integer types are all basically the same - we delegate to
967
intNN_range_check() */
968
#define PROCESS_INTEGER(size) \
969
u.size = dbus_py_##size##_range_check(obj);\
970
if (u.size == (dbus_##size##_t)(-1) && PyErr_Occurred()) {\
974
DBG("Performing actual append: " #size "(%lld)", (long long)u.size); \
975
if (!dbus_message_iter_append_basic(appender, sig_type, &u.size)) {\
982
case DBUS_TYPE_INT16:
983
PROCESS_INTEGER(int16)
985
case DBUS_TYPE_UINT16:
986
PROCESS_INTEGER(uint16)
988
case DBUS_TYPE_INT32:
989
PROCESS_INTEGER(int32)
991
case DBUS_TYPE_UINT32:
992
PROCESS_INTEGER(uint32)
994
#if defined(DBUS_HAVE_INT64) && defined(HAVE_LONG_LONG)
995
case DBUS_TYPE_INT64:
996
PROCESS_INTEGER(int64)
998
case DBUS_TYPE_UINT64:
999
PROCESS_INTEGER(uint64)
1002
case DBUS_TYPE_INT64:
1003
case DBUS_TYPE_UINT64:
1004
PyErr_SetString(PyExc_NotImplementedError, "64-bit integer "
1005
"types are not supported on this platform");
1009
#undef PROCESS_INTEGER
1011
/* Now the more complicated cases, which are delegated to helper
1012
* functions (although in practice, the compiler will hopefully
1013
* inline them anyway). */
1015
case DBUS_TYPE_STRING:
1016
case DBUS_TYPE_SIGNATURE:
1017
case DBUS_TYPE_OBJECT_PATH:
1018
ret = _message_iter_append_string(appender, sig_type, obj, TRUE);
1021
case DBUS_TYPE_BYTE:
1022
ret = _message_iter_append_byte(appender, obj);
1025
case DBUS_TYPE_ARRAY:
1026
/* 3 cases - it might actually be a dict, or it might be a byte array
1027
* being copied from a string (for which we have a faster path),
1028
* or it might be a generic array. */
1030
sig_type = dbus_signature_iter_get_element_type(sig_iter);
1031
if (sig_type == DBUS_TYPE_DICT_ENTRY)
1032
ret = _message_iter_append_multi(appender, sig_iter,
1033
DBUS_TYPE_DICT_ENTRY, obj);
1034
else if (sig_type == DBUS_TYPE_BYTE && PyString_Check(obj))
1035
ret = _message_iter_append_string_as_byte_array(appender, obj);
1037
ret = _message_iter_append_multi(appender, sig_iter,
1038
DBUS_TYPE_ARRAY, obj);
1039
DBG("_message_iter_append_multi(): %d", ret);
1042
case DBUS_TYPE_STRUCT:
1043
ret = _message_iter_append_multi(appender, sig_iter, sig_type, obj);
1046
case DBUS_TYPE_VARIANT:
1047
ret = _message_iter_append_variant(appender, obj);
1050
case DBUS_TYPE_INVALID:
1051
PyErr_SetString(PyExc_TypeError, "Fewer items found in D-Bus "
1052
"signature than in Python arguments");
1056
#if defined(DBUS_TYPE_UNIX_FD)
1057
case DBUS_TYPE_UNIX_FD:
1058
ret = _message_iter_append_unixfd(appender, obj);
1063
PyErr_Format(PyExc_TypeError, "Unknown type '\\x%x' in D-Bus "
1064
"signature", sig_type);
1068
if (ret < 0) return -1;
1070
DBG("Advancing signature iter at %p", sig_iter);
1071
*more = dbus_signature_iter_next(sig_iter);
1073
DBG("- result: %ld, type %02x '%c'", (long)(*more),
1074
(int)dbus_signature_iter_get_current_type(sig_iter),
1075
(int)dbus_signature_iter_get_current_type(sig_iter));
1082
dbus_py_Message_append(Message *self, PyObject *args, PyObject *kwargs)
1084
const char *signature = NULL;
1085
PyObject *signature_obj = NULL;
1086
DBusSignatureIter sig_iter;
1087
DBusMessageIter appender;
1088
static char *argnames[] = {"signature", NULL};
1091
if (!self->msg) return DBusPy_RaiseUnusableMessage();
1094
fprintf(stderr, "DBG/%ld: called Message_append(*", (long)getpid());
1095
PyObject_Print(args, stderr, 0);
1097
fprintf(stderr, ", **");
1098
PyObject_Print(kwargs, stderr, 0);
1100
fprintf(stderr, ")\n");
1103
/* only use kwargs for this step: deliberately ignore args for now */
1104
if (!PyArg_ParseTupleAndKeywords(dbus_py_empty_tuple, kwargs, "|z:append",
1105
argnames, &signature)) return NULL;
1108
DBG("%s", "No signature for message, guessing...");
1109
signature_obj = dbus_py_Message_guess_signature(NULL, args);
1110
if (!signature_obj) return NULL;
1111
signature = PyString_AS_STRING(signature_obj);
1113
/* from here onwards, you have to do a goto rather than returning NULL
1114
to make sure signature_obj gets freed */
1116
/* iterate over args and the signature, together */
1117
if (!dbus_signature_validate(signature, NULL)) {
1118
PyErr_SetString(PyExc_ValueError, "Corrupt type signature");
1121
dbus_message_iter_init_append(self->msg, &appender);
1123
if (signature[0] != '\0') {
1127
dbus_signature_iter_init(&sig_iter, signature);
1129
if (i >= PyTuple_GET_SIZE(args)) {
1130
PyErr_SetString(PyExc_TypeError, "More items found in D-Bus "
1131
"signature than in Python arguments");
1134
if (_message_iter_append_pyobject(&appender, &sig_iter,
1135
PyTuple_GET_ITEM(args, i),
1141
if (i < PyTuple_GET_SIZE(args)) {
1142
PyErr_SetString(PyExc_TypeError, "Fewer items found in D-Bus "
1143
"signature than in Python arguments");
1149
Py_CLEAR(signature_obj);
1153
/* "If appending any of the arguments fails due to lack of memory,
1154
* generally the message is hosed and you have to start over" -libdbus docs
1155
* Enforce this by throwing away the message structure.
1157
dbus_message_unref(self->msg);
1160
Py_CLEAR(signature_obj);
1164
/* vim:set ft=c cino< sw=4 sts=4 et: */