1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-basic.c Marshalling routines for basic (primitive) types
4 * Copyright (C) 2002 CodeFactory AB
5 * Copyright (C) 2003, 2004 Red Hat, Inc.
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "dbus-internals.h"
26 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
27 #include "dbus-string-private.h"
29 #include "dbus-marshal-basic.h"
34 * @defgroup DBusMarshal marshaling and unmarshaling
35 * @ingroup DBusInternals
36 * @brief functions to marshal/unmarshal data from the wire
38 * Types and functions related to converting primitive data types from
39 * wire format to native machine format, and vice versa.
41 * A signature is just a string with multiple types one after the other.
42 * for example a type is "i" or "(ii)", a signature is "i(ii)"
43 * where i is int and (ii) is struct { int; int; }
49 unpack_4_octets (int byte_order,
50 const unsigned char *data)
52 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
54 if (byte_order == DBUS_LITTLE_ENDIAN)
55 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
57 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
60 #ifndef DBUS_HAVE_INT64
63 swap_bytes (unsigned char *data,
66 unsigned char *p1 = data;
67 unsigned char *p2 = data + len - 1;
71 unsigned char tmp = *p1;
79 #endif /* !DBUS_HAVE_INT64 */
82 * Union used to manipulate 8 bytes as if they
87 #ifdef DBUS_HAVE_INT64
88 dbus_int64_t s; /**< 64-bit integer */
89 dbus_uint64_t u; /**< 64-bit unsigned integer */
91 double d; /**< double */
95 unpack_8_octets (int byte_order,
96 const unsigned char *data)
100 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
101 _dbus_assert (sizeof (r) == 8);
103 #ifdef DBUS_HAVE_INT64
104 if (byte_order == DBUS_LITTLE_ENDIAN)
105 r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
107 r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
109 r.d = *(double*)data;
110 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
111 swap_bytes ((unsigned char*) &r, sizeof (r));
118 * Unpacks a 32 bit unsigned integer from a data pointer
120 * @param byte_order The byte order to use
121 * @param data the data pointer
122 * @returns the integer
125 _dbus_unpack_uint32 (int byte_order,
126 const unsigned char *data)
128 return unpack_4_octets (byte_order, data);
132 * Unpacks a 32 bit signed integer from a data pointer
134 * @param byte_order The byte order to use
135 * @param data the data pointer
136 * @returns the integer
139 _dbus_unpack_int32 (int byte_order,
140 const unsigned char *data)
142 return (dbus_int32_t) unpack_4_octets (byte_order, data);
145 #ifdef DBUS_HAVE_INT64
147 * Unpacks a 64 bit unsigned integer from a data pointer
149 * @param byte_order The byte order to use
150 * @param data the data pointer
151 * @returns the integer
154 _dbus_unpack_uint64 (int byte_order,
155 const unsigned char *data)
159 r = unpack_8_octets (byte_order, data);
165 * Unpacks a 64 bit signed integer from a data pointer
167 * @param byte_order The byte order to use
168 * @param data the data pointer
169 * @returns the integer
172 _dbus_unpack_int64 (int byte_order,
173 const unsigned char *data)
177 r = unpack_8_octets (byte_order, data);
182 #endif /* DBUS_HAVE_INT64 */
185 pack_4_octets (dbus_uint32_t value,
189 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
191 if ((byte_order) == DBUS_LITTLE_ENDIAN)
192 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
194 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
198 pack_8_octets (DBusOctets8 value,
202 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
204 #ifdef DBUS_HAVE_INT64
205 if ((byte_order) == DBUS_LITTLE_ENDIAN)
206 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u);
208 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
210 memcpy (data, &value, 8);
211 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
212 swap_bytes ((unsigned char *)data, 8);
217 * Packs a 32 bit unsigned integer into a data pointer.
219 * @param value the value
220 * @param byte_order the byte order to use
221 * @param data the data pointer
224 _dbus_pack_uint32 (dbus_uint32_t value,
228 pack_4_octets (value, byte_order, data);
232 * Packs a 32 bit signed integer into a data pointer.
234 * @param value the value
235 * @param byte_order the byte order to use
236 * @param data the data pointer
239 _dbus_pack_int32 (dbus_int32_t value,
243 pack_4_octets ((dbus_uint32_t) value, byte_order, data);
246 #ifdef DBUS_HAVE_INT64
248 * Packs a 64 bit unsigned integer into a data pointer.
250 * @param value the value
251 * @param byte_order the byte order to use
252 * @param data the data pointer
255 _dbus_pack_uint64 (dbus_uint64_t value,
261 pack_8_octets (r, byte_order, data);
265 * Packs a 64 bit signed integer into a data pointer.
267 * @param value the value
268 * @param byte_order the byte order to use
269 * @param data the data pointer
272 _dbus_pack_int64 (dbus_int64_t value,
278 pack_8_octets (r, byte_order, data);
280 #endif /* DBUS_HAVE_INT64 */
283 set_4_octets (DBusString *str,
290 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
291 byte_order == DBUS_BIG_ENDIAN);
293 data = _dbus_string_get_data_len (str, offset, 4);
295 _dbus_pack_uint32 (value, byte_order, data);
299 set_8_octets (DBusString *str,
306 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
307 byte_order == DBUS_BIG_ENDIAN);
309 data = _dbus_string_get_data_len (str, offset, 8);
311 pack_8_octets (value, byte_order, data);
315 * Sets the 4 bytes at the given offset to a marshaled signed integer,
316 * replacing anything found there previously.
318 * @param str the string to write the marshalled int to
319 * @param offset the byte offset where int should be written
320 * @param byte_order the byte order to use
321 * @param value the value
325 _dbus_marshal_set_int32 (DBusString *str,
330 set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
334 * Sets the 4 bytes at the given offset to a marshaled unsigned
335 * integer, replacing anything found there previously.
337 * @param str the string to write the marshalled int to
338 * @param offset the byte offset where int should be written
339 * @param byte_order the byte order to use
340 * @param value the value
344 _dbus_marshal_set_uint32 (DBusString *str,
349 set_4_octets (str, byte_order, offset, value);
352 #ifdef DBUS_HAVE_INT64
355 * Sets the 8 bytes at the given offset to a marshaled signed integer,
356 * replacing anything found there previously.
358 * @param str the string to write the marshalled int to
359 * @param offset the byte offset where int should be written
360 * @param byte_order the byte order to use
361 * @param value the value
365 _dbus_marshal_set_int64 (DBusString *str,
372 set_8_octets (str, byte_order, offset, r);
376 * Sets the 8 bytes at the given offset to a marshaled unsigned
377 * integer, replacing anything found there previously.
379 * @param str the string to write the marshalled int to
380 * @param offset the byte offset where int should be written
381 * @param byte_order the byte order to use
382 * @param value the value
386 _dbus_marshal_set_uint64 (DBusString *str,
393 set_8_octets (str, byte_order, offset, r);
395 #endif /* DBUS_HAVE_INT64 */
398 * Sets the existing marshaled string at the given offset with
399 * a new marshaled string. The given offset must point to
400 * an existing string or the wrong length will be deleted
401 * and replaced with the new string.
403 * Note: no attempt is made by this function to re-align
404 * any data which has been already marshalled after this
405 * string. Use with caution.
407 * @param str the string to write the marshalled string to
408 * @param offset the byte offset where string should be written
409 * @param byte_order the byte order to use
410 * @param value the value
411 * @param len the length to use
412 * @returns #TRUE on success
416 _dbus_marshal_set_string (DBusString *str,
419 const DBusString *value,
424 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
425 byte_order == DBUS_BIG_ENDIAN);
427 old_len = _dbus_demarshal_uint32 (str, byte_order,
430 if (!_dbus_string_replace_len (value, 0, len,
431 str, offset + 4, old_len))
434 _dbus_marshal_set_uint32 (str, byte_order,
441 * Sets the existing marshaled object path at the given offset to a new
442 * value. The given offset must point to an existing object path or this
443 * function doesn't make sense.
445 * @todo implement this function
447 * @param str the string to write the marshalled path to
448 * @param offset the byte offset where path should be written
449 * @param byte_order the byte order to use
450 * @param path the new path
451 * @param path_len number of elements in the path
454 _dbus_marshal_set_object_path (DBusString *str,
465 marshal_4_octets (DBusString *str,
470 _dbus_assert (sizeof (value) == 4);
472 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
473 value = DBUS_UINT32_SWAP_LE_BE (value);
475 return _dbus_string_insert_4_aligned (str, insert_at,
476 (const unsigned char *)&value);
480 marshal_8_octets (DBusString *str,
485 _dbus_assert (sizeof (value) == 8);
487 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
488 pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
490 return _dbus_string_insert_8_aligned (str, insert_at,
491 (const unsigned char *)&value);
495 * Marshals a double value.
497 * @param str the string to append the marshalled value to
498 * @param byte_order the byte order to use
499 * @param value the value
500 * @returns #TRUE on success
503 _dbus_marshal_double (DBusString *str,
509 return marshal_8_octets (str, _dbus_string_get_length (str),
514 * Marshals a 32 bit signed integer value.
516 * @param str the string to append the marshalled value to
517 * @param byte_order the byte order to use
518 * @param value the value
519 * @returns #TRUE on success
522 _dbus_marshal_int32 (DBusString *str,
526 return marshal_4_octets (str, _dbus_string_get_length (str),
527 byte_order, (dbus_uint32_t) value);
531 * Marshals a 32 bit unsigned integer value.
533 * @param str the string to append the marshalled value to
534 * @param byte_order the byte order to use
535 * @param value the value
536 * @returns #TRUE on success
539 _dbus_marshal_uint32 (DBusString *str,
543 return marshal_4_octets (str, _dbus_string_get_length (str),
548 #ifdef DBUS_HAVE_INT64
550 * Marshals a 64 bit signed integer value.
552 * @param str the string to append the marshalled value to
553 * @param byte_order the byte order to use
554 * @param value the value
555 * @returns #TRUE on success
558 _dbus_marshal_int64 (DBusString *str,
564 return marshal_8_octets (str, _dbus_string_get_length (str),
569 * Marshals a 64 bit unsigned integer value.
571 * @param str the string to append the marshalled value to
572 * @param byte_order the byte order to use
573 * @param value the value
574 * @returns #TRUE on success
577 _dbus_marshal_uint64 (DBusString *str,
583 return marshal_8_octets (str, _dbus_string_get_length (str),
587 #endif /* DBUS_HAVE_INT64 */
590 * Marshals a UTF-8 string
592 * @todo: If the string append fails we need to restore
593 * the old length. (also for other marshallers)
595 * @param str the string to append the marshalled value to
596 * @param byte_order the byte order to use
597 * @param value the string
598 * @returns #TRUE on success
601 _dbus_marshal_string (DBusString *str,
605 int len, old_string_len;
607 old_string_len = _dbus_string_get_length (str);
609 len = strlen (value);
611 if (!_dbus_marshal_uint32 (str, byte_order, len))
613 /* Restore the previous length */
614 _dbus_string_set_length (str, old_string_len);
619 return _dbus_string_append_len (str, value, len + 1);
623 * Marshals a UTF-8 string
625 * @todo: If the string append fails we need to restore
626 * the old length. (also for other marshallers)
628 * @param str the string to append the marshalled value to
629 * @param byte_order the byte order to use
630 * @param value the string
631 * @param len length of string to marshal in bytes
632 * @returns #TRUE on success
635 _dbus_marshal_string_len (DBusString *str,
642 old_string_len = _dbus_string_get_length (str);
644 if (!_dbus_marshal_uint32 (str, byte_order, len))
646 /* Restore the previous length */
647 _dbus_string_set_length (str, old_string_len);
652 if (!_dbus_string_append_len (str, value, len))
656 if (!_dbus_string_lengthen (str, 1))
663 * Marshals a byte array
665 * @param str the string to append the marshalled value to
666 * @param byte_order the byte order to use
667 * @param value the array
668 * @param len number of elements in the array
669 * @returns #TRUE on success
672 _dbus_marshal_byte_array (DBusString *str,
674 const unsigned char *value,
679 old_string_len = _dbus_string_get_length (str);
681 if (!_dbus_marshal_uint32 (str, byte_order, len))
683 /* Restore the previous length */
684 _dbus_string_set_length (str, old_string_len);
692 return _dbus_string_append_len (str, value, len);
696 marshal_4_octets_array (DBusString *str,
698 const dbus_uint32_t *value,
704 old_string_len = _dbus_string_get_length (str);
706 if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
709 array_start = _dbus_string_get_length (str);
711 if (!_dbus_string_append_len (str, (const unsigned char*) value,
715 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
717 const unsigned char *d;
718 const unsigned char *end;
720 d = _dbus_string_get_data (str) + array_start;
724 *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
732 /* Restore previous length */
733 _dbus_string_set_length (str, old_string_len);
739 marshal_8_octets_array (DBusString *str,
741 const DBusOctets8 *value,
747 old_string_len = _dbus_string_get_length (str);
749 /* The array length is the length in bytes of the array,
750 * *excluding* alignment padding.
752 if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
755 array_start = _dbus_string_get_length (str);
757 /* Note that we do alignment padding unconditionally
758 * even if the array is empty; this means that
759 * padding + len is always equal to the number of bytes
763 if (!_dbus_string_align_length (str, 8))
766 if (!_dbus_string_append_len (str, (const unsigned char*) value,
770 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
772 const unsigned char *d;
773 const unsigned char *end;
775 d = _dbus_string_get_data (str) + array_start;
779 #ifdef DBUS_HAVE_INT64
780 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
782 swap_bytes ((unsigned char*) d, 8);
791 /* Restore previous length */
792 _dbus_string_set_length (str, old_string_len);
798 * Marshals a 32 bit signed integer array
800 * @param str the string to append the marshalled value to
801 * @param byte_order the byte order to use
802 * @param value the array
803 * @param len the length of the array
804 * @returns #TRUE on success
807 _dbus_marshal_int32_array (DBusString *str,
809 const dbus_int32_t *value,
812 return marshal_4_octets_array (str, byte_order,
813 (const dbus_uint32_t*) value,
818 * Marshals a 32 bit unsigned integer array
820 * @param str the string to append the marshalled value to
821 * @param byte_order the byte order to use
822 * @param value the array
823 * @param len the length of the array
824 * @returns #TRUE on success
827 _dbus_marshal_uint32_array (DBusString *str,
829 const dbus_uint32_t *value,
832 return marshal_4_octets_array (str, byte_order,
837 #ifdef DBUS_HAVE_INT64
840 * Marshals a 64 bit signed integer array
842 * @param str the string to append the marshalled value to
843 * @param byte_order the byte order to use
844 * @param value the array
845 * @param len the length of the array
846 * @returns #TRUE on success
849 _dbus_marshal_int64_array (DBusString *str,
851 const dbus_int64_t *value,
854 return marshal_8_octets_array (str, byte_order,
855 (const DBusOctets8*) value,
860 * Marshals a 64 bit unsigned integer array
862 * @param str the string to append the marshalled value to
863 * @param byte_order the byte order to use
864 * @param value the array
865 * @param len the length of the array
866 * @returns #TRUE on success
869 _dbus_marshal_uint64_array (DBusString *str,
871 const dbus_uint64_t *value,
874 return marshal_8_octets_array (str, byte_order,
875 (const DBusOctets8*) value,
879 #endif /* DBUS_HAVE_INT64 */
882 * Marshals a double array
884 * @param str the string to append the marshalled value to
885 * @param byte_order the byte order to use
886 * @param value the array
887 * @param len the length of the array
888 * @returns #TRUE on success
891 _dbus_marshal_double_array (DBusString *str,
896 return marshal_8_octets_array (str, byte_order,
897 (const DBusOctets8*) value,
902 * Marshals a string array
904 * @param str the string to append the marshalled value to
905 * @param byte_order the byte order to use
906 * @param value the array
907 * @param len the length of the array
908 * @returns #TRUE on success
911 _dbus_marshal_string_array (DBusString *str,
916 int i, old_string_len, array_start;
918 old_string_len = _dbus_string_get_length (str);
920 /* Set the length to 0 temporarily */
921 if (!_dbus_marshal_uint32 (str, byte_order, 0))
924 array_start = _dbus_string_get_length (str);
926 for (i = 0; i < len; i++)
927 if (!_dbus_marshal_string (str, byte_order, value[i]))
930 /* Write the length now that we know it */
931 _dbus_marshal_set_uint32 (str, byte_order,
932 _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
933 _dbus_string_get_length (str) - array_start);
938 /* Restore previous length */
939 _dbus_string_set_length (str, old_string_len);
945 * Marshals an object path value.
947 * @param str the string to append the marshalled value to
948 * @param byte_order the byte order to use
949 * @param path the path
950 * @param path_len length of the path
951 * @returns #TRUE on success
954 _dbus_marshal_object_path (DBusString *str,
959 int array_start, old_string_len;
962 old_string_len = _dbus_string_get_length (str);
964 /* Set the length to 0 temporarily */
965 if (!_dbus_marshal_uint32 (str, byte_order, 0))
968 array_start = _dbus_string_get_length (str);
973 if (!_dbus_string_append_byte (str, '/'))
976 if (!_dbus_string_append (str, path[0]))
982 /* Write the length now that we know it */
983 _dbus_marshal_set_uint32 (str, byte_order,
984 _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
985 _dbus_string_get_length (str) - array_start);
990 /* Restore the previous length */
991 _dbus_string_set_length (str, old_string_len);
997 demarshal_4_octets (const DBusString *str,
1002 const DBusRealString *real = (const DBusRealString*) str;
1004 pos = _DBUS_ALIGN_VALUE (pos, 4);
1009 return unpack_4_octets (byte_order, real->str + pos);
1013 demarshal_8_octets (const DBusString *str,
1018 const DBusRealString *real = (const DBusRealString*) str;
1020 pos = _DBUS_ALIGN_VALUE (pos, 8);
1025 return unpack_8_octets (byte_order, real->str + pos);
1029 * Demarshals a double.
1031 * @param str the string containing the data
1032 * @param byte_order the byte order
1033 * @param pos the position in the string
1034 * @param new_pos the new position of the string
1035 * @returns the demarshaled double.
1038 _dbus_demarshal_double (const DBusString *str,
1045 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1051 * Demarshals a 32 bit signed integer.
1053 * @param str the string containing the data
1054 * @param byte_order the byte order
1055 * @param pos the position in the string
1056 * @param new_pos the new position of the string
1057 * @returns the demarshaled integer.
1060 _dbus_demarshal_int32 (const DBusString *str,
1065 return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
1069 * Demarshals a 32 bit unsigned integer.
1071 * @param str the string containing the data
1072 * @param byte_order the byte order
1073 * @param pos the position in the string
1074 * @param new_pos the new position of the string
1075 * @returns the demarshaled integer.
1078 _dbus_demarshal_uint32 (const DBusString *str,
1083 return demarshal_4_octets (str, byte_order, pos, new_pos);
1086 #ifdef DBUS_HAVE_INT64
1089 * Demarshals a 64 bit signed integer.
1091 * @param str the string containing the data
1092 * @param byte_order the byte order
1093 * @param pos the position in the string
1094 * @param new_pos the new position of the string
1095 * @returns the demarshaled integer.
1098 _dbus_demarshal_int64 (const DBusString *str,
1105 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1111 * Demarshals a 64 bit unsigned integer.
1113 * @param str the string containing the data
1114 * @param byte_order the byte order
1115 * @param pos the position in the string
1116 * @param new_pos the new position of the string
1117 * @returns the demarshaled integer.
1120 _dbus_demarshal_uint64 (const DBusString *str,
1127 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1132 #endif /* DBUS_HAVE_INT64 */
1135 * Demarshals a basic type
1137 * @param str the string containing the data
1138 * @param type type of value to demarshal
1139 * @param value pointer to return value data
1140 * @param byte_order the byte order
1141 * @param pos pointer to position in the string,
1142 * updated on return to new position
1145 _dbus_demarshal_basic_type (const DBusString *str,
1151 const char *str_data = _dbus_string_get_const_data (str);
1155 case DBUS_TYPE_BYTE:
1156 case DBUS_TYPE_BOOLEAN:
1157 *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
1160 case DBUS_TYPE_INT32:
1161 case DBUS_TYPE_UINT32:
1162 *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1163 *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
1164 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1165 *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
1168 #ifdef DBUS_HAVE_INT64
1169 case DBUS_TYPE_INT64:
1170 case DBUS_TYPE_UINT64:
1171 #endif /* DBUS_HAVE_INT64 */
1172 case DBUS_TYPE_DOUBLE:
1173 *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1174 memcpy (value, str_data + *pos, 8);
1175 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1176 #ifdef DBUS_HAVE_INT64
1177 *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
1179 swap_bytes (value, 8);
1183 case DBUS_TYPE_STRING:
1184 _dbus_assert_not_reached ("FIXME string is a basic type");
1186 case DBUS_TYPE_OBJECT_PATH:
1187 _dbus_assert_not_reached ("FIXME object path is a basic type");
1190 _dbus_verbose ("type %s not a basic type\n",
1191 _dbus_type_to_string (type));
1192 _dbus_assert_not_reached ("not a basic type");
1198 * Demarshals an UTF-8 string.
1200 * @todo Should we check the string to make sure
1201 * that it's valid UTF-8, and maybe "fix" the string
1204 * @todo Should probably demarshal to a DBusString,
1205 * having memcpy() in here is Evil(tm).
1207 * @param str the string containing the data
1208 * @param byte_order the byte order
1209 * @param pos the position in the string
1210 * @param new_pos the new position of the string
1211 * @returns the demarshaled string.
1214 _dbus_demarshal_string (const DBusString *str,
1223 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1225 retval = dbus_malloc (len + 1);
1230 data = _dbus_string_get_const_data_len (str, pos, len + 1);
1235 memcpy (retval, data, len + 1);
1238 *new_pos = pos + len + 1;
1244 * Demarshals a byte array.
1246 * @todo Should probably demarshal to a DBusString,
1247 * having memcpy() in here is Evil(tm).
1249 * @param str the string containing the data
1250 * @param byte_order the byte order
1251 * @param pos the position in the string
1252 * @param new_pos the new position of the string
1253 * @param array the array
1254 * @param array_len length of the demarshaled data
1256 * @returns #TRUE on success
1259 _dbus_demarshal_byte_array (const DBusString *str,
1263 unsigned char **array,
1267 unsigned char *retval;
1270 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1283 retval = dbus_malloc (len);
1288 data = _dbus_string_get_const_data_len (str, pos, len);
1296 memcpy (retval, data, len);
1299 *new_pos = pos + len;
1308 demarshal_4_octets_array (const DBusString *str,
1312 dbus_uint32_t **array,
1316 dbus_uint32_t *retval;
1319 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1333 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1337 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1339 for (i = 0; i < len; i++)
1340 retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1344 *new_pos = pos + byte_len;
1353 demarshal_8_octets_array (const DBusString *str,
1357 DBusOctets8 **array,
1361 DBusOctets8 *retval;
1364 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1366 pos = _DBUS_ALIGN_VALUE (pos, 8);
1381 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1385 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1387 for (i = 0; i < len; i++)
1389 #ifdef DBUS_HAVE_INT64
1390 retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1392 swap_bytes ((unsigned char *) &retval[i], 8);
1398 *new_pos = pos + byte_len;
1407 * Demarshals a 32 bit signed integer array.
1409 * @param str the string containing the data
1410 * @param byte_order the byte order
1411 * @param pos the position in the string
1412 * @param new_pos the new position of the string
1413 * @param array the array
1414 * @param array_len length of the demarshaled data
1415 * @returns #TRUE on success
1418 _dbus_demarshal_int32_array (const DBusString *str,
1422 dbus_int32_t **array,
1425 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1426 (dbus_uint32_t**) array, array_len);
1430 * Demarshals a 32 bit unsigned integer array.
1432 * @param str the string containing the data
1433 * @param byte_order the byte order
1434 * @param pos the position in the string
1435 * @param new_pos the new position of the string
1436 * @param array the array
1437 * @param array_len length of the demarshaled data
1438 * @returns #TRUE on success
1441 _dbus_demarshal_uint32_array (const DBusString *str,
1445 dbus_uint32_t **array,
1448 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1452 #ifdef DBUS_HAVE_INT64
1455 * Demarshals a 64 bit signed integer array.
1457 * @param str the string containing the data
1458 * @param byte_order the byte order
1459 * @param pos the position in the string
1460 * @param new_pos the new position of the string
1461 * @param array the array
1462 * @param array_len length of the demarshaled data
1463 * @returns #TRUE on success
1466 _dbus_demarshal_int64_array (const DBusString *str,
1470 dbus_int64_t **array,
1473 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1474 (DBusOctets8**) array, array_len);
1478 * Demarshals a 64 bit unsigned integer array.
1480 * @param str the string containing the data
1481 * @param byte_order the byte order
1482 * @param pos the position in the string
1483 * @param new_pos the new position of the string
1484 * @param array the array
1485 * @param array_len length of the demarshaled data
1486 * @returns #TRUE on success
1489 _dbus_demarshal_uint64_array (const DBusString *str,
1493 dbus_uint64_t **array,
1496 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1497 (DBusOctets8**) array, array_len);
1500 #endif /* DBUS_HAVE_INT64 */
1503 * Demarshals a double array.
1505 * @param str the string containing the data
1506 * @param byte_order the byte order
1507 * @param pos the position in the string
1508 * @param new_pos the new position of the string
1509 * @param array the array
1510 * @param array_len length of the demarshaled data
1511 * @returns #TRUE on success
1514 _dbus_demarshal_double_array (const DBusString *str,
1521 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1522 (DBusOctets8**) array, array_len);
1527 * Demarshals an array of basic types
1529 * @param str the string containing the data
1530 * @param element_type type of array elements to demarshal
1531 * @param array pointer to pointer to array data
1532 * @param array_len pointer to array length
1533 * @param byte_order the byte order
1534 * @param pos pointer to position in the string,
1535 * updated on return to new position
1538 _dbus_demarshal_basic_type_array (const DBusString *str,
1545 switch (element_type)
1547 case DBUS_TYPE_BOOLEAN:
1548 /* FIXME: do we want to post-normalize these ? */
1549 case DBUS_TYPE_BYTE:
1550 return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
1551 (unsigned char **)array, array_len);
1553 case DBUS_TYPE_INT32:
1554 case DBUS_TYPE_UINT32:
1555 return demarshal_4_octets_array (str, byte_order, *pos, pos,
1556 (dbus_uint32_t **)array, array_len);
1558 #ifdef DBUS_HAVE_INT64
1559 case DBUS_TYPE_INT64:
1560 case DBUS_TYPE_UINT64:
1561 #endif /* DBUS_HAVE_INT64 */
1562 case DBUS_TYPE_DOUBLE:
1563 return demarshal_8_octets_array (str, byte_order, *pos, pos,
1564 (DBusOctets8**) array, array_len);
1566 _dbus_assert_not_reached ("not a basic type");
1573 * Demarshals a string array.
1575 * @param str the string containing the data
1576 * @param byte_order the byte order
1577 * @param pos the position in the string
1578 * @param new_pos the new position of the string
1579 * @param array the array
1580 * @param array_len location for length of the demarshaled data or NULL
1581 * @returns #TRUE on success
1584 _dbus_demarshal_string_array (const DBusString *str,
1596 bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1611 end_pos = pos + bytes_len;
1613 retval = dbus_new (char *, allocated);
1618 while (pos < end_pos)
1620 retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1622 if (retval[len] == NULL)
1627 if (len >= allocated - 1) /* -1 for NULL termination */
1630 newp = dbus_realloc (retval,
1631 sizeof (char*) * allocated * 2);
1651 for (i = 0; i < len; i++)
1652 dbus_free (retval[i]);
1658 /** Set to 1 to get a bunch of spew about disassembling the path string */
1659 #define VERBOSE_DECOMPOSE 0
1662 * Decompose an object path. A path of just "/" is
1663 * represented as an empty vector of strings.
1665 * @param data the path data
1666 * @param len the length of the path string
1667 * @param path address to store new object path
1668 * @param path_len length of stored path
1671 _dbus_decompose_path (const char* data,
1680 _dbus_assert (data != NULL);
1682 #if VERBOSE_DECOMPOSE
1683 _dbus_verbose ("Decomposing path \"%s\"\n",
1696 retval = dbus_new0 (char*, n_components + 1);
1709 while (j < len && data[j] != '/')
1712 /* Now [i, j) is the path component */
1713 _dbus_assert (i < j);
1714 _dbus_assert (data[i] != '/');
1715 _dbus_assert (j == len || data[j] == '/');
1717 #if VERBOSE_DECOMPOSE
1718 _dbus_verbose (" (component in [%d,%d))\n",
1722 retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1723 if (retval[comp] == NULL)
1725 dbus_free_string_array (retval);
1728 retval[comp][j-i] = '\0';
1729 #if VERBOSE_DECOMPOSE
1730 _dbus_verbose (" (component %d = \"%s\")\n",
1731 comp, retval[comp]);
1737 _dbus_assert (i == len);
1741 *path_len = n_components;
1747 * Demarshals an object path. A path of just "/" is
1748 * represented as an empty vector of strings.
1750 * @param str the string containing the data
1751 * @param byte_order the byte order
1752 * @param pos the position in the string
1753 * @param new_pos the new position of the string
1754 * @param path address to store new object path
1755 * @param path_len length of stored path
1758 _dbus_demarshal_object_path (const DBusString *str,
1768 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1769 data = _dbus_string_get_const_data_len (str, pos, len + 1);
1771 if (!_dbus_decompose_path (data, len, path, path_len))
1775 *new_pos = pos + len + 1;
1781 * Skips over a basic type, reporting the following position.
1783 * @param str the string containing the data
1784 * @param type type of value to demarshal
1785 * @param byte_order the byte order
1786 * @param pos pointer to position in the string,
1787 * updated on return to new position
1790 _dbus_marshal_skip_basic_type (const DBusString *str,
1797 case DBUS_TYPE_BYTE:
1798 case DBUS_TYPE_BOOLEAN:
1801 case DBUS_TYPE_INT32:
1802 case DBUS_TYPE_UINT32:
1803 *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1806 #ifdef DBUS_HAVE_INT64
1807 case DBUS_TYPE_INT64:
1808 case DBUS_TYPE_UINT64:
1809 #endif /* DBUS_HAVE_INT64 */
1810 case DBUS_TYPE_DOUBLE:
1811 *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1814 case DBUS_TYPE_STRING:
1815 _dbus_assert_not_reached ("FIXME string is a basic type");
1817 case DBUS_TYPE_OBJECT_PATH:
1818 _dbus_assert_not_reached ("FIXME object path is a basic type");
1821 _dbus_verbose ("type %s not a basic type\n",
1822 _dbus_type_to_string (type));
1823 _dbus_assert_not_reached ("not a basic type");
1829 * Skips an array, returning the next position.
1831 * @param str the string containing the data
1832 * @param byte_order the byte order
1833 * @param pos pointer to position in the string,
1834 * updated on return to new position
1837 _dbus_marshal_skip_array (const DBusString *str,
1843 len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos);
1845 /* FIXME we need to insert alignment padding according to array type */
1851 * Returns the position right after the end of an argument. PERFORMS
1852 * NO VALIDATION WHATSOEVER. The message must have been previously
1855 * @param str a string
1856 * @param byte_order the byte order to use
1857 * @param type the type of the argument
1858 * @param pos the pos where the arg starts
1859 * @param end_pos pointer where the position right
1860 * after the end position will follow
1861 * @returns TRUE if more data exists after the arg
1864 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1870 if (pos >= _dbus_string_get_length (str))
1875 case DBUS_TYPE_INVALID:
1879 case DBUS_TYPE_BYTE:
1883 case DBUS_TYPE_BOOLEAN:
1887 case DBUS_TYPE_INT32:
1888 case DBUS_TYPE_UINT32:
1889 *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1892 case DBUS_TYPE_INT64:
1893 case DBUS_TYPE_UINT64:
1894 case DBUS_TYPE_DOUBLE:
1896 *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1899 case DBUS_TYPE_OBJECT_PATH:
1900 case DBUS_TYPE_STRING:
1904 /* Demarshal the length */
1905 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1907 *end_pos = pos + len + 1;
1911 case DBUS_TYPE_ARRAY:
1915 /* Demarshal the length */
1916 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1918 /* FIXME needs to align to the right boundary for the array type */
1919 *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + len;
1923 case DBUS_TYPE_DICT:
1927 /* Demarshal the length */
1928 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1930 *end_pos = pos + len;
1935 _dbus_warn ("Unknown message arg type %d\n", type);
1936 _dbus_assert_not_reached ("Unknown message argument type\n");
1940 if (*end_pos > _dbus_string_get_length (str))
1947 * Demarshals and validates a length; returns < 0 if the validation
1948 * fails. The length is required to be small enough that
1949 * len*sizeof(double) will not overflow, and small enough to fit in a
1950 * signed integer. DOES NOT check whether the length points
1951 * beyond the end of the string, because it doesn't know the
1952 * size of array elements.
1954 * @param str the string
1955 * @param byte_order the byte order
1956 * @param pos the unaligned string position (snap to next aligned)
1957 * @param new_pos return location for new position.
1960 demarshal_and_validate_len (const DBusString *str,
1965 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1968 _dbus_assert (new_pos != NULL);
1970 if ((align_4 + 4) > _dbus_string_get_length (str))
1972 _dbus_verbose ("not enough room in message for array length\n");
1976 if (!_dbus_string_validate_nul (str, pos,
1979 _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
1983 len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1985 /* note that the len is the number of bytes, so we need it to be
1986 * at least SIZE_T_MAX, but make it smaller just to keep things
1987 * sane. We end up using ints for most sizes to avoid unsigned mess
1988 * so limit to maximum 32-bit signed int divided by at least 8, more
1989 * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1991 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1992 if (len > MAX_ARRAY_LENGTH)
1994 _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
1995 len, MAX_ARRAY_LENGTH, pos);
2003 validate_string (const DBusString *str,
2005 int len_without_nul,
2008 *end_pos = pos + len_without_nul + 1;
2010 if (*end_pos > _dbus_string_get_length (str))
2012 _dbus_verbose ("string length outside length of the message\n");
2016 if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
2018 _dbus_verbose ("string arg not nul-terminated\n");
2022 if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
2024 _dbus_verbose ("string is not valid UTF-8\n");
2032 * Validates and returns a typecode at a specific position
2035 * @param str a string
2036 * @param type the type of the argument
2037 * @param pos the pos where the typecode starts
2038 * @param end_pos pointer where the position right
2039 * after the end position will follow
2040 * @returns #TRUE if the type is valid.
2043 _dbus_marshal_validate_type (const DBusString *str,
2050 if (pos >= _dbus_string_get_length (str))
2053 data = _dbus_string_get_const_data_len (str, pos, 1);
2055 if (_dbus_type_is_valid (*data))
2058 if (end_pos != NULL)
2063 _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
2068 /* Faster validator for array data that doesn't call
2069 * validate_arg for each value
2072 validate_array_data (const DBusString *str,
2083 case DBUS_TYPE_INVALID:
2087 case DBUS_TYPE_OBJECT_PATH:
2088 case DBUS_TYPE_STRING:
2089 case DBUS_TYPE_ARRAY:
2090 case DBUS_TYPE_DICT:
2091 /* This clean recursion to validate_arg is what we
2092 * are doing logically for all types, but we don't
2093 * really want to call validate_arg for every byte
2094 * in a byte array, so the primitive types are
2099 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2100 type, array_type_pos, pos, &pos))
2105 case DBUS_TYPE_BYTE:
2109 case DBUS_TYPE_BOOLEAN:
2114 c = _dbus_string_get_byte (str, pos);
2116 if (!(c == 0 || c == 1))
2118 _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2126 case DBUS_TYPE_INT32:
2127 case DBUS_TYPE_UINT32:
2128 /* Call validate arg one time to check alignment padding
2131 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2132 type, array_type_pos, pos, &pos))
2134 pos = _DBUS_ALIGN_VALUE (end, 4);
2137 case DBUS_TYPE_INT64:
2138 case DBUS_TYPE_UINT64:
2139 case DBUS_TYPE_DOUBLE:
2140 /* Call validate arg one time to check alignment padding
2143 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2144 type, array_type_pos, pos, &pos))
2146 pos = _DBUS_ALIGN_VALUE (end, 8);
2150 _dbus_verbose ("Unknown message arg type %d\n", type);
2160 * Validates an argument of a specific type, checking that it
2161 * is well-formed, for example no ludicrous length fields, strings
2162 * are nul-terminated, etc.
2163 * Returns the end position of the argument in end_pos, and
2164 * returns #TRUE if a valid arg begins at "pos"
2166 * @todo security: need to audit this function.
2168 * @param str a string
2169 * @param byte_order the byte order to use
2170 * @param depth current recursion depth, to prevent excessive recursion
2171 * @param type the type of the argument
2172 * @param array_type_pos the position of the current array type, or
2173 * -1 if not in an array
2174 * @param pos the pos where the arg starts
2175 * @param end_pos pointer where the position right
2176 * after the end position will follow
2177 * @returns #TRUE if the arg is valid.
2180 _dbus_marshal_validate_arg (const DBusString *str,
2188 if (pos > _dbus_string_get_length (str))
2190 _dbus_verbose ("Validation went off the end of the message\n");
2194 #define MAX_VALIDATION_DEPTH 32
2196 if (depth > MAX_VALIDATION_DEPTH)
2198 _dbus_verbose ("Maximum recursion depth reached validating message\n");
2204 case DBUS_TYPE_INVALID:
2208 case DBUS_TYPE_BYTE:
2209 if (1 > _dbus_string_get_length (str) - pos)
2211 _dbus_verbose ("no room for byte value\n");
2218 case DBUS_TYPE_BOOLEAN:
2222 if (1 > _dbus_string_get_length (str) - pos)
2224 _dbus_verbose ("no room for boolean value\n");
2228 c = _dbus_string_get_byte (str, pos);
2230 if (!(c == 0 || c == 1))
2232 _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2240 case DBUS_TYPE_INT32:
2241 case DBUS_TYPE_UINT32:
2243 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
2245 if (!_dbus_string_validate_nul (str, pos,
2248 _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2252 *end_pos = align_4 + 4;
2256 case DBUS_TYPE_INT64:
2257 case DBUS_TYPE_UINT64:
2258 case DBUS_TYPE_DOUBLE:
2260 int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2262 _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2264 if (!_dbus_string_validate_nul (str, pos,
2267 _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
2271 *end_pos = align_8 + 8;
2275 case DBUS_TYPE_OBJECT_PATH:
2276 case DBUS_TYPE_STRING:
2280 /* Demarshal the length, which does NOT include
2283 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2287 if (!validate_string (str, pos, len, end_pos))
2290 if (type == DBUS_TYPE_OBJECT_PATH)
2292 if (!_dbus_string_validate_path (str, pos, len))
2298 case DBUS_TYPE_ARRAY:
2304 if (array_type_pos == -1)
2306 array_type_pos = pos;
2310 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2312 _dbus_verbose ("invalid array type\n");
2316 while (array_type == DBUS_TYPE_ARRAY);
2321 if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2323 _dbus_verbose ("invalid array type\n");
2327 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2330 _dbus_verbose ("invalid array length (<0)\n");
2334 if (len > _dbus_string_get_length (str) - pos)
2336 _dbus_verbose ("array length outside length of the message\n");
2342 if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
2343 array_type, array_type_pos,
2346 _dbus_verbose ("invalid array data\n");
2352 /* This should not be able to happen, as long as validate_arg moves forward;
2353 * but the check is here just to be paranoid.
2355 _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2362 _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2370 case DBUS_TYPE_DICT:
2376 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2380 if (len > _dbus_string_get_length (str) - pos)
2382 _dbus_verbose ("dict length outside length of the message\n");
2391 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2392 DBUS_TYPE_STRING, -1, pos, &pos))
2395 if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2397 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2401 /* Validate element */
2402 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2403 dict_type, -1, pos, &pos))
2405 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
2412 _dbus_verbose ("dict contents exceed stated dict length\n");
2421 _dbus_verbose ("Unknown message arg type %d\n", type);
2425 if (*end_pos > _dbus_string_get_length (str))
2432 * Return #TRUE if the typecode is a valid typecode
2434 * @returns #TRUE if valid
2437 _dbus_type_is_valid (int typecode)
2441 case DBUS_TYPE_BYTE:
2442 case DBUS_TYPE_BOOLEAN:
2443 case DBUS_TYPE_INT32:
2444 case DBUS_TYPE_UINT32:
2445 case DBUS_TYPE_INT64:
2446 case DBUS_TYPE_UINT64:
2447 case DBUS_TYPE_DOUBLE:
2448 case DBUS_TYPE_STRING:
2449 case DBUS_TYPE_OBJECT_PATH:
2450 case DBUS_TYPE_ARRAY:
2451 case DBUS_TYPE_DICT:
2452 case DBUS_TYPE_STRUCT:
2453 case DBUS_TYPE_VARIANT:
2462 * Gets the alignment requirement for the given type;
2463 * will be 1, 4, or 8.
2465 * @param typecode the type
2466 * @returns alignment of 1, 4, or 8
2469 _dbus_type_get_alignment (int typecode)
2473 case DBUS_TYPE_BYTE:
2474 case DBUS_TYPE_BOOLEAN:
2476 case DBUS_TYPE_INT32:
2477 case DBUS_TYPE_UINT32:
2478 /* this stuff is 4 since it starts with a length */
2479 case DBUS_TYPE_STRING:
2480 case DBUS_TYPE_OBJECT_PATH:
2481 case DBUS_TYPE_ARRAY:
2482 case DBUS_TYPE_DICT:
2483 case DBUS_TYPE_VARIANT:
2485 case DBUS_TYPE_INT64:
2486 case DBUS_TYPE_UINT64:
2487 case DBUS_TYPE_DOUBLE:
2488 /* struct is 8 since it could contain an 8-aligned item
2489 * and it's simpler to just always align structs to 8;
2490 * we want the amount of padding in a struct of a given
2491 * type to be predictable, not location-dependent.
2493 case DBUS_TYPE_STRUCT:
2497 _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
2503 * If in verbose mode, print a block of binary data.
2505 * @todo right now it prints even if not in verbose mode
2507 * @param data the data
2508 * @param len the length of the data
2509 * @param offset where to start counting for byte indexes
2512 _dbus_verbose_bytes (const unsigned char *data,
2517 const unsigned char *aligned;
2519 _dbus_assert (len >= 0);
2521 /* Print blanks on first row if appropriate */
2522 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2525 _dbus_assert (aligned <= data);
2527 if (aligned != data)
2529 _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
2530 while (aligned != data)
2532 _dbus_verbose (" ");
2537 /* now print the bytes */
2541 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2543 _dbus_verbose ("%4d\t%p: ",
2544 offset + i, &data[i]);
2547 if (data[i] >= 32 &&
2549 _dbus_verbose (" '%c' ", data[i]);
2551 _dbus_verbose ("0x%s%x ",
2552 data[i] <= 0xf ? "0" : "", data[i]);
2556 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2559 _dbus_verbose ("BE: %d LE: %d",
2560 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2561 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2564 _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2566 _dbus_verbose (" dbl: %g",
2567 *(double*)&data[i-8]);
2570 _dbus_verbose ("\n");
2574 _dbus_verbose ("\n");
2578 * Dump the given part of the string to verbose log.
2580 * @param str the string
2581 * @param start the start of range to dump
2582 * @param len length of range
2585 _dbus_verbose_bytes_of_string (const DBusString *str,
2592 real_len = _dbus_string_get_length (str);
2594 _dbus_assert (start >= 0);
2596 if (start > real_len)
2598 _dbus_verbose (" [%d,%d) is not inside string of length %d\n",
2599 start, len, real_len);
2603 if ((start + len) > real_len)
2605 _dbus_verbose (" [%d,%d) extends outside string of length %d\n",
2606 start, len, real_len);
2607 len = real_len - start;
2610 d = _dbus_string_get_const_data_len (str, start, len);
2612 _dbus_verbose_bytes (d, len, start);
2616 * Marshals a basic type
2618 * @param str string to marshal to
2619 * @param insert_at where to insert the value
2620 * @param type type of value
2621 * @param value pointer to value
2622 * @param byte_order byte order
2623 * @returns #TRUE on success
2626 _dbus_marshal_basic_type (DBusString *str,
2636 case DBUS_TYPE_BYTE:
2637 case DBUS_TYPE_BOOLEAN:
2638 retval = _dbus_string_insert_byte (str, insert_at, *(const unsigned char *)value);
2640 case DBUS_TYPE_INT32:
2641 case DBUS_TYPE_UINT32:
2642 return marshal_4_octets (str, insert_at, byte_order, *(const dbus_uint32_t *)value);
2644 #ifdef DBUS_HAVE_INT64
2645 case DBUS_TYPE_INT64:
2646 case DBUS_TYPE_UINT64:
2649 r.u = *(const dbus_uint64_t *)value;
2650 retval = marshal_8_octets (str, insert_at, byte_order, r);
2653 #endif /* DBUS_HAVE_INT64 */
2654 case DBUS_TYPE_DOUBLE:
2657 r.d = *(const double *)value;
2658 retval = marshal_8_octets (str, insert_at, byte_order, r);
2662 _dbus_assert_not_reached ("not a basic type");
2670 * Marshals a basic type array
2672 * @param str string to marshal to
2673 * @param insert_at where to insert the value
2674 * @param element_type type of array elements
2675 * @param value pointer to value
2676 * @param len length of value data in elements
2677 * @param byte_order byte order
2678 * @returns #TRUE on success
2681 _dbus_marshal_basic_type_array (DBusString *str,
2688 /* FIXME use the insert_at arg */
2690 switch (element_type)
2692 case DBUS_TYPE_BOOLEAN:
2693 /* FIXME: we canonicalize to 0 or 1 for the single boolean case
2694 * should we here too ? */
2695 case DBUS_TYPE_BYTE:
2696 return _dbus_marshal_byte_array (str, byte_order, value, len);
2698 case DBUS_TYPE_INT32:
2699 case DBUS_TYPE_UINT32:
2700 return marshal_4_octets_array (str, byte_order, value, len);
2702 #ifdef DBUS_HAVE_INT64
2703 case DBUS_TYPE_INT64:
2704 case DBUS_TYPE_UINT64:
2705 #endif /* DBUS_HAVE_INT64 */
2706 case DBUS_TYPE_DOUBLE:
2707 return marshal_8_octets_array (str, byte_order, value, len);
2710 _dbus_assert_not_reached ("non basic type in array");
2718 #ifdef DBUS_BUILD_TESTS
2719 #include "dbus-test.h"
2723 _dbus_marshal_test (void)
2728 dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2729 #ifdef DBUS_HAVE_INT64
2730 dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
2731 DBUS_INT64_CONSTANT (0x456ffffffff),
2732 DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
2737 if (!_dbus_string_init (&str))
2738 _dbus_assert_not_reached ("failed to init string");
2740 /* Marshal doubles */
2741 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2742 _dbus_assert_not_reached ("could not marshal double value");
2743 if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2744 _dbus_assert_not_reached ("demarshal failed");
2746 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2747 _dbus_assert_not_reached ("could not marshal double value");
2748 if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2749 _dbus_assert_not_reached ("demarshal failed");
2751 /* Marshal signed integers */
2752 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2753 _dbus_assert_not_reached ("could not marshal signed integer value");
2754 if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2755 _dbus_assert_not_reached ("demarshal failed");
2757 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2758 _dbus_assert_not_reached ("could not marshal signed integer value");
2759 if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2760 _dbus_assert_not_reached ("demarshal failed");
2762 /* Marshal unsigned integers */
2763 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2764 _dbus_assert_not_reached ("could not marshal signed integer value");
2765 if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2766 _dbus_assert_not_reached ("demarshal failed");
2768 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2769 _dbus_assert_not_reached ("could not marshal signed integer value");
2770 if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2771 _dbus_assert_not_reached ("demarshal failed");
2773 #ifdef DBUS_HAVE_INT64
2774 /* Marshal signed integers */
2775 if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2776 _dbus_assert_not_reached ("could not marshal signed integer value");
2777 if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2778 _dbus_assert_not_reached ("demarshal failed");
2780 if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2781 _dbus_assert_not_reached ("could not marshal signed integer value");
2782 if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2783 _dbus_assert_not_reached ("demarshal failed");
2785 /* Marshal unsigned integers */
2786 if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2787 _dbus_assert_not_reached ("could not marshal signed integer value");
2788 if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2789 _dbus_assert_not_reached ("demarshal failed");
2791 if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2792 _dbus_assert_not_reached ("could not marshal signed integer value");
2793 if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2794 _dbus_assert_not_reached ("demarshal failed");
2795 #endif /* DBUS_HAVE_INT64 */
2797 /* Marshal strings */
2798 tmp1 = "This is the dbus test string";
2799 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2800 _dbus_assert_not_reached ("could not marshal string");
2801 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2802 if (!strcmp (tmp1, tmp2) == 0)
2803 _dbus_assert_not_reached ("demarshal failed");
2806 tmp1 = "This is the dbus test string";
2807 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2808 _dbus_assert_not_reached ("could not marshal string");
2809 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2810 if (!strcmp (tmp1, tmp2) == 0)
2811 _dbus_assert_not_reached ("demarshal failed");
2814 /* Marshal signed integer arrays */
2815 if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2816 _dbus_assert_not_reached ("could not marshal integer array");
2817 if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2818 _dbus_assert_not_reached ("could not demarshal integer array");
2821 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2824 #ifdef DBUS_HAVE_INT64
2825 /* Marshal 64-bit signed integer arrays */
2826 if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2827 _dbus_assert_not_reached ("could not marshal integer array");
2828 if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2829 _dbus_assert_not_reached ("could not demarshal integer array");
2832 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2835 /* set/pack 64-bit integers */
2836 _dbus_string_set_length (&str, 8);
2839 _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2840 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2842 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2843 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2844 _dbus_string_get_const_data (&str)));
2847 _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2848 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2850 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2851 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2852 _dbus_string_get_const_data (&str)));
2854 /* signed little pack */
2855 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2857 _dbus_string_get_data (&str));
2859 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2860 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2861 _dbus_string_get_const_data (&str)));
2863 /* signed big pack */
2864 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2866 _dbus_string_get_data (&str));
2868 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2869 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2870 _dbus_string_get_const_data (&str)));
2872 /* unsigned little */
2873 _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2874 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2876 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2877 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2878 _dbus_string_get_const_data (&str)));
2881 _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2882 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2884 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2885 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2886 _dbus_string_get_const_data (&str)));
2888 /* unsigned little pack */
2889 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2891 _dbus_string_get_data (&str));
2893 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2894 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2895 _dbus_string_get_const_data (&str)));
2897 /* unsigned big pack */
2898 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2900 _dbus_string_get_data (&str));
2902 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2903 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2904 _dbus_string_get_const_data (&str)));
2908 /* set/pack 32-bit integers */
2909 _dbus_string_set_length (&str, 4);
2912 _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2915 _dbus_assert (-0x123456 ==
2916 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2917 _dbus_string_get_const_data (&str)));
2920 _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2923 _dbus_assert (-0x123456 ==
2924 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2925 _dbus_string_get_const_data (&str)));
2927 /* signed little pack */
2928 _dbus_pack_int32 (-0x123456,
2930 _dbus_string_get_data (&str));
2932 _dbus_assert (-0x123456 ==
2933 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2934 _dbus_string_get_const_data (&str)));
2936 /* signed big pack */
2937 _dbus_pack_int32 (-0x123456,
2939 _dbus_string_get_data (&str));
2941 _dbus_assert (-0x123456 ==
2942 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2943 _dbus_string_get_const_data (&str)));
2945 /* unsigned little */
2946 _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2949 _dbus_assert (0x123456 ==
2950 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2951 _dbus_string_get_const_data (&str)));
2954 _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2957 _dbus_assert (0x123456 ==
2958 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2959 _dbus_string_get_const_data (&str)));
2961 /* unsigned little pack */
2962 _dbus_pack_uint32 (0x123456,
2964 _dbus_string_get_data (&str));
2966 _dbus_assert (0x123456 ==
2967 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2968 _dbus_string_get_const_data (&str)));
2970 /* unsigned big pack */
2971 _dbus_pack_uint32 (0x123456,
2973 _dbus_string_get_data (&str));
2975 _dbus_assert (0x123456 ==
2976 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2977 _dbus_string_get_const_data (&str)));
2982 _dbus_string_set_length (&str, 0);
2984 _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2987 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2988 _dbus_assert (strcmp (s, "Hello world") == 0);
2991 _dbus_string_init_const (&t, "Hello world foo");
2993 _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2994 &t, _dbus_string_get_length (&t));
2996 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2997 _dbus_assert (strcmp (s, "Hello world foo") == 0);
3000 _dbus_string_init_const (&t, "Hello");
3002 _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
3003 &t, _dbus_string_get_length (&t));
3005 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
3006 _dbus_assert (strcmp (s, "Hello") == 0);
3009 /* Strings (big endian) */
3011 _dbus_string_set_length (&str, 0);
3013 _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
3016 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3017 _dbus_assert (strcmp (s, "Hello world") == 0);
3020 _dbus_string_init_const (&t, "Hello world foo");
3022 _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
3023 &t, _dbus_string_get_length (&t));
3025 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3026 _dbus_assert (strcmp (s, "Hello world foo") == 0);
3029 _dbus_string_init_const (&t, "Hello");
3031 _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
3032 &t, _dbus_string_get_length (&t));
3034 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3035 _dbus_assert (strcmp (s, "Hello") == 0);
3038 _dbus_string_free (&str);
3043 #endif /* DBUS_BUILD_TESTS */