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-marshal-basic.h"
26 #include "dbus-internals.h"
27 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
28 #include "dbus-string-private.h"
33 * @defgroup DBusMarshal marshaling and unmarshaling
34 * @ingroup DBusInternals
35 * @brief functions to marshal/unmarshal data from the wire
37 * Types and functions related to converting primitive data types from
38 * wire format to native machine format, and vice versa.
40 * A signature is just a string with multiple types one after the other.
41 * for example a type is "i" or "(ii)", a signature is "i(ii)"
42 * where i is int and (ii) is struct { int; int; }
48 unpack_4_octets (int byte_order,
49 const unsigned char *data)
51 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
53 if (byte_order == DBUS_LITTLE_ENDIAN)
54 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
56 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
59 #ifndef DBUS_HAVE_INT64
62 swap_bytes (unsigned char *data,
65 unsigned char *p1 = data;
66 unsigned char *p2 = data + len - 1;
70 unsigned char tmp = *p1;
78 #endif /* !DBUS_HAVE_INT64 */
81 * Union used to manipulate 8 bytes as if they
86 #ifdef DBUS_HAVE_INT64
87 dbus_int64_t s; /**< 64-bit integer */
88 dbus_uint64_t u; /**< 64-bit unsinged integer */
90 double d; /**< double */
94 unpack_8_octets (int byte_order,
95 const unsigned char *data)
99 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
100 _dbus_assert (sizeof (r) == 8);
102 #ifdef DBUS_HAVE_INT64
103 if (byte_order == DBUS_LITTLE_ENDIAN)
104 r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
106 r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
108 r.d = *(double*)data;
109 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
110 swap_bytes ((unsigned char*) &r, sizeof (r));
117 * Unpacks a 32 bit unsigned integer from a data pointer
119 * @param byte_order The byte order to use
120 * @param data the data pointer
121 * @returns the integer
124 _dbus_unpack_uint32 (int byte_order,
125 const unsigned char *data)
127 return unpack_4_octets (byte_order, data);
131 * Unpacks a 32 bit signed integer from a data pointer
133 * @param byte_order The byte order to use
134 * @param data the data pointer
135 * @returns the integer
138 _dbus_unpack_int32 (int byte_order,
139 const unsigned char *data)
141 return (dbus_int32_t) unpack_4_octets (byte_order, data);
144 #ifdef DBUS_HAVE_INT64
146 * Unpacks a 64 bit unsigned integer from a data pointer
148 * @param byte_order The byte order to use
149 * @param data the data pointer
150 * @returns the integer
153 _dbus_unpack_uint64 (int byte_order,
154 const unsigned char *data)
158 r = unpack_8_octets (byte_order, data);
164 * Unpacks a 64 bit signed integer from a data pointer
166 * @param byte_order The byte order to use
167 * @param data the data pointer
168 * @returns the integer
171 _dbus_unpack_int64 (int byte_order,
172 const unsigned char *data)
176 r = unpack_8_octets (byte_order, data);
181 #endif /* DBUS_HAVE_INT64 */
184 pack_4_octets (dbus_uint32_t value,
188 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
190 if ((byte_order) == DBUS_LITTLE_ENDIAN)
191 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
193 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
197 pack_8_octets (DBusOctets8 value,
201 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
203 #ifdef DBUS_HAVE_INT64
204 if ((byte_order) == DBUS_LITTLE_ENDIAN)
205 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u);
207 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
209 memcpy (data, &value, 8);
210 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
211 swap_bytes ((unsigned char *)data, 8);
216 * Packs a 32 bit unsigned integer into a data pointer.
218 * @param value the value
219 * @param byte_order the byte order to use
220 * @param data the data pointer
223 _dbus_pack_uint32 (dbus_uint32_t value,
227 pack_4_octets (value, byte_order, data);
231 * Packs a 32 bit signed integer into a data pointer.
233 * @param value the value
234 * @param byte_order the byte order to use
235 * @param data the data pointer
238 _dbus_pack_int32 (dbus_int32_t value,
242 pack_4_octets ((dbus_uint32_t) value, byte_order, data);
245 #ifdef DBUS_HAVE_INT64
247 * Packs a 64 bit unsigned integer into a data pointer.
249 * @param value the value
250 * @param byte_order the byte order to use
251 * @param data the data pointer
254 _dbus_pack_uint64 (dbus_uint64_t value,
260 pack_8_octets (r, byte_order, data);
264 * Packs a 64 bit signed integer into a data pointer.
266 * @param value the value
267 * @param byte_order the byte order to use
268 * @param data the data pointer
271 _dbus_pack_int64 (dbus_int64_t value,
277 pack_8_octets (r, byte_order, data);
279 #endif /* DBUS_HAVE_INT64 */
282 set_4_octets (DBusString *str,
289 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
290 byte_order == DBUS_BIG_ENDIAN);
292 data = _dbus_string_get_data_len (str, offset, 4);
294 _dbus_pack_uint32 (value, byte_order, data);
298 set_8_octets (DBusString *str,
305 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
306 byte_order == DBUS_BIG_ENDIAN);
308 data = _dbus_string_get_data_len (str, offset, 8);
310 pack_8_octets (value, byte_order, data);
314 * Sets the 4 bytes at the given offset to a marshaled signed integer,
315 * replacing anything found there previously.
317 * @param str the string to write the marshalled int to
318 * @param offset the byte offset where int should be written
319 * @param byte_order the byte order to use
320 * @param value the value
324 _dbus_marshal_set_int32 (DBusString *str,
329 set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
333 * Sets the 4 bytes at the given offset to a marshaled unsigned
334 * integer, replacing anything found there previously.
336 * @param str the string to write the marshalled int to
337 * @param offset the byte offset where int should be written
338 * @param byte_order the byte order to use
339 * @param value the value
343 _dbus_marshal_set_uint32 (DBusString *str,
348 set_4_octets (str, byte_order, offset, value);
351 #ifdef DBUS_HAVE_INT64
354 * Sets the 8 bytes at the given offset to a marshaled signed integer,
355 * replacing anything found there previously.
357 * @param str the string to write the marshalled int to
358 * @param offset the byte offset where int should be written
359 * @param byte_order the byte order to use
360 * @param value the value
364 _dbus_marshal_set_int64 (DBusString *str,
371 set_8_octets (str, byte_order, offset, r);
375 * Sets the 8 bytes at the given offset to a marshaled unsigned
376 * integer, replacing anything found there previously.
378 * @param str the string to write the marshalled int to
379 * @param offset the byte offset where int should be written
380 * @param byte_order the byte order to use
381 * @param value the value
385 _dbus_marshal_set_uint64 (DBusString *str,
392 set_8_octets (str, byte_order, offset, r);
394 #endif /* DBUS_HAVE_INT64 */
397 * Sets the existing marshaled string at the given offset with
398 * a new marshaled string. The given offset must point to
399 * an existing string or the wrong length will be deleted
400 * and replaced with the new string.
402 * Note: no attempt is made by this function to re-align
403 * any data which has been already marshalled after this
404 * string. Use with caution.
406 * @param str the string to write the marshalled string to
407 * @param offset the byte offset where string should be written
408 * @param byte_order the byte order to use
409 * @param value the value
410 * @param len the length to use
411 * @returns #TRUE on success
415 _dbus_marshal_set_string (DBusString *str,
418 const DBusString *value,
423 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
424 byte_order == DBUS_BIG_ENDIAN);
426 old_len = _dbus_demarshal_uint32 (str, byte_order,
429 if (!_dbus_string_replace_len (value, 0, len,
430 str, offset + 4, old_len))
433 _dbus_marshal_set_uint32 (str, byte_order,
440 * Sets the existing marshaled object path at the given offset to a new
441 * value. The given offset must point to an existing object path or this
442 * function doesn't make sense.
444 * @todo implement this function
446 * @param str the string to write the marshalled path to
447 * @param offset the byte offset where path should be written
448 * @param byte_order the byte order to use
449 * @param path the new path
450 * @param path_len number of elements in the path
453 _dbus_marshal_set_object_path (DBusString *str,
464 marshal_4_octets (DBusString *str,
468 _dbus_assert (sizeof (value) == 4);
470 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
471 value = DBUS_UINT32_SWAP_LE_BE (value);
473 return _dbus_string_append_4_aligned (str,
474 (const unsigned char *)&value);
478 marshal_8_octets (DBusString *str,
482 _dbus_assert (sizeof (value) == 8);
484 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
485 pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
487 return _dbus_string_append_8_aligned (str,
488 (const unsigned char *)&value);
492 * Marshals a double value.
494 * @param str the string to append the marshalled value to
495 * @param byte_order the byte order to use
496 * @param value the value
497 * @returns #TRUE on success
500 _dbus_marshal_double (DBusString *str,
506 return marshal_8_octets (str, byte_order, r);
510 * Marshals a 32 bit signed integer value.
512 * @param str the string to append the marshalled value to
513 * @param byte_order the byte order to use
514 * @param value the value
515 * @returns #TRUE on success
518 _dbus_marshal_int32 (DBusString *str,
522 return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
526 * Marshals a 32 bit unsigned integer value.
528 * @param str the string to append the marshalled value to
529 * @param byte_order the byte order to use
530 * @param value the value
531 * @returns #TRUE on success
534 _dbus_marshal_uint32 (DBusString *str,
538 return marshal_4_octets (str, byte_order, value);
542 #ifdef DBUS_HAVE_INT64
544 * Marshals a 64 bit signed integer value.
546 * @param str the string to append the marshalled value to
547 * @param byte_order the byte order to use
548 * @param value the value
549 * @returns #TRUE on success
552 _dbus_marshal_int64 (DBusString *str,
558 return marshal_8_octets (str, byte_order, r);
562 * Marshals a 64 bit unsigned integer value.
564 * @param str the string to append the marshalled value to
565 * @param byte_order the byte order to use
566 * @param value the value
567 * @returns #TRUE on success
570 _dbus_marshal_uint64 (DBusString *str,
576 return marshal_8_octets (str, byte_order, r);
579 #endif /* DBUS_HAVE_INT64 */
582 * Marshals a UTF-8 string
584 * @todo: If the string append fails we need to restore
585 * the old length. (also for other marshallers)
587 * @param str the string to append the marshalled value to
588 * @param byte_order the byte order to use
589 * @param value the string
590 * @returns #TRUE on success
593 _dbus_marshal_string (DBusString *str,
597 int len, old_string_len;
599 old_string_len = _dbus_string_get_length (str);
601 len = strlen (value);
603 if (!_dbus_marshal_uint32 (str, byte_order, len))
605 /* Restore the previous length */
606 _dbus_string_set_length (str, old_string_len);
611 return _dbus_string_append_len (str, value, len + 1);
615 * Marshals a UTF-8 string
617 * @todo: If the string append fails we need to restore
618 * the old length. (also for other marshallers)
620 * @param str the string to append the marshalled value to
621 * @param byte_order the byte order to use
622 * @param value the string
623 * @param len length of string to marshal in bytes
624 * @returns #TRUE on success
627 _dbus_marshal_string_len (DBusString *str,
634 old_string_len = _dbus_string_get_length (str);
636 if (!_dbus_marshal_uint32 (str, byte_order, len))
638 /* Restore the previous length */
639 _dbus_string_set_length (str, old_string_len);
644 if (!_dbus_string_append_len (str, value, len))
648 if (!_dbus_string_lengthen (str, 1))
655 * Marshals a byte array
657 * @param str the string to append the marshalled value to
658 * @param byte_order the byte order to use
659 * @param value the array
660 * @param len number of elements in the array
661 * @returns #TRUE on success
664 _dbus_marshal_byte_array (DBusString *str,
666 const unsigned char *value,
671 old_string_len = _dbus_string_get_length (str);
673 if (!_dbus_marshal_uint32 (str, byte_order, len))
675 /* Restore the previous length */
676 _dbus_string_set_length (str, old_string_len);
684 return _dbus_string_append_len (str, value, len);
688 marshal_4_octets_array (DBusString *str,
690 const dbus_uint32_t *value,
696 old_string_len = _dbus_string_get_length (str);
698 if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
701 array_start = _dbus_string_get_length (str);
703 if (!_dbus_string_append_len (str, (const unsigned char*) value,
707 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
709 const unsigned char *d;
710 const unsigned char *end;
712 d = _dbus_string_get_data (str) + array_start;
716 *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
724 /* Restore previous length */
725 _dbus_string_set_length (str, old_string_len);
731 marshal_8_octets_array (DBusString *str,
733 const DBusOctets8 *value,
739 old_string_len = _dbus_string_get_length (str);
741 if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
744 array_start = _dbus_string_get_length (str);
746 if (!_dbus_string_append_len (str, (const unsigned char*) value,
750 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
752 const unsigned char *d;
753 const unsigned char *end;
755 d = _dbus_string_get_data (str) + array_start;
759 #ifdef DBUS_HAVE_INT64
760 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
762 swap_bytes ((unsigned char*) d, 8);
771 /* Restore previous length */
772 _dbus_string_set_length (str, old_string_len);
778 * Marshals a 32 bit signed integer array
780 * @param str the string to append the marshalled value to
781 * @param byte_order the byte order to use
782 * @param value the array
783 * @param len the length of the array
784 * @returns #TRUE on success
787 _dbus_marshal_int32_array (DBusString *str,
789 const dbus_int32_t *value,
792 return marshal_4_octets_array (str, byte_order,
793 (const dbus_uint32_t*) value,
798 * Marshals a 32 bit unsigned 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_uint32_array (DBusString *str,
809 const dbus_uint32_t *value,
812 return marshal_4_octets_array (str, byte_order,
817 #ifdef DBUS_HAVE_INT64
820 * Marshals a 64 bit signed integer array
822 * @param str the string to append the marshalled value to
823 * @param byte_order the byte order to use
824 * @param value the array
825 * @param len the length of the array
826 * @returns #TRUE on success
829 _dbus_marshal_int64_array (DBusString *str,
831 const dbus_int64_t *value,
834 return marshal_8_octets_array (str, byte_order,
835 (const DBusOctets8*) value,
840 * Marshals a 64 bit unsigned 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_uint64_array (DBusString *str,
851 const dbus_uint64_t *value,
854 return marshal_8_octets_array (str, byte_order,
855 (const DBusOctets8*) value,
859 #endif /* DBUS_HAVE_INT64 */
862 * Marshals a double array
864 * @param str the string to append the marshalled value to
865 * @param byte_order the byte order to use
866 * @param value the array
867 * @param len the length of the array
868 * @returns #TRUE on success
871 _dbus_marshal_double_array (DBusString *str,
876 return marshal_8_octets_array (str, byte_order,
877 (const DBusOctets8*) value,
882 * Marshals a string 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_string_array (DBusString *str,
896 int i, old_string_len, array_start;
898 old_string_len = _dbus_string_get_length (str);
900 /* Set the length to 0 temporarily */
901 if (!_dbus_marshal_uint32 (str, byte_order, 0))
904 array_start = _dbus_string_get_length (str);
906 for (i = 0; i < len; i++)
907 if (!_dbus_marshal_string (str, byte_order, value[i]))
910 /* Write the length now that we know it */
911 _dbus_marshal_set_uint32 (str, byte_order,
912 _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
913 _dbus_string_get_length (str) - array_start);
918 /* Restore previous length */
919 _dbus_string_set_length (str, old_string_len);
925 * Marshals an object path value.
927 * @param str the string to append the marshalled value to
928 * @param byte_order the byte order to use
929 * @param path the path
930 * @param path_len length of the path
931 * @returns #TRUE on success
934 _dbus_marshal_object_path (DBusString *str,
939 int array_start, old_string_len;
942 old_string_len = _dbus_string_get_length (str);
944 /* Set the length to 0 temporarily */
945 if (!_dbus_marshal_uint32 (str, byte_order, 0))
948 array_start = _dbus_string_get_length (str);
953 if (!_dbus_string_append_byte (str, '/'))
956 if (!_dbus_string_append (str, path[0]))
962 /* Write the length now that we know it */
963 _dbus_marshal_set_uint32 (str, byte_order,
964 _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
965 _dbus_string_get_length (str) - array_start);
970 /* Restore the previous length */
971 _dbus_string_set_length (str, old_string_len);
977 demarshal_4_octets (const DBusString *str,
982 const DBusRealString *real = (const DBusRealString*) str;
984 pos = _DBUS_ALIGN_VALUE (pos, 4);
989 return unpack_4_octets (byte_order, real->str + pos);
993 demarshal_8_octets (const DBusString *str,
998 const DBusRealString *real = (const DBusRealString*) str;
1000 pos = _DBUS_ALIGN_VALUE (pos, 8);
1005 return unpack_8_octets (byte_order, real->str + pos);
1009 * Demarshals a double.
1011 * @param str the string containing the data
1012 * @param byte_order the byte order
1013 * @param pos the position in the string
1014 * @param new_pos the new position of the string
1015 * @returns the demarshaled double.
1018 _dbus_demarshal_double (const DBusString *str,
1025 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1031 * Demarshals a 32 bit signed integer.
1033 * @param str the string containing the data
1034 * @param byte_order the byte order
1035 * @param pos the position in the string
1036 * @param new_pos the new position of the string
1037 * @returns the demarshaled integer.
1040 _dbus_demarshal_int32 (const DBusString *str,
1045 return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
1049 * Demarshals a 32 bit unsigned integer.
1051 * @param str the string containing the data
1052 * @param byte_order the byte order
1053 * @param pos the position in the string
1054 * @param new_pos the new position of the string
1055 * @returns the demarshaled integer.
1058 _dbus_demarshal_uint32 (const DBusString *str,
1063 return demarshal_4_octets (str, byte_order, pos, new_pos);
1066 #ifdef DBUS_HAVE_INT64
1069 * Demarshals a 64 bit signed 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_int64 (const DBusString *str,
1085 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1091 * Demarshals a 64 bit unsigned integer.
1093 * @param str the string containing the data
1094 * @param byte_order the byte order
1095 * @param pos the position in the string
1096 * @param new_pos the new position of the string
1097 * @returns the demarshaled integer.
1100 _dbus_demarshal_uint64 (const DBusString *str,
1107 r = demarshal_8_octets (str, byte_order, pos, new_pos);
1112 #endif /* DBUS_HAVE_INT64 */
1115 * Demarshals a basic type
1117 * @param str the string containing the data
1118 * @param type type of value to demarshal
1119 * @param value pointer to return value data
1120 * @param byte_order the byte order
1121 * @param pos pointer to position in the string,
1122 * updated on return to new position
1125 _dbus_demarshal_basic_type (const DBusString *str,
1131 const char *str_data = _dbus_string_get_const_data (str);
1135 case DBUS_TYPE_BYTE:
1136 case DBUS_TYPE_BOOLEAN:
1137 *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
1140 case DBUS_TYPE_INT32:
1141 case DBUS_TYPE_UINT32:
1142 *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1143 *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
1144 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1145 *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
1148 #ifdef DBUS_HAVE_INT64
1149 case DBUS_TYPE_INT64:
1150 case DBUS_TYPE_UINT64:
1151 #endif /* DBUS_HAVE_INT64 */
1152 case DBUS_TYPE_DOUBLE:
1153 *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1154 memcpy (value, str_data + *pos, 8);
1155 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1156 #ifdef DBUS_HAVE_INT64
1157 *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
1159 swap_bytes (value, 8);
1164 _dbus_assert_not_reached ("not a basic type");
1170 * Demarshals an UTF-8 string.
1172 * @todo Should we check the string to make sure
1173 * that it's valid UTF-8, and maybe "fix" the string
1176 * @todo Should probably demarshal to a DBusString,
1177 * having memcpy() in here is Evil(tm).
1179 * @param str the string containing the data
1180 * @param byte_order the byte order
1181 * @param pos the position in the string
1182 * @param new_pos the new position of the string
1183 * @returns the demarshaled string.
1186 _dbus_demarshal_string (const DBusString *str,
1195 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1197 retval = dbus_malloc (len + 1);
1202 data = _dbus_string_get_const_data_len (str, pos, len + 1);
1207 memcpy (retval, data, len + 1);
1210 *new_pos = pos + len + 1;
1216 * Demarshals a byte array.
1218 * @todo Should probably demarshal to a DBusString,
1219 * having memcpy() in here is Evil(tm).
1221 * @param str the string containing the data
1222 * @param byte_order the byte order
1223 * @param pos the position in the string
1224 * @param new_pos the new position of the string
1225 * @param array the array
1226 * @param array_len length of the demarshaled data
1228 * @returns #TRUE on success
1231 _dbus_demarshal_byte_array (const DBusString *str,
1235 unsigned char **array,
1239 unsigned char *retval;
1242 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1255 retval = dbus_malloc (len);
1260 data = _dbus_string_get_const_data_len (str, pos, len);
1268 memcpy (retval, data, len);
1271 *new_pos = pos + len;
1280 demarshal_4_octets_array (const DBusString *str,
1284 dbus_uint32_t **array,
1288 dbus_uint32_t *retval;
1291 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1305 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1309 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1311 for (i = 0; i < len; i++)
1312 retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1316 *new_pos = pos + byte_len;
1325 demarshal_8_octets_array (const DBusString *str,
1329 DBusOctets8 **array,
1333 DBusOctets8 *retval;
1336 byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1350 if (!_dbus_string_copy_data_len (str, (char**) &retval,
1354 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1356 for (i = 0; i < len; i++)
1358 #ifdef DBUS_HAVE_INT64
1359 retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1361 swap_bytes ((unsigned char *) &retval[i], 8);
1367 *new_pos = pos + byte_len;
1376 * Demarshals a 32 bit signed integer array.
1378 * @param str the string containing the data
1379 * @param byte_order the byte order
1380 * @param pos the position in the string
1381 * @param new_pos the new position of the string
1382 * @param array the array
1383 * @param array_len length of the demarshaled data
1384 * @returns #TRUE on success
1387 _dbus_demarshal_int32_array (const DBusString *str,
1391 dbus_int32_t **array,
1394 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1395 (dbus_uint32_t**) array, array_len);
1399 * Demarshals a 32 bit unsigned integer array.
1401 * @param str the string containing the data
1402 * @param byte_order the byte order
1403 * @param pos the position in the string
1404 * @param new_pos the new position of the string
1405 * @param array the array
1406 * @param array_len length of the demarshaled data
1407 * @returns #TRUE on success
1410 _dbus_demarshal_uint32_array (const DBusString *str,
1414 dbus_uint32_t **array,
1417 return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1421 #ifdef DBUS_HAVE_INT64
1424 * Demarshals a 64 bit signed integer array.
1426 * @param str the string containing the data
1427 * @param byte_order the byte order
1428 * @param pos the position in the string
1429 * @param new_pos the new position of the string
1430 * @param array the array
1431 * @param array_len length of the demarshaled data
1432 * @returns #TRUE on success
1435 _dbus_demarshal_int64_array (const DBusString *str,
1439 dbus_int64_t **array,
1442 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1443 (DBusOctets8**) array, array_len);
1447 * Demarshals a 64 bit unsigned integer array.
1449 * @param str the string containing the data
1450 * @param byte_order the byte order
1451 * @param pos the position in the string
1452 * @param new_pos the new position of the string
1453 * @param array the array
1454 * @param array_len length of the demarshaled data
1455 * @returns #TRUE on success
1458 _dbus_demarshal_uint64_array (const DBusString *str,
1462 dbus_uint64_t **array,
1465 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1466 (DBusOctets8**) array, array_len);
1469 #endif /* DBUS_HAVE_INT64 */
1472 * Demarshals a double array.
1474 * @param str the string containing the data
1475 * @param byte_order the byte order
1476 * @param pos the position in the string
1477 * @param new_pos the new position of the string
1478 * @param array the array
1479 * @param array_len length of the demarshaled data
1480 * @returns #TRUE on success
1483 _dbus_demarshal_double_array (const DBusString *str,
1490 return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1491 (DBusOctets8**) array, array_len);
1496 * Demarshals an array of basic types
1498 * @param str the string containing the data
1499 * @param element_type type of array elements to demarshal
1500 * @param array pointer to pointer to array data
1501 * @param array_len pointer to array length
1502 * @param byte_order the byte order
1503 * @param pos pointer to position in the string,
1504 * updated on return to new position
1507 _dbus_demarshal_basic_type_array (const DBusString *str,
1514 switch (element_type)
1516 case DBUS_TYPE_BOOLEAN:
1517 /* FIXME: do we want to post-normalize these ? */
1518 case DBUS_TYPE_BYTE:
1519 return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
1520 (unsigned char **)array, array_len);
1522 case DBUS_TYPE_INT32:
1523 case DBUS_TYPE_UINT32:
1524 return demarshal_4_octets_array (str, byte_order, *pos, pos,
1525 (dbus_uint32_t **)array, array_len);
1527 #ifdef DBUS_HAVE_INT64
1528 case DBUS_TYPE_INT64:
1529 case DBUS_TYPE_UINT64:
1530 #endif /* DBUS_HAVE_INT64 */
1531 case DBUS_TYPE_DOUBLE:
1532 return demarshal_8_octets_array (str, byte_order, *pos, pos,
1533 (DBusOctets8**) array, array_len);
1535 _dbus_assert_not_reached ("not a basic type");
1542 * Demarshals a string array.
1544 * @param str the string containing the data
1545 * @param byte_order the byte order
1546 * @param pos the position in the string
1547 * @param new_pos the new position of the string
1548 * @param array the array
1549 * @param array_len location for length of the demarshaled data or NULL
1550 * @returns #TRUE on success
1553 _dbus_demarshal_string_array (const DBusString *str,
1565 bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1580 end_pos = pos + bytes_len;
1582 retval = dbus_new (char *, allocated);
1587 while (pos < end_pos)
1589 retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1591 if (retval[len] == NULL)
1596 if (len >= allocated - 1) /* -1 for NULL termination */
1599 newp = dbus_realloc (retval,
1600 sizeof (char*) * allocated * 2);
1620 for (i = 0; i < len; i++)
1621 dbus_free (retval[i]);
1627 /** Set to 1 to get a bunch of spew about disassembling the path string */
1628 #define VERBOSE_DECOMPOSE 0
1631 * Decompose an object path. A path of just "/" is
1632 * represented as an empty vector of strings.
1634 * @param data the path data
1635 * @param len the length of the path string
1636 * @param path address to store new object path
1637 * @param path_len length of stored path
1640 _dbus_decompose_path (const char* data,
1649 _dbus_assert (data != NULL);
1651 #if VERBOSE_DECOMPOSE
1652 _dbus_verbose ("Decomposing path \"%s\"\n",
1665 retval = dbus_new0 (char*, n_components + 1);
1678 while (j < len && data[j] != '/')
1681 /* Now [i, j) is the path component */
1682 _dbus_assert (i < j);
1683 _dbus_assert (data[i] != '/');
1684 _dbus_assert (j == len || data[j] == '/');
1686 #if VERBOSE_DECOMPOSE
1687 _dbus_verbose (" (component in [%d,%d))\n",
1691 retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1692 if (retval[comp] == NULL)
1694 dbus_free_string_array (retval);
1697 retval[comp][j-i] = '\0';
1698 #if VERBOSE_DECOMPOSE
1699 _dbus_verbose (" (component %d = \"%s\")\n",
1700 comp, retval[comp]);
1706 _dbus_assert (i == len);
1710 *path_len = n_components;
1716 * Demarshals an object path. A path of just "/" is
1717 * represented as an empty vector of strings.
1719 * @param str the string containing the data
1720 * @param byte_order the byte order
1721 * @param pos the position in the string
1722 * @param new_pos the new position of the string
1723 * @param path address to store new object path
1724 * @param path_len length of stored path
1727 _dbus_demarshal_object_path (const DBusString *str,
1737 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1738 data = _dbus_string_get_const_data_len (str, pos, len + 1);
1740 if (!_dbus_decompose_path (data, len, path, path_len))
1744 *new_pos = pos + len + 1;
1750 * Returns the position right after the end of an argument. PERFORMS
1751 * NO VALIDATION WHATSOEVER. The message must have been previously
1754 * @param str a string
1755 * @param byte_order the byte order to use
1756 * @param type the type of the argument
1757 * @param pos the pos where the arg starts
1758 * @param end_pos pointer where the position right
1759 * after the end position will follow
1760 * @returns TRUE if more data exists after the arg
1763 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1769 if (pos >= _dbus_string_get_length (str))
1774 case DBUS_TYPE_INVALID:
1782 case DBUS_TYPE_BYTE:
1786 case DBUS_TYPE_BOOLEAN:
1790 case DBUS_TYPE_INT32:
1791 case DBUS_TYPE_UINT32:
1792 *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1795 case DBUS_TYPE_INT64:
1796 case DBUS_TYPE_UINT64:
1797 case DBUS_TYPE_DOUBLE:
1799 *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1802 case DBUS_TYPE_OBJECT_PATH:
1803 case DBUS_TYPE_STRING:
1807 /* Demarshal the length */
1808 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1810 *end_pos = pos + len + 1;
1814 case DBUS_TYPE_CUSTOM:
1818 /* Demarshal the string length */
1819 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1823 /* Demarshal the data length */
1824 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1826 *end_pos = pos + len;
1830 case DBUS_TYPE_ARRAY:
1834 /* Demarshal the length */
1835 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1837 *end_pos = pos + len;
1841 case DBUS_TYPE_DICT:
1845 /* Demarshal the length */
1846 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1848 *end_pos = pos + len;
1853 _dbus_warn ("Unknown message arg type %d\n", type);
1854 _dbus_assert_not_reached ("Unknown message argument type\n");
1858 if (*end_pos > _dbus_string_get_length (str))
1865 * Demarshals and validates a length; returns < 0 if the validation
1866 * fails. The length is required to be small enough that
1867 * len*sizeof(double) will not overflow, and small enough to fit in a
1868 * signed integer. DOES NOT check whether the length points
1869 * beyond the end of the string, because it doesn't know the
1870 * size of array elements.
1872 * @param str the string
1873 * @param byte_order the byte order
1874 * @param pos the unaligned string position (snap to next aligned)
1875 * @param new_pos return location for new position.
1878 demarshal_and_validate_len (const DBusString *str,
1883 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1886 _dbus_assert (new_pos != NULL);
1888 if ((align_4 + 4) > _dbus_string_get_length (str))
1890 _dbus_verbose ("not enough room in message for array length\n");
1894 if (!_dbus_string_validate_nul (str, pos,
1897 _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
1901 len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1903 /* note that the len is the number of bytes, so we need it to be
1904 * at least SIZE_T_MAX, but make it smaller just to keep things
1905 * sane. We end up using ints for most sizes to avoid unsigned mess
1906 * so limit to maximum 32-bit signed int divided by at least 8, more
1907 * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1909 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1910 if (len > MAX_ARRAY_LENGTH)
1912 _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
1913 len, MAX_ARRAY_LENGTH, pos);
1921 validate_string (const DBusString *str,
1923 int len_without_nul,
1926 *end_pos = pos + len_without_nul + 1;
1928 if (*end_pos > _dbus_string_get_length (str))
1930 _dbus_verbose ("string length outside length of the message\n");
1934 if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1936 _dbus_verbose ("string arg not nul-terminated\n");
1940 if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1942 _dbus_verbose ("string is not valid UTF-8\n");
1950 * Validates and returns a typecode at a specific position
1953 * @param str a string
1954 * @param type the type of the argument
1955 * @param pos the pos where the typecode starts
1956 * @param end_pos pointer where the position right
1957 * after the end position will follow
1958 * @returns #TRUE if the type is valid.
1961 _dbus_marshal_validate_type (const DBusString *str,
1968 if (pos >= _dbus_string_get_length (str))
1971 data = _dbus_string_get_const_data_len (str, pos, 1);
1973 if (_dbus_type_is_valid (*data))
1976 if (end_pos != NULL)
1981 _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
1986 /* Faster validator for array data that doesn't call
1987 * validate_arg for each value
1990 validate_array_data (const DBusString *str,
2001 case DBUS_TYPE_INVALID:
2008 case DBUS_TYPE_OBJECT_PATH:
2009 case DBUS_TYPE_STRING:
2010 case DBUS_TYPE_CUSTOM:
2011 case DBUS_TYPE_ARRAY:
2012 case DBUS_TYPE_DICT:
2013 /* This clean recursion to validate_arg is what we
2014 * are doing logically for all types, but we don't
2015 * really want to call validate_arg for every byte
2016 * in a byte array, so the primitive types are
2021 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2022 type, array_type_pos, pos, &pos))
2027 case DBUS_TYPE_BYTE:
2031 case DBUS_TYPE_BOOLEAN:
2036 c = _dbus_string_get_byte (str, pos);
2038 if (!(c == 0 || c == 1))
2040 _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2048 case DBUS_TYPE_INT32:
2049 case DBUS_TYPE_UINT32:
2050 /* Call validate arg one time to check alignment padding
2053 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2054 type, array_type_pos, pos, &pos))
2056 pos = _DBUS_ALIGN_VALUE (end, 4);
2059 case DBUS_TYPE_INT64:
2060 case DBUS_TYPE_UINT64:
2061 case DBUS_TYPE_DOUBLE:
2062 /* Call validate arg one time to check alignment padding
2065 if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2066 type, array_type_pos, pos, &pos))
2068 pos = _DBUS_ALIGN_VALUE (end, 8);
2072 _dbus_verbose ("Unknown message arg type %d\n", type);
2082 * Validates an argument of a specific type, checking that it
2083 * is well-formed, for example no ludicrous length fields, strings
2084 * are nul-terminated, etc.
2085 * Returns the end position of the argument in end_pos, and
2086 * returns #TRUE if a valid arg begins at "pos"
2088 * @todo security: need to audit this function.
2090 * @param str a string
2091 * @param byte_order the byte order to use
2092 * @param depth current recursion depth, to prevent excessive recursion
2093 * @param type the type of the argument
2094 * @param array_type_pos the position of the current array type, or
2095 * -1 if not in an array
2096 * @param pos the pos where the arg starts
2097 * @param end_pos pointer where the position right
2098 * after the end position will follow
2099 * @returns #TRUE if the arg is valid.
2102 _dbus_marshal_validate_arg (const DBusString *str,
2110 if (pos > _dbus_string_get_length (str))
2112 _dbus_verbose ("Validation went off the end of the message\n");
2116 #define MAX_VALIDATION_DEPTH 32
2118 if (depth > MAX_VALIDATION_DEPTH)
2120 _dbus_verbose ("Maximum recursion depth reached validating message\n");
2126 case DBUS_TYPE_INVALID:
2134 case DBUS_TYPE_BYTE:
2135 if (1 > _dbus_string_get_length (str) - pos)
2137 _dbus_verbose ("no room for byte value\n");
2144 case DBUS_TYPE_BOOLEAN:
2148 if (1 > _dbus_string_get_length (str) - pos)
2150 _dbus_verbose ("no room for boolean value\n");
2154 c = _dbus_string_get_byte (str, pos);
2156 if (!(c == 0 || c == 1))
2158 _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2166 case DBUS_TYPE_INT32:
2167 case DBUS_TYPE_UINT32:
2169 int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
2171 if (!_dbus_string_validate_nul (str, pos,
2174 _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2178 *end_pos = align_4 + 4;
2182 case DBUS_TYPE_INT64:
2183 case DBUS_TYPE_UINT64:
2184 case DBUS_TYPE_DOUBLE:
2186 int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2188 _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2190 if (!_dbus_string_validate_nul (str, pos,
2193 _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
2197 *end_pos = align_8 + 8;
2201 case DBUS_TYPE_OBJECT_PATH:
2202 case DBUS_TYPE_STRING:
2206 /* Demarshal the length, which does NOT include
2209 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2213 if (!validate_string (str, pos, len, end_pos))
2216 if (type == DBUS_TYPE_OBJECT_PATH)
2218 if (!_dbus_string_validate_path (str, pos, len))
2224 case DBUS_TYPE_CUSTOM:
2228 /* Demarshal the string length, which does NOT include
2231 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2235 if (!validate_string (str, pos, len, &pos))
2239 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2243 *end_pos = pos + len;
2247 case DBUS_TYPE_ARRAY:
2253 if (array_type_pos == -1)
2255 array_type_pos = pos;
2259 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2261 _dbus_verbose ("invalid array type\n");
2265 /* NIL values take up no space, so you couldn't iterate over an array of them.
2266 * array of nil seems useless anyway; the useful thing might be array of
2267 * (nil OR string) but we have no framework for that.
2269 if (array_type == DBUS_TYPE_NIL)
2271 _dbus_verbose ("array of NIL is not allowed\n");
2275 while (array_type == DBUS_TYPE_ARRAY);
2280 if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2282 _dbus_verbose ("invalid array type\n");
2286 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2289 _dbus_verbose ("invalid array length (<0)\n");
2293 if (len > _dbus_string_get_length (str) - pos)
2295 _dbus_verbose ("array length outside length of the message\n");
2301 if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
2302 array_type, array_type_pos,
2305 _dbus_verbose ("invalid array data\n");
2311 /* This should not be able to happen, as long as validate_arg moves forward;
2312 * but the check is here just to be paranoid.
2314 _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2321 _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2329 case DBUS_TYPE_DICT:
2335 len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2339 if (len > _dbus_string_get_length (str) - pos)
2341 _dbus_verbose ("dict length outside length of the message\n");
2350 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2351 DBUS_TYPE_STRING, -1, pos, &pos))
2354 if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2356 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2360 /* Validate element */
2361 if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2362 dict_type, -1, pos, &pos))
2364 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
2371 _dbus_verbose ("dict contents exceed stated dict length\n");
2380 _dbus_verbose ("Unknown message arg type %d\n", type);
2384 if (*end_pos > _dbus_string_get_length (str))
2391 * Return #TRUE if the typecode is a valid typecode
2393 * @returns #TRUE if valid
2396 _dbus_type_is_valid (int typecode)
2401 case DBUS_TYPE_BYTE:
2402 case DBUS_TYPE_BOOLEAN:
2403 case DBUS_TYPE_INT32:
2404 case DBUS_TYPE_UINT32:
2405 case DBUS_TYPE_INT64:
2406 case DBUS_TYPE_UINT64:
2407 case DBUS_TYPE_DOUBLE:
2408 case DBUS_TYPE_STRING:
2409 case DBUS_TYPE_CUSTOM:
2410 case DBUS_TYPE_ARRAY:
2411 case DBUS_TYPE_DICT:
2412 case DBUS_TYPE_OBJECT_PATH:
2421 * If in verbose mode, print a block of binary data.
2423 * @todo right now it prints even if not in verbose mode
2425 * @param data the data
2426 * @param len the length of the data
2429 _dbus_verbose_bytes (const unsigned char *data,
2433 const unsigned char *aligned;
2435 _dbus_assert (len >= 0);
2437 /* Print blanks on first row if appropriate */
2438 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2441 _dbus_assert (aligned <= data);
2443 if (aligned != data)
2445 _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
2446 while (aligned != data)
2448 _dbus_verbose (" ");
2453 /* now print the bytes */
2457 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2459 _dbus_verbose ("%4d\t%p: ",
2463 if (data[i] >= 32 &&
2465 _dbus_verbose (" '%c' ", data[i]);
2467 _dbus_verbose ("0x%s%x ",
2468 data[i] <= 0xf ? "0" : "", data[i]);
2472 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2475 _dbus_verbose ("BE: %d LE: %d",
2476 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2477 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2480 _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2482 _dbus_verbose (" dbl: %g",
2483 *(double*)&data[i-8]);
2486 _dbus_verbose ("\n");
2490 _dbus_verbose ("\n");
2494 * Dump the given part of the string to verbose log.
2496 * @param str the string
2497 * @param start the start of range to dump
2498 * @param len length of range
2501 _dbus_verbose_bytes_of_string (const DBusString *str,
2508 real_len = _dbus_string_get_length (str);
2510 _dbus_assert (start >= 0);
2512 if (start > real_len)
2514 _dbus_verbose (" [%d,%d) is not inside string of length %d\n",
2515 start, len, real_len);
2519 if ((start + len) > real_len)
2521 _dbus_verbose (" [%d,%d) extends outside string of length %d\n",
2522 start, len, real_len);
2523 len = real_len - start;
2526 d = _dbus_string_get_const_data_len (str, start, len);
2528 _dbus_verbose_bytes (d, len);
2532 * Marshals a basic type
2534 * @param str string to marshal to
2535 * @param type type of value
2536 * @param value pointer to value
2537 * @param byte_order byte order
2538 * @returns #TRUE on success
2541 _dbus_marshal_basic_type (DBusString *str,
2550 case DBUS_TYPE_BYTE:
2551 case DBUS_TYPE_BOOLEAN:
2552 retval = _dbus_string_append_byte (str, *(unsigned char *)value);
2554 case DBUS_TYPE_INT32:
2555 case DBUS_TYPE_UINT32:
2556 return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
2558 #ifdef DBUS_HAVE_INT64
2559 case DBUS_TYPE_INT64:
2560 case DBUS_TYPE_UINT64:
2561 retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
2563 #endif /* DBUS_HAVE_INT64 */
2564 case DBUS_TYPE_DOUBLE:
2565 retval = _dbus_marshal_double (str, byte_order, *(double *)value);
2568 _dbus_assert_not_reached ("not a basic type");
2576 * Marshals a basic type array
2578 * @param str string to marshal to
2579 * @param element_type type of array elements
2580 * @param value pointer to value
2581 * @param len length of value data in elements
2582 * @param byte_order byte order
2583 * @returns #TRUE on success
2586 _dbus_marshal_basic_type_array (DBusString *str,
2592 switch (element_type)
2594 case DBUS_TYPE_BOOLEAN:
2595 /* FIXME: we canonicalize to 0 or 1 for the single boolean case
2596 * should we here too ? */
2597 case DBUS_TYPE_BYTE:
2598 return _dbus_marshal_byte_array (str, byte_order, value, len);
2600 case DBUS_TYPE_INT32:
2601 case DBUS_TYPE_UINT32:
2602 return marshal_4_octets_array (str, byte_order, value, len);
2604 #ifdef DBUS_HAVE_INT64
2605 case DBUS_TYPE_INT64:
2606 case DBUS_TYPE_UINT64:
2607 #endif /* DBUS_HAVE_INT64 */
2608 case DBUS_TYPE_DOUBLE:
2609 return marshal_8_octets_array (str, byte_order, value, len);
2612 _dbus_assert_not_reached ("non basic type in array");
2620 #ifdef DBUS_BUILD_TESTS
2621 #include "dbus-test.h"
2625 _dbus_marshal_test (void)
2630 dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2631 #ifdef DBUS_HAVE_INT64
2632 dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
2633 DBUS_INT64_CONSTANT (0x456ffffffff),
2634 DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
2639 if (!_dbus_string_init (&str))
2640 _dbus_assert_not_reached ("failed to init string");
2642 /* Marshal doubles */
2643 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2644 _dbus_assert_not_reached ("could not marshal double value");
2645 if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2646 _dbus_assert_not_reached ("demarshal failed");
2648 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2649 _dbus_assert_not_reached ("could not marshal double value");
2650 if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2651 _dbus_assert_not_reached ("demarshal failed");
2653 /* Marshal signed integers */
2654 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2655 _dbus_assert_not_reached ("could not marshal signed integer value");
2656 if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2657 _dbus_assert_not_reached ("demarshal failed");
2659 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2660 _dbus_assert_not_reached ("could not marshal signed integer value");
2661 if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2662 _dbus_assert_not_reached ("demarshal failed");
2664 /* Marshal unsigned integers */
2665 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2666 _dbus_assert_not_reached ("could not marshal signed integer value");
2667 if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2668 _dbus_assert_not_reached ("demarshal failed");
2670 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2671 _dbus_assert_not_reached ("could not marshal signed integer value");
2672 if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2673 _dbus_assert_not_reached ("demarshal failed");
2675 #ifdef DBUS_HAVE_INT64
2676 /* Marshal signed integers */
2677 if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2678 _dbus_assert_not_reached ("could not marshal signed integer value");
2679 if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2680 _dbus_assert_not_reached ("demarshal failed");
2682 if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2683 _dbus_assert_not_reached ("could not marshal signed integer value");
2684 if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2685 _dbus_assert_not_reached ("demarshal failed");
2687 /* Marshal unsigned integers */
2688 if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2689 _dbus_assert_not_reached ("could not marshal signed integer value");
2690 if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2691 _dbus_assert_not_reached ("demarshal failed");
2693 if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2694 _dbus_assert_not_reached ("could not marshal signed integer value");
2695 if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2696 _dbus_assert_not_reached ("demarshal failed");
2697 #endif /* DBUS_HAVE_INT64 */
2699 /* Marshal strings */
2700 tmp1 = "This is the dbus test string";
2701 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2702 _dbus_assert_not_reached ("could not marshal string");
2703 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2704 if (!strcmp (tmp1, tmp2) == 0)
2705 _dbus_assert_not_reached ("demarshal failed");
2708 tmp1 = "This is the dbus test string";
2709 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2710 _dbus_assert_not_reached ("could not marshal string");
2711 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2712 if (!strcmp (tmp1, tmp2) == 0)
2713 _dbus_assert_not_reached ("demarshal failed");
2716 /* Marshal signed integer arrays */
2717 if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2718 _dbus_assert_not_reached ("could not marshal integer array");
2719 if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2720 _dbus_assert_not_reached ("could not demarshal integer array");
2723 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2726 #ifdef DBUS_HAVE_INT64
2727 /* Marshal 64-bit signed integer arrays */
2728 if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2729 _dbus_assert_not_reached ("could not marshal integer array");
2730 if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2731 _dbus_assert_not_reached ("could not demarshal integer array");
2734 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2737 /* set/pack 64-bit integers */
2738 _dbus_string_set_length (&str, 8);
2741 _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2742 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2744 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2745 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2746 _dbus_string_get_const_data (&str)));
2749 _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2750 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2752 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2753 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2754 _dbus_string_get_const_data (&str)));
2756 /* signed little pack */
2757 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2759 _dbus_string_get_data (&str));
2761 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2762 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2763 _dbus_string_get_const_data (&str)));
2765 /* signed big pack */
2766 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2768 _dbus_string_get_data (&str));
2770 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2771 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2772 _dbus_string_get_const_data (&str)));
2774 /* unsigned little */
2775 _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2776 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2778 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2779 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2780 _dbus_string_get_const_data (&str)));
2783 _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2784 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2786 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2787 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2788 _dbus_string_get_const_data (&str)));
2790 /* unsigned little pack */
2791 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2793 _dbus_string_get_data (&str));
2795 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2796 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2797 _dbus_string_get_const_data (&str)));
2799 /* unsigned big pack */
2800 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2802 _dbus_string_get_data (&str));
2804 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2805 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2806 _dbus_string_get_const_data (&str)));
2810 /* set/pack 32-bit integers */
2811 _dbus_string_set_length (&str, 4);
2814 _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2817 _dbus_assert (-0x123456 ==
2818 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2819 _dbus_string_get_const_data (&str)));
2822 _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2825 _dbus_assert (-0x123456 ==
2826 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2827 _dbus_string_get_const_data (&str)));
2829 /* signed little pack */
2830 _dbus_pack_int32 (-0x123456,
2832 _dbus_string_get_data (&str));
2834 _dbus_assert (-0x123456 ==
2835 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2836 _dbus_string_get_const_data (&str)));
2838 /* signed big pack */
2839 _dbus_pack_int32 (-0x123456,
2841 _dbus_string_get_data (&str));
2843 _dbus_assert (-0x123456 ==
2844 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2845 _dbus_string_get_const_data (&str)));
2847 /* unsigned little */
2848 _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2851 _dbus_assert (0x123456 ==
2852 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2853 _dbus_string_get_const_data (&str)));
2856 _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2859 _dbus_assert (0x123456 ==
2860 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2861 _dbus_string_get_const_data (&str)));
2863 /* unsigned little pack */
2864 _dbus_pack_uint32 (0x123456,
2866 _dbus_string_get_data (&str));
2868 _dbus_assert (0x123456 ==
2869 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2870 _dbus_string_get_const_data (&str)));
2872 /* unsigned big pack */
2873 _dbus_pack_uint32 (0x123456,
2875 _dbus_string_get_data (&str));
2877 _dbus_assert (0x123456 ==
2878 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2879 _dbus_string_get_const_data (&str)));
2884 _dbus_string_set_length (&str, 0);
2886 _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2889 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2890 _dbus_assert (strcmp (s, "Hello world") == 0);
2893 _dbus_string_init_const (&t, "Hello world foo");
2895 _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2896 &t, _dbus_string_get_length (&t));
2898 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2899 _dbus_assert (strcmp (s, "Hello world foo") == 0);
2902 _dbus_string_init_const (&t, "Hello");
2904 _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2905 &t, _dbus_string_get_length (&t));
2907 s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2908 _dbus_assert (strcmp (s, "Hello") == 0);
2911 /* Strings (big endian) */
2913 _dbus_string_set_length (&str, 0);
2915 _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2918 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2919 _dbus_assert (strcmp (s, "Hello world") == 0);
2922 _dbus_string_init_const (&t, "Hello world foo");
2924 _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2925 &t, _dbus_string_get_length (&t));
2927 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2928 _dbus_assert (strcmp (s, "Hello world foo") == 0);
2931 _dbus_string_init_const (&t, "Hello");
2933 _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2934 &t, _dbus_string_get_length (&t));
2936 s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2937 _dbus_assert (strcmp (s, "Hello") == 0);
2940 _dbus_string_free (&str);
2945 #endif /* DBUS_BUILD_TESTS */