2005-02-06 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-marshal-basic.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-marshal-basic.c  Marshalling routines for basic (primitive) types
3  *
4  * Copyright (C) 2002 CodeFactory AB
5  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal-basic.h"
27
28 #include <string.h>
29
30 /**
31  * @defgroup DBusMarshal marshaling and unmarshaling
32  * @ingroup  DBusInternals
33  * @brief functions to marshal/unmarshal data from the wire
34  *
35  * Types and functions related to converting primitive data types from
36  * wire format to native machine format, and vice versa.
37  *
38  * A signature is just a string with multiple types one after the other.
39  * for example a type is "i" or "(ii)", a signature is "i(ii)"
40  * where i is int and (ii) is struct { int; int; }
41  *
42  * @{
43  */
44
45 static void
46 pack_2_octets (dbus_uint16_t   value,
47                int             byte_order,
48                unsigned char  *data)
49 {
50   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
51
52   if ((byte_order) == DBUS_LITTLE_ENDIAN)
53     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
54   else
55     *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
56 }
57
58 static void
59 pack_4_octets (dbus_uint32_t   value,
60                int             byte_order,
61                unsigned char  *data)
62 {
63   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
64
65   if ((byte_order) == DBUS_LITTLE_ENDIAN)
66     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
67   else
68     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
69 }
70
71 static void
72 pack_8_octets (DBusBasicValue     value,
73                int                byte_order,
74                unsigned char     *data)
75 {
76   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
77
78 #ifdef DBUS_HAVE_INT64
79   if ((byte_order) == DBUS_LITTLE_ENDIAN)
80     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
81   else
82     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
83 #else
84   *(DBus8ByteStruct*)data = value.u64;
85   swap_8_octets ((DBusBasicValue*)data, byte_order);
86 #endif
87 }
88
89 /**
90  * Packs a 32 bit unsigned integer into a data pointer.
91  *
92  * @param value the value
93  * @param byte_order the byte order to use
94  * @param data the data pointer
95  */
96 void
97 _dbus_pack_uint32 (dbus_uint32_t   value,
98                    int             byte_order,
99                    unsigned char  *data)
100 {
101   pack_4_octets (value, byte_order, data);
102 }
103
104 #ifndef DBUS_HAVE_INT64
105 /* from ORBit */
106 static void
107 swap_bytes (unsigned char *data,
108             unsigned int   len)
109 {
110   unsigned char *p1 = data;
111   unsigned char *p2 = data + len - 1;
112
113   while (p1 < p2)
114     {
115       unsigned char tmp = *p1;
116       *p1 = *p2;
117       *p2 = tmp;
118
119       --p2;
120       ++p1;
121     }
122 }
123 #endif /* !DBUS_HAVE_INT64 */
124
125 static void
126 swap_8_octets (DBusBasicValue    *value,
127                int                byte_order)
128 {
129   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
130     {
131 #ifdef DBUS_HAVE_INT64
132       value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
133 #else
134       swap_bytes ((unsigned char *)value, 8);
135 #endif
136     }
137 }
138
139 #if 0
140 static DBusBasicValue
141 unpack_8_octets (int                  byte_order,
142                  const unsigned char *data)
143 {
144   DBusBasicValue r;
145
146   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
147   _dbus_assert (sizeof (r) == 8);
148
149 #ifdef DBUS_HAVE_INT64
150   if (byte_order == DBUS_LITTLE_ENDIAN)
151     r.u64 = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
152   else
153     r.u64 = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
154 #else
155   r.u64 = *(DBus8ByteStruct*)data;
156   swap_8_octets (&r, byte_order);
157 #endif
158
159   return r;
160 }
161 #endif
162
163 #ifndef _dbus_unpack_uint16
164 /**
165  * Unpacks a 16 bit unsigned integer from a data pointer
166  *
167  * @param byte_order The byte order to use
168  * @param data the data pointer
169  * @returns the integer
170  */
171 dbus_uint16_t
172 _dbus_unpack_uint16 (int                  byte_order,
173                      const unsigned char *data)
174 {
175   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
176
177   if (byte_order == DBUS_LITTLE_ENDIAN)
178     return DBUS_UINT16_FROM_LE (*(dbus_uint16_t*)data);
179   else
180     return DBUS_UINT16_FROM_BE (*(dbus_uint16_t*)data);
181 }
182 #endif /* _dbus_unpack_uint16 */
183
184 #ifndef _dbus_unpack_uint32
185 /**
186  * Unpacks a 32 bit unsigned integer from a data pointer
187  *
188  * @param byte_order The byte order to use
189  * @param data the data pointer
190  * @returns the integer
191  */
192 dbus_uint32_t
193 _dbus_unpack_uint32 (int                  byte_order,
194                      const unsigned char *data)
195 {
196   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
197
198   if (byte_order == DBUS_LITTLE_ENDIAN)
199     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
200   else
201     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
202 }
203 #endif /* _dbus_unpack_uint32 */
204
205 static void
206 set_2_octets (DBusString          *str,
207               int                  offset,
208               dbus_uint16_t        value,
209               int                  byte_order)
210 {
211   char *data;
212
213   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
214                 byte_order == DBUS_BIG_ENDIAN);
215
216   data = _dbus_string_get_data_len (str, offset, 2);
217
218   pack_2_octets (value, byte_order, data);
219 }
220
221 static void
222 set_4_octets (DBusString          *str,
223               int                  offset,
224               dbus_uint32_t        value,
225               int                  byte_order)
226 {
227   char *data;
228
229   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
230                 byte_order == DBUS_BIG_ENDIAN);
231
232   data = _dbus_string_get_data_len (str, offset, 4);
233
234   pack_4_octets (value, byte_order, data);
235 }
236
237 static void
238 set_8_octets (DBusString          *str,
239               int                  offset,
240               DBusBasicValue       value,
241               int                  byte_order)
242 {
243   char *data;
244
245   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
246                 byte_order == DBUS_BIG_ENDIAN);
247
248   data = _dbus_string_get_data_len (str, offset, 8);
249
250   pack_8_octets (value, byte_order, data);
251 }
252
253 /**
254  * Sets the 4 bytes at the given offset to a marshaled unsigned
255  * integer, replacing anything found there previously.
256  *
257  * @param str the string to write the marshalled int to
258  * @param pos the byte offset where int should be written
259  * @param value the value
260  * @param byte_order the byte order to use
261  *
262  */
263 void
264 _dbus_marshal_set_uint32 (DBusString          *str,
265                           int                  pos,
266                           dbus_uint32_t        value,
267                           int                  byte_order)
268 {
269   set_4_octets (str, pos, value, byte_order);
270 }
271
272 /**
273  * Sets the existing marshaled string at the given offset with
274  * a new marshaled string. The given offset must point to
275  * an existing string or the wrong length will be deleted
276  * and replaced with the new string.
277  *
278  * Note: no attempt is made by this function to re-align
279  * any data which has been already marshalled after this
280  * string. Use with caution.
281  *
282  * @param str the string to write the marshalled string to
283  * @param pos the position of the marshaled string length
284  * @param value the value
285  * @param byte_order the byte order to use
286  * @param old_end_pos place to store byte after the nul byte of the old value
287  * @param new_end_pos place to store byte after the nul byte of the new value
288  * @returns #TRUE on success, #FALSE if no memory
289  *
290  */
291 static dbus_bool_t
292 set_string (DBusString          *str,
293             int                  pos,
294             const char          *value,
295             int                  byte_order,
296             int                 *old_end_pos,
297             int                 *new_end_pos)
298 {
299   int old_len, new_len;
300   DBusString dstr;
301
302   _dbus_string_init_const (&dstr, value);
303
304   _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
305   old_len = _dbus_unpack_uint32 (byte_order,
306                                  _dbus_string_get_const_data_len (str, pos, 4));
307
308   new_len = _dbus_string_get_length (&dstr);
309
310   if (!_dbus_string_replace_len (&dstr, 0, new_len,
311                                  str, pos + 4, old_len))
312     return FALSE;
313
314   _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
315
316   if (old_end_pos)
317     *old_end_pos = pos + 4 + old_len + 1;
318   if (new_end_pos)
319     *new_end_pos = pos + 4 + new_len + 1;
320
321   return TRUE;
322 }
323
324 /**
325  * Sets the existing marshaled signature at the given offset to a new
326  * marshaled signature. Same basic ideas as set_string().
327  *
328  * @param str the string to write the marshalled signature to
329  * @param pos the position of the marshaled signature length
330  * @param value the value
331  * @param byte_order the byte order to use
332  * @param old_end_pos place to store byte after the nul byte of the old value
333  * @param new_end_pos place to store byte after the nul byte of the new value
334  * @returns #TRUE on success, #FALSE if no memory
335  *
336  */
337 static dbus_bool_t
338 set_signature (DBusString          *str,
339                int                  pos,
340                const char          *value,
341                int                  byte_order,
342                int                 *old_end_pos,
343                int                 *new_end_pos)
344 {
345   int old_len, new_len;
346   DBusString dstr;
347
348   _dbus_string_init_const (&dstr, value);
349
350   old_len = _dbus_string_get_byte (str, pos);
351   new_len = _dbus_string_get_length (&dstr);
352
353   if (!_dbus_string_replace_len (&dstr, 0, new_len,
354                                  str, pos + 1, old_len))
355     return FALSE;
356
357   _dbus_string_set_byte (str, pos, new_len);
358
359   if (old_end_pos)
360     *old_end_pos = pos + 1 + old_len + 1;
361   if (new_end_pos)
362     *new_end_pos = pos + 1 + new_len + 1;
363
364   return TRUE;
365 }
366
367 /**
368  * Sets an existing basic type value to a new value.
369  * Arguments work the same way as _dbus_marshal_basic_type().
370  *
371  * @param str the string
372  * @param pos location of the current value
373  * @param type the type of the current and new values
374  * @param value the address of the new value
375  * @param byte_order byte order for marshaling
376  * @param old_end_pos location to store end position of the old value, or #NULL
377  * @param new_end_pos location to store end position of the new value, or #NULL
378  * @returns #FALSE if no memory
379  */
380 dbus_bool_t
381 _dbus_marshal_set_basic (DBusString       *str,
382                          int               pos,
383                          int               type,
384                          const void       *value,
385                          int               byte_order,
386                          int              *old_end_pos,
387                          int              *new_end_pos)
388 {
389   const DBusBasicValue *vp;
390
391   vp = value;
392
393   switch (type)
394     {
395     case DBUS_TYPE_BYTE:
396       _dbus_string_set_byte (str, pos, vp->byt);
397       if (old_end_pos)
398         *old_end_pos = pos + 1;
399       if (new_end_pos)
400         *new_end_pos = pos + 1;
401       return TRUE;
402       break;
403     case DBUS_TYPE_INT16:
404     case DBUS_TYPE_UINT16:
405       pos = _DBUS_ALIGN_VALUE (pos, 2);
406       set_2_octets (str, pos, vp->u16, byte_order);
407       if (old_end_pos)
408         *old_end_pos = pos + 2;
409       if (new_end_pos)
410         *new_end_pos = pos + 2;
411       return TRUE;
412       break;
413     case DBUS_TYPE_BOOLEAN:
414     case DBUS_TYPE_INT32:
415     case DBUS_TYPE_UINT32:
416       pos = _DBUS_ALIGN_VALUE (pos, 4);
417       set_4_octets (str, pos, vp->u32, byte_order);
418       if (old_end_pos)
419         *old_end_pos = pos + 4;
420       if (new_end_pos)
421         *new_end_pos = pos + 4;
422       return TRUE;
423       break;
424     case DBUS_TYPE_INT64:
425     case DBUS_TYPE_UINT64:
426     case DBUS_TYPE_DOUBLE:
427       pos = _DBUS_ALIGN_VALUE (pos, 8);
428       set_8_octets (str, pos, *vp, byte_order);
429       if (old_end_pos)
430         *old_end_pos = pos + 8;
431       if (new_end_pos)
432         *new_end_pos = pos + 8;
433       return TRUE;
434       break;
435     case DBUS_TYPE_STRING:
436     case DBUS_TYPE_OBJECT_PATH:
437       pos = _DBUS_ALIGN_VALUE (pos, 4);
438       _dbus_assert (vp->str != NULL);
439       return set_string (str, pos, vp->str, byte_order,
440                          old_end_pos, new_end_pos);
441       break;
442     case DBUS_TYPE_SIGNATURE:
443       _dbus_assert (vp->str != NULL);
444       return set_signature (str, pos, vp->str, byte_order,
445                             old_end_pos, new_end_pos);
446       break;
447     default:
448       _dbus_assert_not_reached ("not a basic type");
449       return FALSE;
450       break;
451     }
452 }
453
454 /**
455  * Convenience function to demarshal a 32 bit unsigned integer.
456  *
457  * @param str the string containing the data
458  * @param byte_order the byte order
459  * @param pos the position in the string
460  * @param new_pos the new position of the string
461  * @returns the demarshaled integer.
462  */
463 dbus_uint32_t
464 _dbus_marshal_read_uint32  (const DBusString *str,
465                             int               pos,
466                             int               byte_order,
467                             int              *new_pos)
468 {
469   pos = _DBUS_ALIGN_VALUE (pos, 4);
470
471   if (new_pos)
472     *new_pos = pos + 4;
473
474   _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
475   
476   return _dbus_unpack_uint32 (byte_order,
477                               _dbus_string_get_const_data (str) + pos);
478 }
479
480 /**
481  * Demarshals a basic-typed value. The "value" pointer is always
482  * the address of a variable of the basic type. So e.g.
483  * if the basic type is "double" then the pointer is
484  * a double*, and if it's "char*" then the pointer is
485  * a "char**".
486  *
487  * A value of type #DBusBasicValue is guaranteed to be large enough to
488  * hold any of the types that may be returned, which is handy if you
489  * are trying to do things generically. For example you can pass
490  * a DBusBasicValue* in to this function, and then pass the same
491  * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
492  * move a value from one place to another.
493  *
494  * @param str the string containing the data
495  * @param pos position in the string
496  * @param type type of value to demarshal
497  * @param value pointer to return value data
498  * @param byte_order the byte order
499  * @param new_pos pointer to update with new position, or #NULL
500  **/
501 void
502 _dbus_marshal_read_basic (const DBusString      *str,
503                           int                    pos,
504                           int                    type,
505                           void                  *value,
506                           int                    byte_order,
507                           int                   *new_pos)
508 {
509   const char *str_data;
510   DBusBasicValue *vp;
511
512   _dbus_assert (_dbus_type_is_basic (type));
513
514   str_data = _dbus_string_get_const_data (str);
515   vp = value;
516
517   switch (type)
518     {
519     case DBUS_TYPE_BYTE:
520       vp->byt = _dbus_string_get_byte (str, pos);
521       (pos)++;
522       break;
523     case DBUS_TYPE_INT16:
524     case DBUS_TYPE_UINT16:
525       pos = _DBUS_ALIGN_VALUE (pos, 2);
526       vp->u16 = *(dbus_uint16_t *)(str_data + pos);
527       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
528         vp->u16 = DBUS_UINT16_SWAP_LE_BE (vp->u16);
529       pos += 2;
530       break;
531     case DBUS_TYPE_INT32:
532     case DBUS_TYPE_UINT32:
533     case DBUS_TYPE_BOOLEAN:
534       pos = _DBUS_ALIGN_VALUE (pos, 4);
535       vp->u32 = *(dbus_uint32_t *)(str_data + pos);
536       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
537         vp->u32 = DBUS_UINT32_SWAP_LE_BE (vp->u32);
538       pos += 4;
539       break;
540     case DBUS_TYPE_INT64:
541     case DBUS_TYPE_UINT64:
542     case DBUS_TYPE_DOUBLE:
543       pos = _DBUS_ALIGN_VALUE (pos, 8);
544 #ifdef DBUS_HAVE_INT64
545       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
546         vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t*)(str_data + pos));
547       else
548         vp->u64 = *(dbus_uint64_t*)(str_data + pos);
549 #else
550       vp->u64 = *(DBus8ByteStruct*) (str_data + pos);
551       swap_8_octets (vp, byte_order);
552 #endif
553       pos += 8;
554       break;
555     case DBUS_TYPE_STRING:
556     case DBUS_TYPE_OBJECT_PATH:
557       {
558         int len;
559
560         len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
561
562         vp->str = (char*) str_data + pos;
563
564         pos += len + 1; /* length plus nul */
565       }
566       break;
567     case DBUS_TYPE_SIGNATURE:
568       {
569         int len;
570
571         len = _dbus_string_get_byte (str, pos);
572         pos += 1;
573
574         vp->str = (char*) str_data + pos;
575
576         pos += len + 1; /* length plus nul */
577       }
578       break;
579     default:
580       _dbus_warn ("type %s %d not a basic type\n",
581                   _dbus_type_to_string (type), type);
582       _dbus_assert_not_reached ("not a basic type");
583       break;
584     }
585
586   if (new_pos)
587     *new_pos = pos;
588 }
589
590 /**
591  * Reads a block of fixed-length basic values, as an optimization
592  * vs. reading each one individually into a new buffer.
593  *
594  * This function returns the data in-place; it does not make a copy,
595  * and it does not swap the bytes.
596  *
597  * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
598  * and the "value" argument should be a "const double**" and so on.
599  *
600  * @todo we aren't using this function (except in the test suite)
601  * 
602  * @param str the string to read from
603  * @param pos position to read from
604  * @param element_type type of array elements
605  * @param value place to return the array
606  * @param n_elements number of array elements to read
607  * @param byte_order the byte order, used to read the array length
608  * @param new_pos #NULL or location to store a position after the elements
609  */
610 void
611 _dbus_marshal_read_fixed_multi  (const DBusString *str,
612                                  int               pos,
613                                  int               element_type,
614                                  void             *value,
615                                  int               n_elements,
616                                  int               byte_order,
617                                  int              *new_pos)
618 {
619   int array_len;
620   int alignment;
621
622   _dbus_assert (_dbus_type_is_fixed (element_type));
623   _dbus_assert (_dbus_type_is_basic (element_type));
624
625 #if 0
626   _dbus_verbose ("reading %d elements of %s\n",
627                  n_elements, _dbus_type_to_string (element_type));
628 #endif
629   
630   alignment = _dbus_type_get_alignment (element_type);
631
632   pos = _DBUS_ALIGN_VALUE (pos, alignment);
633   
634   array_len = n_elements * alignment;
635
636   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
637   if (new_pos)
638     *new_pos = pos + array_len;
639 }
640
641 static dbus_bool_t
642 marshal_2_octets (DBusString   *str,
643                   int           insert_at,
644                   dbus_uint16_t value,
645                   int           byte_order,
646                   int          *pos_after)
647 {
648   dbus_bool_t retval;
649   int orig_len;
650
651   _dbus_assert (sizeof (value) == 2);
652
653   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
654     value = DBUS_UINT16_SWAP_LE_BE (value);
655
656   orig_len = _dbus_string_get_length (str);
657
658   retval = _dbus_string_insert_2_aligned (str, insert_at,
659                                           (const unsigned char *)&value);
660
661   if (pos_after)
662     {
663       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
664       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
665     }
666
667   return retval;
668 }
669
670 static dbus_bool_t
671 marshal_4_octets (DBusString   *str,
672                   int           insert_at,
673                   dbus_uint32_t value,
674                   int           byte_order,
675                   int          *pos_after)
676 {
677   dbus_bool_t retval;
678   int orig_len;
679
680   _dbus_assert (sizeof (value) == 4);
681
682   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
683     value = DBUS_UINT32_SWAP_LE_BE (value);
684
685   orig_len = _dbus_string_get_length (str);
686
687   retval = _dbus_string_insert_4_aligned (str, insert_at,
688                                           (const unsigned char *)&value);
689
690   if (pos_after)
691     {
692       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
693       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
694     }
695
696   return retval;
697 }
698
699 static dbus_bool_t
700 marshal_8_octets (DBusString    *str,
701                   int            insert_at,
702                   DBusBasicValue value,
703                   int            byte_order,
704                   int           *pos_after)
705 {
706   dbus_bool_t retval;
707   int orig_len;
708
709   _dbus_assert (sizeof (value) == 8);
710
711   swap_8_octets (&value, byte_order);
712
713   orig_len = _dbus_string_get_length (str);
714
715   retval = _dbus_string_insert_8_aligned (str, insert_at,
716                                           (const unsigned char *)&value);
717
718   if (pos_after)
719     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
720
721   return retval;
722 }
723
724 enum
725   {
726     MARSHAL_AS_STRING,
727     MARSHAL_AS_SIGNATURE,
728     MARSHAL_AS_BYTE_ARRAY
729   };
730
731 static dbus_bool_t
732 marshal_len_followed_by_bytes (int                  marshal_as,
733                                DBusString          *str,
734                                int                  insert_at,
735                                const unsigned char *value,
736                                int                  data_len, /* doesn't include nul if any */
737                                int                  byte_order,
738                                int                 *pos_after)
739 {
740   int pos;
741   DBusString value_str;
742   int value_len;
743
744   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
745   if (insert_at > _dbus_string_get_length (str))
746     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
747                 insert_at, _dbus_string_get_length (str), data_len);
748   
749   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
750     value_len = data_len;
751   else
752     value_len = data_len + 1; /* value has a nul */
753
754   _dbus_string_init_const_len (&value_str, value, value_len);
755
756   pos = insert_at;
757
758   if (marshal_as == MARSHAL_AS_SIGNATURE)
759     {
760       _dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
761       _dbus_assert (data_len <= 255); /* same as max sig len right now */
762       
763       if (!_dbus_string_insert_byte (str, pos, data_len))
764         goto oom;
765
766       pos += 1;
767     }
768   else
769     {
770       if (!marshal_4_octets (str, pos, data_len,
771                              byte_order, &pos))
772         goto oom;
773     }
774
775   if (!_dbus_string_copy_len (&value_str, 0, value_len,
776                               str, pos))
777     goto oom;
778
779 #if 0
780   /* too expensive */
781   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
782                                               str, pos));
783   _dbus_verbose_bytes_of_string (str, pos, value_len);
784 #endif
785
786   pos += value_len;
787
788   if (pos_after)
789     *pos_after = pos;
790
791   return TRUE;
792
793  oom:
794   /* Delete what we've inserted */
795   _dbus_string_delete (str, insert_at, pos - insert_at);
796
797   return FALSE;
798 }
799
800 static dbus_bool_t
801 marshal_string (DBusString    *str,
802                 int            insert_at,
803                 const char    *value,
804                 int            byte_order,
805                 int           *pos_after)
806 {
807   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
808                                         str, insert_at, value,
809                                         strlen (value),
810                                         byte_order, pos_after);
811 }
812
813 static dbus_bool_t
814 marshal_signature (DBusString    *str,
815                    int            insert_at,
816                    const char    *value,
817                    int           *pos_after)
818 {
819   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
820                                         str, insert_at, value,
821                                         strlen (value),
822                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
823                                         pos_after);
824 }
825
826 /**
827  * Marshals a basic-typed value. The "value" pointer is always the
828  * address of a variable containing the basic type value.
829  * So for example for int32 it will be dbus_int32_t*, and
830  * for string it will be const char**. This is for symmetry
831  * with _dbus_marshal_read_basic() and to have a simple
832  * consistent rule.
833  *
834  * @param str string to marshal to
835  * @param insert_at where to insert the value
836  * @param type type of value
837  * @param value pointer to a variable containing the value
838  * @param byte_order byte order
839  * @param pos_after #NULL or the position after the type
840  * @returns #TRUE on success
841  **/
842 dbus_bool_t
843 _dbus_marshal_write_basic (DBusString *str,
844                            int         insert_at,
845                            int         type,
846                            const void *value,
847                            int         byte_order,
848                            int        *pos_after)
849 {
850   const DBusBasicValue *vp;
851
852   _dbus_assert (_dbus_type_is_basic (type));
853
854   vp = value;
855
856   switch (type)
857     {
858     case DBUS_TYPE_BYTE:
859       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
860         return FALSE;
861       if (pos_after)
862         *pos_after = insert_at + 1;
863       return TRUE;
864       break;
865     case DBUS_TYPE_INT16:
866     case DBUS_TYPE_UINT16:
867       return marshal_2_octets (str, insert_at, vp->u16,
868                                byte_order, pos_after);
869       break;
870     case DBUS_TYPE_BOOLEAN:
871       return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
872                                byte_order, pos_after);
873       break;
874     case DBUS_TYPE_INT32:
875     case DBUS_TYPE_UINT32:
876       return marshal_4_octets (str, insert_at, vp->u32,
877                                byte_order, pos_after);
878       break;
879     case DBUS_TYPE_INT64:
880     case DBUS_TYPE_UINT64:
881     case DBUS_TYPE_DOUBLE:
882       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
883       break;
884
885     case DBUS_TYPE_STRING:
886     case DBUS_TYPE_OBJECT_PATH:
887       _dbus_assert (vp->str != NULL);
888       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
889       break;
890     case DBUS_TYPE_SIGNATURE:
891       _dbus_assert (vp->str != NULL);
892       return marshal_signature (str, insert_at, vp->str, pos_after);
893       break;
894     default:
895       _dbus_assert_not_reached ("not a basic type");
896       return FALSE;
897       break;
898     }
899 }
900
901 static dbus_bool_t
902 marshal_1_octets_array (DBusString          *str,
903                         int                  insert_at,
904                         const unsigned char *value,
905                         int                  n_elements,
906                         int                  byte_order,
907                         int                 *pos_after)
908 {
909   int pos;
910   DBusString value_str;
911
912   _dbus_string_init_const_len (&value_str, value, n_elements);
913
914   pos = insert_at;
915
916   if (!_dbus_string_copy_len (&value_str, 0, n_elements,
917                               str, pos))
918     return FALSE;
919
920   pos += n_elements;
921
922   if (pos_after)
923     *pos_after = pos;
924
925   return TRUE;
926 }
927
928 /**
929  * Swaps the elements of an array to the opposite byte order
930  *
931  * @param data start of array
932  * @param n_elements number of elements
933  * @param alignment size of each element
934  */
935 void
936 _dbus_swap_array (unsigned char *data,
937                   int            n_elements,
938                   int            alignment)
939 {
940   unsigned char *d;
941   unsigned char *end;
942
943   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
944
945   /* we use const_data and cast it off so DBusString can be a const string
946    * for the unit tests. don't ask.
947    */
948   d = data;
949   end = d + (n_elements * alignment);
950   
951   if (alignment == 8)
952     {
953       while (d != end)
954         {
955 #ifdef DBUS_HAVE_INT64
956           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
957 #else
958           swap_8_bytes ((DBusBasicValue*) d);
959 #endif
960           d += 8;
961         }
962     }
963   else if (alignment == 4)
964     {
965       while (d != end)
966         {
967           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
968           d += 4;
969         }
970     }
971   else
972     {
973       _dbus_assert (alignment == 2);
974       
975       while (d != end)
976         {
977           *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
978           d += 2;
979         }
980     }
981 }
982
983 static void
984 swap_array (DBusString *str,
985             int         array_start,
986             int         n_elements,
987             int         byte_order,
988             int         alignment)
989 {
990   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
991
992   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
993     {
994       /* we use const_data and cast it off so DBusString can be a const string
995        * for the unit tests. don't ask.
996        */
997       _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
998                         n_elements, alignment);
999     }
1000 }
1001
1002 static dbus_bool_t
1003 marshal_fixed_multi (DBusString           *str,
1004                      int                   insert_at,
1005                      const DBusBasicValue *value,
1006                      int                   n_elements,
1007                      int                   byte_order,
1008                      int                   alignment,
1009                      int                  *pos_after)
1010 {
1011   int old_string_len;
1012   int array_start;
1013   DBusString t;
1014   int len_in_bytes;
1015
1016   _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
1017   
1018   old_string_len = _dbus_string_get_length (str);
1019
1020   len_in_bytes = n_elements * alignment;
1021   array_start = insert_at;
1022   
1023   /* Note that we do alignment padding unconditionally
1024    * even if the array is empty; this means that
1025    * padding + len is always equal to the number of bytes
1026    * in the array.
1027    */
1028
1029   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
1030     goto error;
1031
1032   _dbus_string_init_const_len (&t,
1033                                (const unsigned char*) value,
1034                                len_in_bytes);
1035
1036   if (!_dbus_string_copy (&t, 0,
1037                           str, array_start))
1038     goto error;
1039
1040   swap_array (str, array_start, n_elements, byte_order, alignment);
1041
1042   if (pos_after)
1043     *pos_after = array_start + len_in_bytes;
1044   
1045   return TRUE;
1046
1047  error:
1048   _dbus_string_delete (str, insert_at,
1049                        _dbus_string_get_length (str) - old_string_len);
1050
1051   return FALSE;
1052 }
1053
1054 /**
1055  * Marshals a block of values of fixed-length type all at once, as an
1056  * optimization.  _dbus_type_is_fixed() returns #TRUE for fixed-length
1057  * types, which are the basic types minus the string-like types.
1058  *
1059  * The value argument should be the adddress of an
1060  * array, so e.g. "const dbus_uint32_t**"
1061  *
1062  * @param str string to marshal to
1063  * @param insert_at where to insert the value
1064  * @param element_type type of array elements
1065  * @param value address of an array to marshal
1066  * @param n_elements number of elements in the array
1067  * @param byte_order byte order
1068  * @param pos_after #NULL or the position after the type
1069  * @returns #TRUE on success
1070  **/
1071 dbus_bool_t
1072 _dbus_marshal_write_fixed_multi (DBusString *str,
1073                                  int         insert_at,
1074                                  int         element_type,
1075                                  const void *value,
1076                                  int         n_elements,
1077                                  int         byte_order,
1078                                  int        *pos_after)
1079 {
1080   const void* vp = *(const DBusBasicValue**)value;
1081   
1082   _dbus_assert (_dbus_type_is_fixed (element_type));
1083   _dbus_assert (n_elements >= 0);
1084
1085 #if 0
1086   _dbus_verbose ("writing %d elements of %s\n",
1087                  n_elements, _dbus_type_to_string (element_type));
1088 #endif
1089   
1090   switch (element_type)
1091     {
1092     case DBUS_TYPE_BYTE:
1093       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
1094       break;
1095     case DBUS_TYPE_INT16:
1096     case DBUS_TYPE_UINT16:
1097       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
1098       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
1099        * should we here too ? */
1100     case DBUS_TYPE_BOOLEAN:
1101     case DBUS_TYPE_INT32:
1102     case DBUS_TYPE_UINT32:
1103       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
1104       break;
1105     case DBUS_TYPE_INT64:
1106     case DBUS_TYPE_UINT64:
1107     case DBUS_TYPE_DOUBLE:
1108       return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
1109       break;
1110
1111     default:
1112       _dbus_assert_not_reached ("non fixed type in array write");
1113       break;
1114     }
1115
1116   return FALSE;
1117 }
1118
1119
1120 /**
1121  * Skips over a basic-typed value, reporting the following position.
1122  *
1123  * @param str the string containing the data
1124  * @param type type of value to read
1125  * @param byte_order the byte order
1126  * @param pos pointer to position in the string,
1127  *            updated on return to new position
1128  **/
1129 void
1130 _dbus_marshal_skip_basic (const DBusString      *str,
1131                           int                    type,
1132                           int                    byte_order,
1133                           int                   *pos)
1134 {
1135   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
1136                 byte_order == DBUS_BIG_ENDIAN);
1137   
1138   switch (type)
1139     {
1140     case DBUS_TYPE_BYTE:
1141       (*pos)++;
1142       break;
1143     case DBUS_TYPE_INT16:
1144     case DBUS_TYPE_UINT16:
1145       *pos = _DBUS_ALIGN_VALUE (*pos, 2);
1146       *pos += 2;
1147       break;
1148     case DBUS_TYPE_BOOLEAN:
1149     case DBUS_TYPE_INT32:
1150     case DBUS_TYPE_UINT32:
1151       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1152       *pos += 4;
1153       break;
1154     case DBUS_TYPE_INT64:
1155     case DBUS_TYPE_UINT64:
1156     case DBUS_TYPE_DOUBLE:
1157       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1158       *pos += 8;
1159       break;
1160     case DBUS_TYPE_STRING:
1161     case DBUS_TYPE_OBJECT_PATH:
1162       {
1163         int len;
1164
1165         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
1166         
1167         *pos += len + 1; /* length plus nul */
1168       }
1169       break;
1170     case DBUS_TYPE_SIGNATURE:
1171       {
1172         int len;
1173
1174         len = _dbus_string_get_byte (str, *pos);
1175
1176         *pos += len + 2; /* length byte plus length plus nul */
1177       }
1178       break;
1179     default:
1180       _dbus_warn ("type %s not a basic type\n",
1181                   _dbus_type_to_string (type));
1182       _dbus_assert_not_reached ("not a basic type");
1183       break;
1184     }
1185 }
1186
1187 /**
1188  * Skips an array, returning the next position.
1189  *
1190  * @param str the string containing the data
1191  * @param element_type the type of array elements
1192  * @param byte_order the byte order
1193  * @param pos pointer to position in the string,
1194  *            updated on return to new position
1195  */
1196 void
1197 _dbus_marshal_skip_array (const DBusString  *str,
1198                           int                element_type,
1199                           int                byte_order,
1200                           int               *pos)
1201 {
1202   dbus_uint32_t array_len;
1203   int i;
1204   int alignment;
1205
1206   i = _DBUS_ALIGN_VALUE (*pos, 4);
1207
1208   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
1209
1210   alignment = _dbus_type_get_alignment (element_type);
1211
1212   i = _DBUS_ALIGN_VALUE (i, alignment);
1213
1214   *pos = i + array_len;
1215 }
1216
1217 /**
1218  * Gets the alignment requirement for the given type;
1219  * will be 1, 4, or 8.
1220  *
1221  * @param typecode the type
1222  * @returns alignment of 1, 4, or 8
1223  */
1224 int
1225 _dbus_type_get_alignment (int typecode)
1226 {
1227   switch (typecode)
1228     {
1229     case DBUS_TYPE_BYTE:
1230     case DBUS_TYPE_VARIANT:
1231     case DBUS_TYPE_SIGNATURE:
1232       return 1;
1233     case DBUS_TYPE_INT16:
1234     case DBUS_TYPE_UINT16:
1235       return 2;
1236     case DBUS_TYPE_BOOLEAN:
1237     case DBUS_TYPE_INT32:
1238     case DBUS_TYPE_UINT32:
1239       /* this stuff is 4 since it starts with a length */
1240     case DBUS_TYPE_STRING:
1241     case DBUS_TYPE_OBJECT_PATH:
1242     case DBUS_TYPE_ARRAY:
1243       return 4;
1244     case DBUS_TYPE_INT64:
1245     case DBUS_TYPE_UINT64:
1246     case DBUS_TYPE_DOUBLE:
1247       /* struct is 8 since it could contain an 8-aligned item
1248        * and it's simpler to just always align structs to 8;
1249        * we want the amount of padding in a struct of a given
1250        * type to be predictable, not location-dependent.
1251        * DICT_ENTRY is always the same as struct.
1252        */
1253     case DBUS_TYPE_STRUCT:
1254     case DBUS_TYPE_DICT_ENTRY:
1255       return 8;
1256
1257     default:
1258       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
1259       return 0;
1260     }
1261 }
1262
1263
1264 /**
1265  * Return #TRUE if the typecode is a valid typecode.
1266  * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
1267  * random unknown bytes aren't either. This function is safe with
1268  * untrusted data.
1269  *
1270  * @returns #TRUE if valid
1271  */
1272 dbus_bool_t
1273 _dbus_type_is_valid (int typecode)
1274 {
1275   switch (typecode)
1276     {
1277     case DBUS_TYPE_BYTE:
1278     case DBUS_TYPE_BOOLEAN:
1279     case DBUS_TYPE_INT16:
1280     case DBUS_TYPE_UINT16:
1281     case DBUS_TYPE_INT32:
1282     case DBUS_TYPE_UINT32:
1283     case DBUS_TYPE_INT64:
1284     case DBUS_TYPE_UINT64:
1285     case DBUS_TYPE_DOUBLE:
1286     case DBUS_TYPE_STRING:
1287     case DBUS_TYPE_OBJECT_PATH:
1288     case DBUS_TYPE_SIGNATURE:
1289     case DBUS_TYPE_ARRAY:
1290     case DBUS_TYPE_STRUCT:
1291     case DBUS_TYPE_DICT_ENTRY:
1292     case DBUS_TYPE_VARIANT:
1293       return TRUE;
1294
1295     default:
1296       return FALSE;
1297     }
1298 }
1299
1300 /** macro that checks whether a typecode is a container type */
1301 #define TYPE_IS_CONTAINER(typecode)             \
1302     ((typecode) == DBUS_TYPE_STRUCT ||          \
1303      (typecode) == DBUS_TYPE_DICT_ENTRY ||      \
1304      (typecode) == DBUS_TYPE_VARIANT ||         \
1305      (typecode) == DBUS_TYPE_ARRAY)
1306
1307 /**
1308  * A "container type" can contain basic types, or nested
1309  * container types. #DBUS_TYPE_INVALID is not a container type.
1310  * This function will crash if passed a typecode that isn't
1311  * in dbus-protocol.h
1312  *
1313  * @returns #TRUE if type is a container
1314  */
1315 dbus_bool_t
1316 _dbus_type_is_container (int typecode)
1317 {
1318   /* only reasonable (non-line-noise) typecodes are allowed */
1319   _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
1320   return TYPE_IS_CONTAINER (typecode);
1321 }
1322
1323 /**
1324  * A "basic type" is a somewhat arbitrary concept, but the intent
1325  * is to include those types that are fully-specified by a single
1326  * typecode, with no additional type information or nested
1327  * values. So all numbers and strings are basic types and
1328  * structs, arrays, and variants are not basic types.
1329  * #DBUS_TYPE_INVALID is not a basic type.
1330  *
1331  * This function is defined to return #TRUE for exactly those
1332  * types that can be written with _dbus_marshal_basic_type()
1333  * and read with _dbus_marshal_read_basic().
1334  *
1335  * This function will crash if passed a typecode that isn't
1336  * in dbus-protocol.h
1337  *
1338  * @returns #TRUE if type is basic
1339  */
1340 dbus_bool_t
1341 _dbus_type_is_basic (int typecode)
1342 {
1343   /* only reasonable (non-line-noise) typecodes are allowed */
1344   _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
1345
1346   /* everything that isn't invalid or a container */
1347   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
1348 }
1349
1350 /**
1351  * Tells you whether values of this type can change length if you set
1352  * them to some other value. For this purpose, you assume that the
1353  * first byte of the old and new value would be in the same location,
1354  * so alignment padding is not a factor.
1355  *
1356  * @returns #FALSE if the type can occupy different lengths
1357  */
1358 dbus_bool_t
1359 _dbus_type_is_fixed (int typecode)
1360 {
1361   switch (typecode)
1362     {
1363     case DBUS_TYPE_BYTE:
1364     case DBUS_TYPE_BOOLEAN:
1365     case DBUS_TYPE_INT16:
1366     case DBUS_TYPE_UINT16:
1367     case DBUS_TYPE_INT32:
1368     case DBUS_TYPE_UINT32:
1369     case DBUS_TYPE_INT64:
1370     case DBUS_TYPE_UINT64:
1371     case DBUS_TYPE_DOUBLE:
1372       return TRUE;
1373     default:
1374       return FALSE;
1375     }
1376 }
1377
1378 /**
1379  * Returns a string describing the given type.
1380  *
1381  * @param typecode the type to describe
1382  * @returns a constant string describing the type
1383  */
1384 const char *
1385 _dbus_type_to_string (int typecode)
1386 {
1387   switch (typecode)
1388     {
1389     case DBUS_TYPE_INVALID:
1390       return "invalid";
1391     case DBUS_TYPE_BOOLEAN:
1392       return "boolean";
1393     case DBUS_TYPE_BYTE:
1394       return "byte";
1395     case DBUS_TYPE_INT16:
1396       return "int16";
1397     case DBUS_TYPE_UINT16:
1398       return "uint16";
1399     case DBUS_TYPE_INT32:
1400       return "int32";
1401     case DBUS_TYPE_UINT32:
1402       return "uint32";
1403     case DBUS_TYPE_DOUBLE:
1404       return "double";
1405     case DBUS_TYPE_STRING:
1406       return "string";
1407     case DBUS_TYPE_OBJECT_PATH:
1408       return "object_path";
1409     case DBUS_TYPE_SIGNATURE:
1410       return "signature";
1411     case DBUS_TYPE_STRUCT:
1412       return "struct";
1413     case DBUS_TYPE_DICT_ENTRY:
1414       return "dict_entry";
1415     case DBUS_TYPE_ARRAY:
1416       return "array";
1417     case DBUS_TYPE_VARIANT:
1418       return "variant";
1419     case DBUS_STRUCT_BEGIN_CHAR:
1420       return "begin_struct";
1421     case DBUS_STRUCT_END_CHAR:
1422       return "end_struct";
1423     case DBUS_DICT_ENTRY_BEGIN_CHAR:
1424       return "begin_dict_entry";
1425     case DBUS_DICT_ENTRY_END_CHAR:
1426       return "end_dict_entry";
1427     default:
1428       return "unknown";
1429     }
1430 }
1431
1432 /**
1433  * If in verbose mode, print a block of binary data.
1434  *
1435  * @todo right now it prints even if not in verbose mode
1436  *
1437  * @param data the data
1438  * @param len the length of the data
1439  * @param offset where to start counting for byte indexes
1440  */
1441 void
1442 _dbus_verbose_bytes (const unsigned char *data,
1443                      int                  len,
1444                      int                  offset)
1445 {
1446   int i;
1447   const unsigned char *aligned;
1448
1449   _dbus_assert (len >= 0);
1450
1451   /* Print blanks on first row if appropriate */
1452   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1453   if (aligned > data)
1454     aligned -= 4;
1455   _dbus_assert (aligned <= data);
1456
1457   if (aligned != data)
1458     {
1459       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
1460       while (aligned != data)
1461         {
1462           _dbus_verbose ("    ");
1463           ++aligned;
1464         }
1465     }
1466
1467   /* now print the bytes */
1468   i = 0;
1469   while (i < len)
1470     {
1471       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1472         {
1473           _dbus_verbose ("%4d\t%p: ",
1474                          offset + i, &data[i]);
1475         }
1476
1477       if (data[i] >= 32 &&
1478           data[i] <= 126)
1479         _dbus_verbose (" '%c' ", data[i]);
1480       else
1481         _dbus_verbose ("0x%s%x ",
1482                        data[i] <= 0xf ? "0" : "", data[i]);
1483
1484       ++i;
1485
1486       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1487         {
1488           if (i > 3)
1489             _dbus_verbose ("BE: %d LE: %d",
1490                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1491                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1492
1493           if (i > 7 &&
1494               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1495             {
1496 #ifdef DBUS_HAVE_INT64
1497               /* I think I probably mean "GNU libc printf" and not "GNUC"
1498                * but we'll wait until someone complains. If you hit this,
1499                * just turn off verbose mode as a workaround.
1500                */
1501 #if __GNUC__
1502               _dbus_verbose (" u64: 0x%llx",
1503                              *(dbus_uint64_t*)&data[i-8]);
1504 #endif
1505 #endif
1506               _dbus_verbose (" dbl: %g",
1507                              *(double*)&data[i-8]);
1508             }
1509
1510           _dbus_verbose ("\n");
1511         }
1512     }
1513
1514   _dbus_verbose ("\n");
1515 }
1516
1517 /**
1518  * Dump the given part of the string to verbose log.
1519  *
1520  * @param str the string
1521  * @param start the start of range to dump
1522  * @param len length of range
1523  */
1524 void
1525 _dbus_verbose_bytes_of_string (const DBusString    *str,
1526                                int                  start,
1527                                int                  len)
1528 {
1529   const char *d;
1530   int real_len;
1531
1532   real_len = _dbus_string_get_length (str);
1533
1534   _dbus_assert (start >= 0);
1535
1536   if (start > real_len)
1537     {
1538       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1539                      start, len, real_len);
1540       return;
1541     }
1542
1543   if ((start + len) > real_len)
1544     {
1545       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1546                      start, len, real_len);
1547       len = real_len - start;
1548     }
1549
1550   d = _dbus_string_get_const_data_len (str, start, len);
1551
1552   _dbus_verbose_bytes (d, len, start);
1553 }
1554
1555 /**
1556  * Get the first type in the signature. The difference between this
1557  * and just getting the first byte of the signature is that you won't
1558  * get DBUS_STRUCT_BEGIN_CHAR, you'll get DBUS_TYPE_STRUCT
1559  * instead.
1560  *
1561  * @param str string containing signature
1562  * @param pos where the signature starts
1563  * @returns the first type in the signature
1564  */
1565 int
1566 _dbus_first_type_in_signature (const DBusString *str,
1567                                int               pos)
1568 {
1569   unsigned char t;
1570
1571   t = _dbus_string_get_byte (str, pos);
1572
1573   if (t == DBUS_STRUCT_BEGIN_CHAR)
1574     return DBUS_TYPE_STRUCT;
1575   else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
1576     return DBUS_TYPE_DICT_ENTRY;
1577   else
1578     {
1579       _dbus_assert (t != DBUS_STRUCT_END_CHAR);
1580       _dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
1581       return t;
1582     }
1583 }
1584
1585 /** @} */
1586
1587 #ifdef DBUS_BUILD_TESTS
1588 #include "dbus-test.h"
1589 #include <stdio.h>
1590
1591 static void
1592 swap_test_array (void *array,
1593                  int   len_bytes,
1594                  int   byte_order,
1595                  int   alignment)
1596 {
1597   DBusString t;
1598
1599   if (alignment == 1)
1600     return;
1601   
1602   _dbus_string_init_const_len (&t, array, len_bytes);
1603   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
1604 }
1605
1606 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
1607   do {                                                                  \
1608      v_##typename = literal;                                            \
1609      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
1610                                     &v_##typename,                      \
1611                                     byte_order, NULL))                  \
1612        _dbus_assert_not_reached ("no memory");                          \
1613    } while (0)
1614
1615 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
1616   do {                                                                          \
1617     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
1618                               byte_order, &pos);                                \
1619   } while (0)
1620
1621 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
1622   do {                                                                                  \
1623     DEMARSHAL_BASIC (typename, byte_order);                                             \
1624     if (literal != v_##typename)                                                        \
1625       {                                                                                 \
1626         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1627                                      _dbus_string_get_length (&str) - dump_pos);        \
1628         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1629       }                                                                                 \
1630   } while (0)
1631
1632 #define MARSHAL_TEST(typename, byte_order, literal)             \
1633   do {                                                          \
1634     MARSHAL_BASIC (typename, byte_order, literal);              \
1635     dump_pos = pos;                                             \
1636     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
1637   } while (0)
1638
1639 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
1640   do {                                                                                  \
1641     MARSHAL_BASIC (typename, byte_order, literal);                                      \
1642     dump_pos = pos;                                                                     \
1643     DEMARSHAL_BASIC (typename, byte_order);                                             \
1644     if (strcmp (literal, v_##typename) != 0)                                            \
1645       {                                                                                 \
1646         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1647                                        _dbus_string_get_length (&str) - dump_pos);      \
1648         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
1649         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1650       }                                                                                 \
1651   } while (0)
1652
1653 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
1654   do {                                                                                          \
1655      int next;                                                                                  \
1656      v_UINT32 = sizeof(literal);                                                                \
1657      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32,                    \
1658                                      byte_order, &next))                                        \
1659        _dbus_assert_not_reached ("no memory");                                                  \
1660      v_ARRAY_##typename = literal;                                                              \
1661      if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename,                    \
1662                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
1663                                            byte_order, NULL))                                   \
1664        _dbus_assert_not_reached ("no memory");                                                  \
1665    } while (0)
1666
1667 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
1668   do {                                                                                          \
1669     int next;                                                                                   \
1670     alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename);                                \
1671     v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next);                   \
1672     _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename,      \
1673                                     v_UINT32/alignment,                                         \
1674                                     byte_order, NULL);                                          \
1675     swap_test_array (v_ARRAY_##typename, v_UINT32,                                              \
1676                      byte_order, alignment);                                                    \
1677   } while (0)
1678
1679 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
1680   do {                                                                                  \
1681     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
1682     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
1683       {                                                                                 \
1684         _dbus_verbose ("MARSHALED DATA\n");                                             \
1685         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1686                                       _dbus_string_get_length (&str) - dump_pos);       \
1687         _dbus_verbose ("LITERAL DATA\n");                                               \
1688         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
1689         _dbus_verbose ("READ DATA\n");                                                  \
1690         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
1691         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
1692       }                                                                                 \
1693   } while (0)
1694
1695 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
1696   do {                                                                  \
1697     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
1698     dump_pos = pos;                                                     \
1699     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
1700   } while (0)
1701
1702 dbus_bool_t
1703 _dbus_marshal_test (void)
1704 {
1705   int alignment;
1706   DBusString str;
1707   int pos, dump_pos;
1708   unsigned char array1[5] = { 3, 4, 0, 1, 9 };
1709   dbus_int16_t array2[3] = { 124, 457, 780 };
1710   dbus_int32_t array4[3] = { 123, 456, 789 };
1711 #ifdef DBUS_HAVE_INT64
1712   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1713                              DBUS_INT64_CONSTANT (0x456ffffffff),
1714                              DBUS_INT64_CONSTANT (0x789ffffffff) };
1715   dbus_int64_t *v_ARRAY_INT64;
1716 #endif
1717   unsigned char *v_ARRAY_BYTE;
1718   dbus_int16_t *v_ARRAY_INT16;
1719   dbus_uint16_t *v_ARRAY_UINT16;
1720   dbus_int32_t *v_ARRAY_INT32;
1721   dbus_uint32_t *v_ARRAY_UINT32;
1722   double *v_ARRAY_DOUBLE;
1723   DBusString t;
1724   double v_DOUBLE;
1725   double t_DOUBLE;
1726   dbus_int16_t v_INT16;
1727   dbus_uint16_t v_UINT16;
1728   dbus_int32_t v_INT32;
1729   dbus_uint32_t v_UINT32;
1730   dbus_int64_t v_INT64;
1731   dbus_uint64_t v_UINT64;
1732   unsigned char v_BYTE;
1733   dbus_bool_t v_BOOLEAN;
1734   const char *v_STRING;
1735   const char *v_SIGNATURE;
1736   const char *v_OBJECT_PATH;
1737   int byte_order;
1738
1739   if (!_dbus_string_init (&str))
1740     _dbus_assert_not_reached ("failed to init string");
1741
1742   pos = 0;
1743
1744   /* Marshal doubles */
1745   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1746   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1747   t_DOUBLE = 3.14;
1748   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1749     _dbus_assert_not_reached ("got wrong double value");
1750
1751   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1752   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1753   t_DOUBLE = 3.14;
1754   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1755     _dbus_assert_not_reached ("got wrong double value");
1756
1757   /* Marshal signed 16 integers */
1758   MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
1759   MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
1760
1761   /* Marshal unsigned 16 integers */
1762   MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
1763   MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
1764   
1765   /* Marshal signed integers */
1766   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1767   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1768
1769   /* Marshal unsigned integers */
1770   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1771   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1772
1773 #ifdef DBUS_HAVE_INT64
1774   /* Marshal signed integers */
1775   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1776   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1777
1778   /* Marshal unsigned integers */
1779   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1780   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1781 #endif /* DBUS_HAVE_INT64 */
1782
1783   /* Marshal byte */
1784   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1785   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1786
1787   /* Marshal all possible bools! */
1788   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1789   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1790   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1791   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1792
1793   /* Marshal strings */
1794   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1795   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1796   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1797   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1798
1799   /* object paths */
1800   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1801   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1802
1803   /* signatures */
1804   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1805   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1806   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1807   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1808
1809   /* Arrays */
1810   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
1811   MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
1812   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2);
1813   MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2);
1814   
1815   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
1816   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
1817   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4);
1818   MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4);
1819
1820   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
1821   MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
1822   
1823 #ifdef DBUS_HAVE_INT64
1824   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
1825   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
1826 #endif
1827
1828 #if 0
1829
1830   /*
1831    * FIXME restore the set/pack tests
1832    */
1833
1834 #ifdef DBUS_HAVE_INT64
1835   /* set/pack 64-bit integers */
1836   _dbus_string_set_length (&str, 8);
1837
1838   /* signed little */
1839   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1840                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1841
1842   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1843                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1844                                     _dbus_string_get_const_data (&str)));
1845
1846   /* signed big */
1847   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1848                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1849
1850   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1851                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1852                                     _dbus_string_get_const_data (&str)));
1853
1854   /* signed little pack */
1855   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1856                     DBUS_LITTLE_ENDIAN,
1857                     _dbus_string_get_data (&str));
1858
1859   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1860                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1861                                     _dbus_string_get_const_data (&str)));
1862
1863   /* signed big pack */
1864   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1865                     DBUS_BIG_ENDIAN,
1866                     _dbus_string_get_data (&str));
1867
1868   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1869                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1870                                     _dbus_string_get_const_data (&str)));
1871
1872   /* unsigned little */
1873   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1874                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1875
1876   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1877                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1878                                      _dbus_string_get_const_data (&str)));
1879
1880   /* unsigned big */
1881   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1882                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1883
1884   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1885                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1886                                      _dbus_string_get_const_data (&str)));
1887
1888   /* unsigned little pack */
1889   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1890                      DBUS_LITTLE_ENDIAN,
1891                      _dbus_string_get_data (&str));
1892
1893   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1894                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1895                                      _dbus_string_get_const_data (&str)));
1896
1897   /* unsigned big pack */
1898   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1899                      DBUS_BIG_ENDIAN,
1900                      _dbus_string_get_data (&str));
1901
1902   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1903                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1904                                      _dbus_string_get_const_data (&str)));
1905 #endif /* DBUS_HAVE_INT64 */
1906
1907   /* set/pack 32-bit integers */
1908   _dbus_string_set_length (&str, 4);
1909
1910   /* signed little */
1911   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1912                            0, -0x123456);
1913
1914   _dbus_assert (-0x123456 ==
1915                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1916                                     _dbus_string_get_const_data (&str)));
1917
1918   /* signed big */
1919   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1920                            0, -0x123456);
1921
1922   _dbus_assert (-0x123456 ==
1923                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1924                                     _dbus_string_get_const_data (&str)));
1925
1926   /* signed little pack */
1927   _dbus_pack_int32 (-0x123456,
1928                     DBUS_LITTLE_ENDIAN,
1929                     _dbus_string_get_data (&str));
1930
1931   _dbus_assert (-0x123456 ==
1932                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1933                                     _dbus_string_get_const_data (&str)));
1934
1935   /* signed big pack */
1936   _dbus_pack_int32 (-0x123456,
1937                     DBUS_BIG_ENDIAN,
1938                     _dbus_string_get_data (&str));
1939
1940   _dbus_assert (-0x123456 ==
1941                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1942                                     _dbus_string_get_const_data (&str)));
1943
1944   /* unsigned little */
1945   _dbus_marshal_set_uint32 (&str,
1946                             0, 0x123456,
1947                             DBUS_LITTLE_ENDIAN);
1948
1949   _dbus_assert (0x123456 ==
1950                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1951                                      _dbus_string_get_const_data (&str)));
1952
1953   /* unsigned big */
1954   _dbus_marshal_set_uint32 (&str,
1955                             0, 0x123456,
1956                             DBUS_BIG_ENDIAN);
1957
1958   _dbus_assert (0x123456 ==
1959                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1960                                      _dbus_string_get_const_data (&str)));
1961
1962   /* unsigned little pack */
1963   _dbus_pack_uint32 (0x123456,
1964                      DBUS_LITTLE_ENDIAN,
1965                      _dbus_string_get_data (&str));
1966
1967   _dbus_assert (0x123456 ==
1968                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1969                                      _dbus_string_get_const_data (&str)));
1970
1971   /* unsigned big pack */
1972   _dbus_pack_uint32 (0x123456,
1973                      DBUS_BIG_ENDIAN,
1974                      _dbus_string_get_data (&str));
1975
1976   _dbus_assert (0x123456 ==
1977                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1978                                      _dbus_string_get_const_data (&str)));
1979
1980 #endif /* set/pack tests for integers */
1981
1982   /* Strings in-place set */
1983   byte_order = DBUS_LITTLE_ENDIAN;
1984   while (TRUE)
1985     {
1986       /* Init a string */
1987       _dbus_string_set_length (&str, 0);
1988
1989       /* reset pos for the macros */
1990       pos = 0;
1991
1992       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1993
1994       /* Set it to something longer */
1995       _dbus_string_init_const (&t, "Hello world foo");
1996
1997       v_STRING = _dbus_string_get_const_data (&t);
1998       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
1999                                &v_STRING, byte_order, NULL, NULL);
2000
2001       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
2002                                 &v_STRING, byte_order,
2003                                 NULL);
2004       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
2005
2006       /* Set it to something shorter */
2007       _dbus_string_init_const (&t, "Hello");
2008
2009       v_STRING = _dbus_string_get_const_data (&t);
2010       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
2011                                &v_STRING, byte_order, NULL, NULL);
2012       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
2013                                 &v_STRING, byte_order,
2014                                 NULL);
2015       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
2016
2017       /* Do the other byte order */
2018       if (byte_order == DBUS_LITTLE_ENDIAN)
2019         byte_order = DBUS_BIG_ENDIAN;
2020       else
2021         break;
2022     }
2023
2024   /* Clean up */
2025   _dbus_string_free (&str);
2026
2027   return TRUE;
2028 }
2029
2030 #endif /* DBUS_BUILD_TESTS */