1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal.c Marshalling routines
4 * Copyright (C) 2002 CodeFactory AB
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-marshal.h"
25 #include "dbus-internals.h"
31 swap_bytes (unsigned char *data,
34 unsigned char *p1 = data;
35 unsigned char *p2 = data + len - 1;
39 unsigned char tmp = *p1;
49 * @defgroup DBusMarshal marshaling and unmarshaling
50 * @ingroup DBusInternals
51 * @brief functions to marshal/unmarshal data from the wire
53 * Types and functions related to converting primitive data types from
54 * wire format to native machine format, and vice versa.
60 * Unpacks a 32 bit unsigned integer from a data pointer
62 * @param byte_order The byte order to use
63 * @param data the data pointer
64 * @returns the integer
67 _dbus_unpack_uint32 (int byte_order,
68 const unsigned char *data)
70 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
72 if (byte_order == DBUS_LITTLE_ENDIAN)
73 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
75 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
79 * Unpacks a 32 bit signed integer from a data pointer
81 * @param byte_order The byte order to use
82 * @param data the data pointer
83 * @returns the integer
86 _dbus_unpack_int32 (int byte_order,
87 const unsigned char *data)
89 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
91 if (byte_order == DBUS_LITTLE_ENDIAN)
92 return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
94 return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
98 * Packs a 32 bit unsigned integer into a data pointer.
100 * @param value the value
101 * @param byte_order the byte order to use
102 * @param data the data pointer
105 _dbus_pack_uint32 (dbus_uint32_t value,
109 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
111 if ((byte_order) == DBUS_LITTLE_ENDIAN)
112 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
114 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
118 * Packs a 32 bit signed integer into a data pointer.
120 * @param value the value
121 * @param byte_order the byte order to use
122 * @param data the data pointer
125 _dbus_pack_int32 (dbus_int32_t value,
129 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
131 if ((byte_order) == DBUS_LITTLE_ENDIAN)
132 *((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);
134 *((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
138 * Marshals a double value.
140 * @param str the string to append the marshalled value to
141 * @param byte_order the byte order to use
142 * @param value the value
143 * @returns #TRUE on success
146 _dbus_marshal_double (DBusString *str,
150 _dbus_assert (sizeof (double) == 8);
152 if (!_dbus_string_align_length (str, sizeof (double)))
155 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
156 swap_bytes ((unsigned char *)&value, sizeof (double));
158 return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
162 * Marshals a 32 bit signed integer value.
164 * @param str the string to append the marshalled value to
165 * @param byte_order the byte order to use
166 * @param value the value
167 * @returns #TRUE on success
170 _dbus_marshal_int32 (DBusString *str,
174 if (!_dbus_string_align_length (str, sizeof (dbus_int32_t)))
177 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
178 swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
180 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
184 * Marshals a 32 bit unsigned integer value.
186 * @param str the string to append the marshalled value to
187 * @param byte_order the byte order to use
188 * @param value the value
189 * @returns #TRUE on success
192 _dbus_marshal_uint32 (DBusString *str,
196 if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
199 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
200 swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
202 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
206 * Marshals a UTF-8 string
208 * @param str the string to append the marshalled value to
209 * @param byte_order the byte order to use
210 * @param value the string
211 * @returns #TRUE on success
214 _dbus_marshal_string (DBusString *str,
218 int len, old_string_len;
220 old_string_len = _dbus_string_get_length (str);
222 len = strlen (value);
224 if (!_dbus_marshal_uint32 (str, byte_order, len))
226 /* Restore the previous length */
227 _dbus_string_set_length (str, old_string_len);
232 return _dbus_string_append_len (str, value, len + 1);
236 * Marshals a byte array
238 * @param str the string to append the marshalled value to
239 * @param byte_order the byte order to use
240 * @param value the array
241 * @param len number of elements in the array
242 * @returns #TRUE on success
245 _dbus_marshal_byte_array (DBusString *str,
247 const unsigned char *value,
252 old_string_len = _dbus_string_get_length (str);
254 if (!_dbus_marshal_uint32 (str, byte_order, len))
256 /* Restore the previous length */
257 _dbus_string_set_length (str, old_string_len);
262 return _dbus_string_append_len (str, value, len);
266 * Marshals a 32 bit signed integer array
268 * @param str the string to append the marshalled value to
269 * @param byte_order the byte order to use
270 * @param value the array
271 * @param len the length of the array
272 * @returns #TRUE on success
275 _dbus_marshal_int32_array (DBusString *str,
277 const dbus_int32_t *value,
280 int i, old_string_len;
282 old_string_len = _dbus_string_get_length (str);
284 if (!_dbus_marshal_uint32 (str, byte_order, len))
287 for (i = 0; i < len; i++)
288 if (!_dbus_marshal_int32 (str, byte_order, value[i]))
294 /* Restore previous length */
295 _dbus_string_set_length (str, old_string_len);
301 * Marshals a 32 bit unsigned integer array
303 * @param str the string to append the marshalled value to
304 * @param byte_order the byte order to use
305 * @param value the array
306 * @param len the length of the array
307 * @returns #TRUE on success
310 _dbus_marshal_uint32_array (DBusString *str,
312 const dbus_uint32_t *value,
315 int i, old_string_len;
317 old_string_len = _dbus_string_get_length (str);
319 if (!_dbus_marshal_uint32 (str, byte_order, len))
322 for (i = 0; i < len; i++)
323 if (!_dbus_marshal_uint32 (str, byte_order, value[i]))
329 /* Restore previous length */
330 _dbus_string_set_length (str, old_string_len);
336 * Marshals a double array
338 * @param str the string to append the marshalled value to
339 * @param byte_order the byte order to use
340 * @param value the array
341 * @param len the length of the array
342 * @returns #TRUE on success
345 _dbus_marshal_double_array (DBusString *str,
350 int i, old_string_len;
352 old_string_len = _dbus_string_get_length (str);
354 if (!_dbus_marshal_uint32 (str, byte_order, len))
357 for (i = 0; i < len; i++)
358 if (!_dbus_marshal_double (str, byte_order, value[i]))
364 /* Restore previous length */
365 _dbus_string_set_length (str, old_string_len);
371 * Marshals a string array
373 * @param str the string to append the marshalled value to
374 * @param byte_order the byte order to use
375 * @param value the array
376 * @param len the length of the array
377 * @returns #TRUE on success
380 _dbus_marshal_string_array (DBusString *str,
385 int i, old_string_len;
387 old_string_len = _dbus_string_get_length (str);
389 if (!_dbus_marshal_uint32 (str, byte_order, len))
392 for (i = 0; i < len; i++)
393 if (!_dbus_marshal_string (str, byte_order, value[i]))
399 /* Restore previous length */
400 _dbus_string_set_length (str, old_string_len);
406 * Demarshals a double.
408 * @param str the string containing the data
409 * @param byte_order the byte order
410 * @param pos the position in the string
411 * @param new_pos the new position of the string
412 * @returns the demarshaled double.
415 _dbus_demarshal_double (DBusString *str,
423 pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
425 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
427 retval = *(double *)buffer;
429 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
430 swap_bytes ((unsigned char *)&retval, sizeof (double));
433 *new_pos = pos + sizeof (double);
439 * Demarshals a 32 bit signed integer.
441 * @param str the string containing the data
442 * @param byte_order the byte order
443 * @param pos the position in the string
444 * @param new_pos the new position of the string
445 * @returns the demarshaled integer.
448 _dbus_demarshal_int32 (DBusString *str,
455 pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
457 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
460 *new_pos = pos + sizeof (dbus_int32_t);
462 return _dbus_unpack_int32 (byte_order, buffer);
466 * Demarshals a 32 bit unsigned integer.
468 * @param str the string containing the data
469 * @param byte_order the byte order
470 * @param pos the position in the string
471 * @param new_pos the new position of the string
472 * @returns the demarshaled integer.
475 _dbus_demarshal_uint32 (DBusString *str,
482 pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
484 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
487 *new_pos = pos + sizeof (dbus_uint32_t);
489 return _dbus_unpack_uint32 (byte_order, buffer);
493 * Demarshals an UTF-8 string.
495 * @todo Should we check the string to make sure
496 * that it's valid UTF-8, and maybe "fix" the string
499 * @todo Should probably demarshal to a DBusString,
500 * having memcpy() in here is Evil(tm).
502 * @param str the string containing the data
503 * @param byte_order the byte order
504 * @param pos the position in the string
505 * @param new_pos the new position of the string
506 * @returns the demarshaled string.
509 _dbus_demarshal_string (DBusString *str,
518 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
520 retval = dbus_malloc (len + 1);
525 _dbus_string_get_const_data_len (str, &data, pos, len);
530 memcpy (retval, data, len + 1);
533 *new_pos = pos + len + 1;
539 * Demarshals a byte array.
541 * @todo Should probably demarshal to a DBusString,
542 * having memcpy() in here is Evil(tm).
544 * @param str the string containing the data
545 * @param byte_order the byte order
546 * @param pos the position in the string
547 * @param new_pos the new position of the string
548 * @param array_len length of the demarshaled data
549 * @returns the demarshaled data.
552 _dbus_demarshal_byte_array (DBusString *str,
559 unsigned char *retval;
562 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
564 retval = dbus_malloc (len);
569 _dbus_string_get_const_data_len (str, &data, pos, len);
574 memcpy (retval, data, len);
577 *new_pos = pos + len;
586 * Demarshals a 32 bit signed integer array.
588 * @param str the string containing the data
589 * @param byte_order the byte order
590 * @param pos the position in the string
591 * @param new_pos the new position of the string
592 * @param array_len length of the demarshaled data
593 * @returns the demarshaled data.
596 _dbus_demarshal_int32_array (DBusString *str,
603 dbus_int32_t *retval;
605 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
607 retval = dbus_new (dbus_int32_t, len);
612 for (i = 0; i < len; i++)
613 retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
625 * Demarshals a 32 bit unsigned integer array.
627 * @param str the string containing the data
628 * @param byte_order the byte order
629 * @param pos the position in the string
630 * @param new_pos the new position of the string
631 * @param array_len length of the demarshaled data
632 * @returns the demarshaled data.
635 _dbus_demarshal_uint32_array (DBusString *str,
642 dbus_uint32_t *retval;
644 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
646 retval = dbus_new (dbus_uint32_t, len);
651 for (i = 0; i < len; i++)
652 retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
664 * Demarshals a double array.
666 * @param str the string containing the data
667 * @param byte_order the byte order
668 * @param pos the position in the string
669 * @param new_pos the new position of the string
670 * @param array_len length of the demarshaled data
671 * @returns the demarshaled data.
674 _dbus_demarshal_double_array (DBusString *str,
683 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
685 retval = dbus_new (double, len);
690 for (i = 0; i < len; i++)
691 retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
703 * Demarshals a string array.
705 * @param str the string containing the data
706 * @param byte_order the byte order
707 * @param pos the position in the string
708 * @param new_pos the new position of the string
709 * @param array_len length of the demarshaled data
710 * @returns the demarshaled data.
713 _dbus_demarshal_string_array (DBusString *str,
722 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
724 retval = dbus_new (char *, len);
729 for (i = 0; i < len; i++)
731 retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
746 for (j = 0; j < i; j++)
747 dbus_free (retval[i]);
754 * Returns the position right after the end position
755 * end position of a field
757 * @todo warns on invalid type in a message, but
758 * probably the whole message needs to be dumped,
759 * or we might even drop the connection due
760 * to bad protocol. Needs better error handling.
761 * Possible security issue.
763 * @param str a string
764 * @param byte_order the byte order to use
765 * @param pos the pos where the field starts
766 * @param end_pos pointer where the position right
767 * after the end position will follow
768 * @returns TRUE if more data exists after the field
771 _dbus_marshal_get_field_end_pos (DBusString *str,
778 if (pos >= _dbus_string_get_length (str))
781 _dbus_string_get_const_data_len (str, &data, pos, 1);
785 case DBUS_TYPE_INVALID:
789 case DBUS_TYPE_INT32:
790 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
794 case DBUS_TYPE_UINT32:
795 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
799 case DBUS_TYPE_DOUBLE:
800 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
804 case DBUS_TYPE_STRING:
808 /* Demarshal the length */
809 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
811 *end_pos = pos + len + 1;
816 case DBUS_TYPE_BYTE_ARRAY:
820 /* Demarshal the length */
821 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
823 *end_pos = pos + len;
828 case DBUS_TYPE_INT32_ARRAY:
832 /* Demarshal the length */
833 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
835 *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
836 + (len * sizeof (dbus_int32_t));
841 case DBUS_TYPE_UINT32_ARRAY:
845 /* Demarshal the length */
846 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
848 *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
849 + (len * sizeof (dbus_uint32_t));
854 case DBUS_TYPE_DOUBLE_ARRAY:
858 /* Demarshal the length */
859 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
861 *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
862 + (len * sizeof (double));
867 case DBUS_TYPE_STRING_ARRAY:
871 /* Demarshal the length */
872 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
874 for (i = 0; i < len; i++)
878 /* Demarshal string length */
879 str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
887 _dbus_warn ("Unknown message field type %d\n", *data);
891 if (*end_pos >= _dbus_string_get_length (str))
898 * If in verbose mode, print a block of binary data.
900 * @todo right now it prints even if not in verbose mode
902 * @param data the data
903 * @param len the length of the data
906 _dbus_verbose_bytes (const unsigned char *data,
910 const unsigned char *aligned;
912 /* Print blanks on first row if appropriate */
913 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
916 _dbus_assert (aligned <= data);
920 _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
921 while (aligned != data)
928 /* now print the bytes */
932 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
934 _dbus_verbose ("%5d\t%p: ",
940 _dbus_verbose (" '%c' ", data[i]);
942 _dbus_verbose ("0x%s%x ",
943 data[i] <= 0xf ? "0" : "", data[i]);
947 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
950 _dbus_verbose ("big: %d little: %d",
951 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
952 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
954 _dbus_verbose ("\n");
958 _dbus_verbose ("\n");
962 * Dump the given part of the string to verbose log.
964 * @param str the string
965 * @param start the start of range to dump
966 * @param len length of range
969 _dbus_verbose_bytes_of_string (const DBusString *str,
975 _dbus_string_get_const_data_len (str, &d, start, len);
977 _dbus_verbose_bytes (d, len);
982 #ifdef DBUS_BUILD_TESTS
983 #include "dbus-test.h"
987 _dbus_marshal_test (void)
991 dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
994 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
995 _dbus_assert_not_reached ("failed to init string");
997 /* Marshal doubles */
998 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
999 _dbus_assert_not_reached ("could not marshal double value");
1000 _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
1002 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
1003 _dbus_assert_not_reached ("could not marshal double value");
1004 _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
1006 /* Marshal signed integers */
1007 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1008 _dbus_assert_not_reached ("could not marshal signed integer value");
1009 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
1011 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1012 _dbus_assert_not_reached ("could not marshal signed integer value");
1013 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
1015 /* Marshal unsigned integers */
1016 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1017 _dbus_assert_not_reached ("could not marshal signed integer value");
1018 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
1020 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1021 _dbus_assert_not_reached ("could not marshal signed integer value");
1022 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
1024 /* Marshal strings */
1025 tmp1 = "This is the dbus test string";
1026 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1027 _dbus_assert_not_reached ("could not marshal string");
1028 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1029 _dbus_assert (strcmp (tmp1, tmp2) == 0);
1032 tmp1 = "This is the dbus test string";
1033 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1034 _dbus_assert_not_reached ("could not marshal string");
1035 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1036 _dbus_assert (strcmp (tmp1, tmp2) == 0);
1039 /* Marshal signed integer arrays */
1040 if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1041 _dbus_assert_not_reached ("could not marshal integer array");
1042 array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
1043 printf ("length is: %d\n", len);
1045 _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1050 _dbus_string_free (&str);
1056 #endif /* DBUS_BUILD_TESTS */