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 (!_dbus_string_set_length (str,
141 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
145 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
146 swap_bytes ((unsigned char *)&value, sizeof (double));
148 return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
152 * Marshals a 32 bit signed integer value.
154 * @param str the string to append the marshalled value to
155 * @param byte_order the byte order to use
156 * @param value the value
157 * @returns #TRUE on success
160 _dbus_marshal_int32 (DBusString *str,
164 if (!_dbus_string_set_length (str,
165 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
166 sizeof (dbus_int32_t))))
169 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
170 swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
172 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
176 * Marshals a 32 bit unsigned integer value.
178 * @param str the string to append the marshalled value to
179 * @param byte_order the byte order to use
180 * @param value the value
181 * @returns #TRUE on success
184 _dbus_marshal_uint32 (DBusString *str,
188 if (!_dbus_string_set_length (str,
189 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
190 sizeof (dbus_uint32_t))))
193 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
194 swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
196 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
200 * Marshals a UTF-8 string
202 * @param str the string to append the marshalled value to
203 * @param byte_order the byte order to use
204 * @param value the string
205 * @returns #TRUE on success
208 _dbus_marshal_string (DBusString *str,
214 len = strlen (value);
216 if (!_dbus_marshal_uint32 (str, byte_order, len))
219 return _dbus_string_append_len (str, value, len + 1);
223 * Marshals a byte array
225 * @param str the string to append the marshalled value to
226 * @param byte_order the byte order to use
227 * @param value the byte array
228 * @param len the length of the byte array
229 * @returns #TRUE on success
232 _dbus_marshal_byte_array (DBusString *str,
234 const unsigned char *value,
237 if (!_dbus_marshal_uint32 (str, byte_order, len))
240 return _dbus_string_append_len (str, value, len);
244 * Demarshals a double.
246 * @param str the string containing the data
247 * @param byte_order the byte order
248 * @param pos the position in the string
249 * @param new_pos the new position of the string
250 * @returns the demarshaled double.
253 _dbus_demarshal_double (DBusString *str,
261 pos = DBUS_ALIGN_VALUE (pos, sizeof (double));
263 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
265 retval = *(double *)buffer;
267 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
268 swap_bytes ((unsigned char *)&retval, sizeof (double));
271 *new_pos = pos + sizeof (double);
277 * Demarshals a 32 bit signed integer.
279 * @param str the string containing the data
280 * @param byte_order the byte order
281 * @param pos the position in the string
282 * @param new_pos the new position of the string
283 * @returns the demarshaled integer.
286 _dbus_demarshal_int32 (DBusString *str,
293 pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
295 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
298 *new_pos = pos + sizeof (dbus_int32_t);
300 return unpack_int32 (byte_order, buffer);
304 * Demarshals a 32 bit unsigned integer.
306 * @param str the string containing the data
307 * @param byte_order the byte order
308 * @param pos the position in the string
309 * @param new_pos the new position of the string
310 * @returns the demarshaled integer.
313 _dbus_demarshal_uint32 (DBusString *str,
320 pos = DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
322 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
325 *new_pos = pos + sizeof (dbus_uint32_t);
327 return unpack_uint32 (byte_order, buffer);
331 * Demarshals an UTF-8 string.
333 * @todo Should we check the string to make sure
334 * that it's valid UTF-8, and maybe "fix" the string
337 * @param str the string containing the data
338 * @param byte_order the byte order
339 * @param pos the position in the string
340 * @param new_pos the new position of the string
341 * @returns the demarshaled string.
344 _dbus_demarshal_string (DBusString *str,
353 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
355 retval = dbus_malloc (len + 1);
360 _dbus_string_get_const_data_len (str, &data, pos, 3);
365 memcpy (retval, data, len + 1);
368 *new_pos = pos + len + 1;
374 * If in verbose mode, print a block of binary data.
376 * @param data the data
377 * @param len the length of the data
380 _dbus_verbose_bytes (const unsigned char *data,
384 const unsigned char *aligned;
386 /* Print blanks on first row if appropriate */
387 aligned = DBUS_ALIGN_ADDRESS (data, 4);
390 _dbus_assert (aligned <= data);
394 _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
395 while (aligned != data)
402 /* now print the bytes */
406 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
408 _dbus_verbose ("%5d\t%p: ",
414 _dbus_verbose (" '%c' ", data[i]);
416 _dbus_verbose ("0x%s%x ",
417 data[i] <= 0xf ? "0" : "", data[i]);
421 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
424 _dbus_verbose ("big: %d little: %d",
425 unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
426 unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
428 _dbus_verbose ("\n");
432 _dbus_verbose ("\n");
436 * Dump the given part of the string to verbose log.
438 * @param str the string
439 * @param start the start of range to dump
440 * @param len length of range
443 _dbus_verbose_bytes_of_string (const DBusString *str,
449 _dbus_string_get_const_data_len (str, &d, start, len);
451 _dbus_verbose_bytes (d, len);
456 #ifdef DBUS_BUILD_TESTS
457 #include "dbus-test.h"
461 _dbus_marshal_test (void)
467 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
468 _dbus_assert_not_reached ("failed to init string");
471 /* Marshal doubles */
472 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
473 _dbus_assert_not_reached ("could not marshal double value");
474 _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
477 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
478 _dbus_assert_not_reached ("could not marshal double value");
479 _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
481 /* Marshal signed integers */
482 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
483 _dbus_assert_not_reached ("could not marshal signed integer value");
484 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
486 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
487 _dbus_assert_not_reached ("could not marshal signed integer value");
488 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
490 /* Marshal unsigned integers */
491 if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
492 _dbus_assert_not_reached ("could not marshal signed integer value");
493 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
495 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
496 _dbus_assert_not_reached ("could not marshal signed integer value");
497 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
499 /* Marshal strings */
500 tmp1 = "This is the dbus test string";
501 if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
502 _dbus_assert_not_reached ("could not marshal string");
503 tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
504 _dbus_assert (strcmp (tmp1, tmp2) == 0);
507 tmp1 = "This is the dbus test string";
508 if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
509 _dbus_assert_not_reached ("could not marshal string");
510 tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
511 _dbus_assert (strcmp (tmp1, tmp2) == 0);
514 _dbus_string_free (&str);
519 #endif /* DBUS_BUILD_TESTS */