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 _dbus_marshal_double (DBusString *str,
132 if (!_dbus_string_set_length (str,
133 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
137 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
138 swap_bytes ((unsigned char *)&value, sizeof (double));
140 return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
144 _dbus_marshal_int32 (DBusString *str,
148 if (!_dbus_string_set_length (str,
149 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
150 sizeof (dbus_int32_t))))
153 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
154 swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
156 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
160 _dbus_marshal_uint32 (DBusString *str,
164 if (!_dbus_string_set_length (str,
165 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
166 sizeof (dbus_uint32_t))))
169 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
170 swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
172 return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
176 _dbus_marshal_string (DBusString *str,
182 if (!_dbus_string_set_length (str,
183 DBUS_ALIGN_VALUE (_dbus_string_get_length (str),
184 sizeof (dbus_uint32_t))))
187 len = strlen (value);
189 if (!_dbus_string_lengthen (str, len + 1))
192 if (!_dbus_marshal_uint32 (str, byte_order, len))
195 return _dbus_string_append_len (str, value, len + 1);
200 _dbus_demarshal_double (DBusString *str,
208 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
210 retval = *(double *)buffer;
212 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
213 swap_bytes ((unsigned char *)&retval, sizeof (double));
216 *new_pos = pos + sizeof (double);
222 _dbus_demarshal_int32 (DBusString *str,
229 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
232 *new_pos = pos + sizeof (dbus_int32_t);
234 return unpack_int32 (byte_order, buffer);
238 _dbus_demarshal_uint32 (DBusString *str,
245 _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
248 *new_pos = pos + sizeof (dbus_uint32_t);
250 return unpack_uint32 (byte_order, buffer);
254 _dbus_demarshal_string (DBusString *str,
263 len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
265 retval = dbus_malloc (len + 1);
270 _dbus_string_get_const_data_len (str, &data, pos, len + 1);
275 memcpy (retval, data, len + 1);
278 *new_pos = pos + len + 1;
284 * If in verbose mode, print a block of binary data.
286 * @param data the data
287 * @param len the length of the data
290 _dbus_verbose_bytes (const unsigned char *data,
294 const unsigned char *aligned;
296 /* Print blanks on first row if appropriate */
297 aligned = DBUS_ALIGN_ADDRESS (data, 4);
300 _dbus_assert (aligned <= data);
304 _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned);
305 while (aligned != data)
312 /* now print the bytes */
316 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
318 _dbus_verbose ("%5d\t%p: ",
324 _dbus_verbose (" '%c' ", data[i]);
326 _dbus_verbose ("0x%s%x ",
327 data[i] <= 0xf ? "0" : "", data[i]);
331 if (DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
334 _dbus_verbose ("big: %d little: %d",
335 unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
336 unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
338 _dbus_verbose ("\n");
342 _dbus_verbose ("\n");
347 #ifdef DBUS_BUILD_TESTS
348 #include "dbus-test.h"
352 _dbus_marshal_test (void)
357 if (!_dbus_string_init (&str, _DBUS_INT_MAX))
358 _dbus_assert_not_reached ("failed to init string");
361 /* Marshal doubles */
362 if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
363 _dbus_assert_not_reached ("could not marshal double value");
364 _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
367 if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
368 _dbus_assert_not_reached ("could not marshal double value");
369 _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
371 /* Marshal signed integers */
372 if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
373 _dbus_assert_not_reached ("could not marshal signed integer value");
374 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
376 if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
377 _dbus_assert_not_reached ("could not marshal signed integer value");
378 _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
380 /* Marshal unsigned integers */
381 if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
382 _dbus_assert_not_reached ("could not marshal signed integer value");
383 _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
385 _dbus_string_free (&str);
387 /* FIXME. Add string marshal tests */
392 #endif /* DBUS_BUILD_TESTS */