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))
56 /* This alignment thing is from ORBit2 */
57 /* Align a value upward to a boundary, expressed as a number of bytes.
58 * E.g. align to an 8-byte boundary with argument of 8.
62 * (this + boundary - 1)
67 #define DBUS_ALIGN_VALUE(this, boundary) \
68 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
70 #define DBUS_ALIGN_ADDRESS(this, boundary) \
71 ((void*)DBUS_ALIGN_VALUE(this, boundary))
75 swap_bytes (unsigned char *data,
78 unsigned char *p1 = data;
79 unsigned char *p2 = data + len - 1;
83 unsigned char tmp = *p1;
93 unpack_uint32 (int byte_order,
94 const unsigned char *data)
96 _dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
98 if (byte_order == DBUS_LITTLE_ENDIAN)
99 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
101 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
105 unpack_int32 (int byte_order,
106 const unsigned char *data)
108 _dbus_assert (DBUS_ALIGN_ADDRESS (data, 4) == data);
110 if (byte_order == DBUS_LITTLE_ENDIAN)
111 return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
113 return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
117 * @defgroup DBusMarshal marshaling and unmarshaling
118 * @ingroup DBusInternals
119 * @brief functions to marshal/unmarshal data from the wire
121 * Types and functions related to converting primitive data types from
122 * wire format to native machine format, and vice versa.
128 * Marshals a double value.
130 * @param str the string to append the marshalled value to
131 * @param byte_order the byte order to use
132 * @param value the value
133 * @returns #TRUE on success
136 _dbus_marshal_double (DBusString *str,
140 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
141 swap_bytes ((unsigned char *)&value, sizeof (double));
143 return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
147 * Marshals a 32 bit signed integer value.
149 * @param str the string to append the marshalled value to
150 * @param byte_order the byte order to use
151 * @param value the value
152 * @returns #TRUE on success
155 _dbus_marshal_int32 (DBusString *str,
159 if (!_dbus_string_set_length (str,
160 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
161 sizeof (dbus_int32_t))))
164 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
165 swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
167 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
171 * Marshals a 32 bit unsigned integer value.
173 * @param str the string to append the marshalled value to
174 * @param byte_order the byte order to use
175 * @param value the value
176 * @returns #TRUE on success
179 _dbus_marshal_uint32 (DBusString *str,
183 if (!_dbus_string_set_length (str,
184 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
185 sizeof (dbus_uint32_t))))
188 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
189 swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
191 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
195 * Marshals a UTF-8 string
197 * @param str the string to append the marshalled value to
198 * @param byte_order the byte order to use
199 * @param value the string
200 * @returns #TRUE on success
203 _dbus_marshal_string (DBusString *str,
207 int len, old_string_len;
209 old_string_len = _dbus_string_get_length (str);
211 len = strlen (value);
213 if (!_dbus_marshal_uint32 (str, byte_order, len))
215 /* Restore the previous length */
216 _dbus_string_set_length (str, old_string_len);
221 return _dbus_string_append_len (str, value, len + 1);
225 * Marshals a byte array
227 * @param str the string to append the marshalled value to
228 * @param byte_order the byte order to use
229 * @param value the byte array
230 * @param len the length of the byte array
231 * @returns #TRUE on success
234 _dbus_marshal_byte_array (DBusString *str,
236 const unsigned char *value,
241 old_string_len = _dbus_string_get_length (str);
243 if (!_dbus_marshal_uint32 (str, byte_order, len))
245 /* Restore the previous length */
246 _dbus_string_set_length (str, old_string_len);
251 return _dbus_string_append_len (str, value, len);
255 * Demarshals a double.
257 * @param str the string containing the data
258 * @param byte_order the byte order
259 * @param pos the position in the string
260 * @param new_pos the new position of the string
261 * @returns the demarshaled double.
264 _dbus_demarshal_double (DBusString *str,
272 pos = DBUS_ALIGN_VALUE (pos, sizeof (double));
274 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
276 retval = *(double *)buffer;
278 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
279 swap_bytes ((unsigned char *)&retval, sizeof (double));
282 *new_pos = pos + sizeof (double);
288 * Demarshals a 32 bit signed integer.
290 * @param str the string containing the data
291 * @param byte_order the byte order
292 * @param pos the position in the string
293 * @param new_pos the new position of the string
294 * @returns the demarshaled integer.
297 _dbus_demarshal_int32 (DBusString *str,
304 pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
306 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
309 *new_pos = pos + sizeof (dbus_int32_t);
311 return unpack_int32 (byte_order, buffer);
315 * Demarshals a 32 bit unsigned integer.
317 * @param str the string containing the data
318 * @param byte_order the byte order
319 * @param pos the position in the string
320 * @param new_pos the new position of the string
321 * @returns the demarshaled integer.
324 _dbus_demarshal_uint32 (DBusString *str,
331 pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
333 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
336 *new_pos = pos + sizeof (dbus_uint32_t);
338 return unpack_uint32 (byte_order, buffer);
342 * Demarshals an UTF-8 string.
344 * @todo Should we check the string to make sure
345 * that it's valid UTF-8, and maybe "fix" the string
348 * @param str the string containing the data
349 * @param byte_order the byte order
350 * @param pos the position in the string
351 * @param new_pos the new position of the string
352 * @returns the demarshaled string.
355 _dbus_demarshal_string (DBusString *str,
364 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
366 retval = dbus_malloc (len + 1);
371 _dbus_string_get_const_data_len (str, &data, pos, 3);
376 memcpy (retval, data, len + 1);
379 *new_pos = pos + len + 1;
385 * If in verbose mode, print a block of binary data.
387 * @param data the data
388 * @param len the length of the data
391 _dbus_verbose_bytes (const unsigned char *data,
395 const unsigned char *aligned;
397 /* Print blanks on first row if appropriate */
398 aligned = DBUS_ALIGN_ADDRESS (data, 4);
401 _dbus_assert (aligned <= data);
405 _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
406 while (aligned != data)
413 /* now print the bytes */
417 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
419 _dbus_verbose ("%5d\t%p: ",
425 _dbus_verbose (" '%c' ", data[i]);
427 _dbus_verbose ("0x%s%x ",
428 data[i] <= 0xf ? "0" : "", data[i]);
432 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
435 _dbus_verbose ("big: %d little: %d",
436 unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
437 unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
439 _dbus_verbose ("\n");
443 _dbus_verbose ("\n");
447 * Dump the given part of the string to verbose log.
449 * @param str the string
450 * @param start the start of range to dump
451 * @param len length of range
454 _dbus_verbose_bytes_of_string (const DBusString *str,
460 _dbus_string_get_const_data_len (str, &d, start, len);
462 _dbus_verbose_bytes (d, len);
467 #ifdef DBUS_BUILD_TESTS
468 #include "dbus-test.h"
472 _dbus_marshal_test (void)
478 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
479 _dbus_assert_not_reached ("failed to init string");
482 /* Marshal doubles */
483 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
484 _dbus_assert_not_reached ("could not marshal double value");
485 _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
488 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
489 _dbus_assert_not_reached ("could not marshal double value");
490 _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
492 /* Marshal signed integers */
493 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
494 _dbus_assert_not_reached ("could not marshal signed integer value");
495 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
497 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
498 _dbus_assert_not_reached ("could not marshal signed integer value");
499 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
501 /* Marshal unsigned integers */
502 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
503 _dbus_assert_not_reached ("could not marshal signed integer value");
504 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
506 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
507 _dbus_assert_not_reached ("could not marshal signed integer value");
508 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
510 /* Marshal strings */
511 tmp1 = "This is the dbus test string";
512 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
513 _dbus_assert_not_reached ("could not marshal string");
514 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
515 _dbus_assert (strcmp (tmp1, tmp2) == 0);
518 tmp1 = "This is the dbus test string";
519 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
520 _dbus_assert_not_reached ("could not marshal string");
521 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
522 _dbus_assert (strcmp (tmp1, tmp2) == 0);
525 _dbus_string_free (&str);
530 #endif /* DBUS_BUILD_TESTS */