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"
29 #define DBUS_UINT32_SWAP_LE_BE_CONSTANT(val) ((dbus_uint32_t) ( \
30 (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x000000ffU) << 24) | \
31 (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x0000ff00U) << 8) | \
32 (((dbus_uint32_t) (val) & (dbus_uint32_t) 0x00ff0000U) >> 8) | \
33 (((dbus_uint32_t) (val) & (dbus_uint32_t) 0xff000000U) >> 24)))
35 #define DBUS_UINT32_SWAP_LE_BE(val) (DBUS_UINT32_SWAP_LE_BE_CONSTANT (val))
37 #ifdef WORDS_BIGENDIAN
38 #define DBUS_INT32_TO_BE(val) ((dbus_int32_t) (val))
39 #define DBUS_UINT32_TO_BE(val) ((dbus_uint32_t) (val))
40 #define DBUS_INT32_TO_LE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
41 #define DBUS_UINT32_TO_LE(val) (DBUS_UINT32_SWAP_LE_BE (val))
43 #define DBUS_INT32_TO_LE(val) ((dbus_int32_t) (val))
44 #define DBUS_UINT32_TO_LE(val) ((dbus_uint32_t) (val))
45 #define DBUS_INT32_TO_BE(val) ((dbus_int32_t) DBUS_UINT32_SWAP_LE_BE (val))
46 #define DBUS_UINT32_TO_BE(val) (DBUS_UINT32_SWAP_LE_BE (val))
49 /* The transformation is symmetric, so the FROM just maps to the TO. */
50 #define DBUS_INT32_FROM_LE(val) (DBUS_INT32_TO_LE (val))
51 #define DBUS_UINT32_FROM_LE(val) (DBUS_UINT32_TO_LE (val))
52 #define DBUS_INT32_FROM_BE(val) (DBUS_INT32_TO_BE (val))
53 #define DBUS_UINT32_FROM_BE(val) (DBUS_UINT32_TO_BE (val))
58 swap_bytes (unsigned char *data,
61 unsigned char *p1 = data;
62 unsigned char *p2 = data + len - 1;
66 unsigned char tmp = *p1;
76 unpack_uint32 (int byte_order,
77 const unsigned char *data)
79 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
81 if (byte_order == DBUS_LITTLE_ENDIAN)
82 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
84 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
88 * Unpacks a 32 bit unsigned integer from a data pointer
90 * @param byte_order The byte order to use
91 * @param data the data pointer
92 * @returns the integer
95 dbus_unpack_int32 (int byte_order,
96 const unsigned char *data)
98 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
100 if (byte_order == DBUS_LITTLE_ENDIAN)
101 return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
103 return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
107 * @defgroup DBusMarshal marshaling and unmarshaling
108 * @ingroup DBusInternals
109 * @brief functions to marshal/unmarshal data from the wire
111 * Types and functions related to converting primitive data types from
112 * wire format to native machine format, and vice versa.
118 * Packs a 32 bit unsigned 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 if (!_dbus_string_set_length (str,
151 _DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
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_set_length (str,
175 _DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
176 sizeof (dbus_int32_t))))
179 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
180 swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
182 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
186 * Marshals a 32 bit unsigned integer value.
188 * @param str the string to append the marshalled value to
189 * @param byte_order the byte order to use
190 * @param value the value
191 * @returns #TRUE on success
194 _dbus_marshal_uint32 (DBusString *str,
198 if (!_dbus_string_set_length (str,
199 _DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
200 sizeof (dbus_uint32_t))))
203 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
204 swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
206 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
210 * Marshals a UTF-8 string
212 * @param str the string to append the marshalled value to
213 * @param byte_order the byte order to use
214 * @param value the string
215 * @returns #TRUE on success
218 _dbus_marshal_string (DBusString *str,
222 int len, old_string_len;
224 old_string_len = _dbus_string_get_length (str);
226 len = strlen (value);
228 if (!_dbus_marshal_uint32 (str, byte_order, len))
230 /* Restore the previous length */
231 _dbus_string_set_length (str, old_string_len);
236 return _dbus_string_append_len (str, value, len + 1);
240 * Marshals a byte array
242 * @param str the string to append the marshalled value to
243 * @param byte_order the byte order to use
244 * @param value the byte array
245 * @param len the length of the byte array
246 * @returns #TRUE on success
249 _dbus_marshal_byte_array (DBusString *str,
251 const unsigned char *value,
256 old_string_len = _dbus_string_get_length (str);
258 if (!_dbus_marshal_uint32 (str, byte_order, len))
260 /* Restore the previous length */
261 _dbus_string_set_length (str, old_string_len);
266 return _dbus_string_append_len (str, value, len);
270 * Demarshals a double.
272 * @param str the string containing the data
273 * @param byte_order the byte order
274 * @param pos the position in the string
275 * @param new_pos the new position of the string
276 * @returns the demarshaled double.
279 _dbus_demarshal_double (DBusString *str,
287 pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
289 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
291 retval = *(double *)buffer;
293 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
294 swap_bytes ((unsigned char *)&retval, sizeof (double));
297 *new_pos = pos + sizeof (double);
303 * Demarshals a 32 bit signed integer.
305 * @param str the string containing the data
306 * @param byte_order the byte order
307 * @param pos the position in the string
308 * @param new_pos the new position of the string
309 * @returns the demarshaled integer.
312 _dbus_demarshal_int32 (DBusString *str,
319 pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
321 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
324 *new_pos = pos + sizeof (dbus_int32_t);
326 return dbus_unpack_int32 (byte_order, buffer);
330 * Demarshals a 32 bit unsigned integer.
332 * @param str the string containing the data
333 * @param byte_order the byte order
334 * @param pos the position in the string
335 * @param new_pos the new position of the string
336 * @returns the demarshaled integer.
339 _dbus_demarshal_uint32 (DBusString *str,
346 pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
348 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
351 *new_pos = pos + sizeof (dbus_uint32_t);
353 return unpack_uint32 (byte_order, buffer);
357 * Demarshals an UTF-8 string.
359 * @todo Should we check the string to make sure
360 * that it's valid UTF-8, and maybe "fix" the string
363 * @param str the string containing the data
364 * @param byte_order the byte order
365 * @param pos the position in the string
366 * @param new_pos the new position of the string
367 * @returns the demarshaled string.
370 _dbus_demarshal_string (DBusString *str,
379 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
381 retval = dbus_malloc (len + 1);
386 _dbus_string_get_const_data_len (str, &data, pos, len);
391 memcpy (retval, data, len + 1);
394 *new_pos = pos + len + 1;
400 _dbus_demarshal_byte_array (DBusString *str,
407 unsigned char *retval;
410 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
412 retval = dbus_malloc (len);
417 _dbus_string_get_const_data_len (str, &data, pos, len);
422 memcpy (retval, data, len);
425 *new_pos = pos + len;
434 * Returns the position right after the end position
435 * end position of a field
437 * @param str a string
438 * @param byte_order the byte order to use
439 * @param pos the pos where the field starts
440 * @param end_pos pointer where the position right
441 * after the end position will follow
442 * @returns TRUE if more data exists after the field
445 _dbus_marshal_get_field_end_pos (DBusString *str,
452 if (pos >= _dbus_string_get_length (str))
455 _dbus_string_get_const_data_len (str, &data, pos, 1);
459 case DBUS_TYPE_INVALID:
463 case DBUS_TYPE_INT32:
464 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
468 case DBUS_TYPE_UINT32:
469 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
473 case DBUS_TYPE_DOUBLE:
474 *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
478 case DBUS_TYPE_STRING:
482 /* Demarshal the length */
483 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
485 *end_pos = new_pos + len + 1;
490 case DBUS_TYPE_BYTE_ARRAY:
494 /* Demarshal the length */
495 len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
497 *end_pos = new_pos + len;
503 _dbus_warn ("Unknown message field type %d\n", *data);
507 if (*end_pos >= _dbus_string_get_length (str))
514 * If in verbose mode, print a block of binary data.
516 * @todo right now it prints even if not in verbose mode
518 * @param data the data
519 * @param len the length of the data
522 _dbus_verbose_bytes (const unsigned char *data,
526 const unsigned char *aligned;
528 /* Print blanks on first row if appropriate */
529 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
532 _dbus_assert (aligned <= data);
536 _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
537 while (aligned != data)
544 /* now print the bytes */
548 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
550 _dbus_verbose ("%5d\t%p: ",
556 _dbus_verbose (" '%c' ", data[i]);
558 _dbus_verbose ("0x%s%x ",
559 data[i] <= 0xf ? "0" : "", data[i]);
563 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
566 _dbus_verbose ("big: %d little: %d",
567 unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
568 unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
570 _dbus_verbose ("\n");
574 _dbus_verbose ("\n");
578 * Dump the given part of the string to verbose log.
580 * @param str the string
581 * @param start the start of range to dump
582 * @param len length of range
585 _dbus_verbose_bytes_of_string (const DBusString *str,
591 _dbus_string_get_const_data_len (str, &d, start, len);
593 _dbus_verbose_bytes (d, len);
598 #ifdef DBUS_BUILD_TESTS
599 #include "dbus-test.h"
603 _dbus_marshal_test (void)
609 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
610 _dbus_assert_not_reached ("failed to init string");
613 /* Marshal doubles */
614 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
615 _dbus_assert_not_reached ("could not marshal double value");
616 _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
618 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
619 _dbus_assert_not_reached ("could not marshal double value");
620 _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
622 /* Marshal signed integers */
623 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
624 _dbus_assert_not_reached ("could not marshal signed integer value");
625 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
627 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
628 _dbus_assert_not_reached ("could not marshal signed integer value");
629 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
631 /* Marshal unsigned integers */
632 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
633 _dbus_assert_not_reached ("could not marshal signed integer value");
634 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
636 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
637 _dbus_assert_not_reached ("could not marshal signed integer value");
638 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
640 /* Marshal strings */
641 tmp1 = "This is the dbus test string";
642 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
643 _dbus_assert_not_reached ("could not marshal string");
644 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
645 _dbus_assert (strcmp (tmp1, tmp2) == 0);
648 tmp1 = "This is the dbus test string";
649 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
650 _dbus_assert_not_reached ("could not marshal string");
651 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
652 _dbus_assert (strcmp (tmp1, tmp2) == 0);
655 _dbus_string_free (&str);
660 #endif /* DBUS_BUILD_TESTS */