change strings to be marshaled consistently with the other basic types (address of...
[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 dbus_uint32_t
46 unpack_4_octets (int                  byte_order,
47                  const unsigned char *data)
48 {
49   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
50
51   if (byte_order == DBUS_LITTLE_ENDIAN)
52     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
53   else
54     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
55 }
56
57 #ifndef DBUS_HAVE_INT64
58 /* from ORBit */
59 static void
60 swap_bytes (unsigned char *data,
61             unsigned int   len)
62 {
63   unsigned char *p1 = data;
64   unsigned char *p2 = data + len - 1;
65
66   while (p1 < p2)
67     {
68       unsigned char tmp = *p1;
69       *p1 = *p2;
70       *p2 = tmp;
71
72       --p2;
73       ++p1;
74     }
75 }
76 #endif /* !DBUS_HAVE_INT64 */
77
78 /**
79  * Union used to manipulate 8 bytes as if they
80  * were various types.
81  */
82 typedef union
83 {
84 #ifdef DBUS_HAVE_INT64
85   dbus_int64_t  s; /**< 64-bit integer */
86   dbus_uint64_t u; /**< 64-bit unsigned integer */
87 #endif
88   double d;        /**< double */
89 } DBusOctets8;
90
91 static DBusOctets8
92 unpack_8_octets (int                  byte_order,
93                  const unsigned char *data)
94 {
95   DBusOctets8 r;
96
97   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
98   _dbus_assert (sizeof (r) == 8);
99
100 #ifdef DBUS_HAVE_INT64
101   if (byte_order == DBUS_LITTLE_ENDIAN)
102     r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
103   else
104     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
105 #else
106   r.d = *(double*)data;
107   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
108     swap_bytes ((unsigned char*) &r, sizeof (r));
109 #endif
110
111   return r;
112 }
113
114 /**
115  * Unpacks a 32 bit unsigned integer from a data pointer
116  *
117  * @param byte_order The byte order to use
118  * @param data the data pointer
119  * @returns the integer
120  */
121 dbus_uint32_t
122 _dbus_unpack_uint32 (int                  byte_order,
123                      const unsigned char *data)
124 {
125   return unpack_4_octets (byte_order, data);
126 }
127
128 /**
129  * Unpacks a 32 bit signed integer from a data pointer
130  *
131  * @param byte_order The byte order to use
132  * @param data the data pointer
133  * @returns the integer
134  */
135 dbus_int32_t
136 _dbus_unpack_int32 (int                  byte_order,
137                     const unsigned char *data)
138 {
139   return (dbus_int32_t) unpack_4_octets (byte_order, data);
140 }
141
142 #ifdef DBUS_HAVE_INT64
143 /**
144  * Unpacks a 64 bit unsigned integer from a data pointer
145  *
146  * @param byte_order The byte order to use
147  * @param data the data pointer
148  * @returns the integer
149  */
150 dbus_uint64_t
151 _dbus_unpack_uint64 (int                  byte_order,
152                      const unsigned char *data)
153 {
154   DBusOctets8 r;
155
156   r = unpack_8_octets (byte_order, data);
157
158   return r.u;
159 }
160
161 /**
162  * Unpacks a 64 bit signed integer from a data pointer
163  *
164  * @param byte_order The byte order to use
165  * @param data the data pointer
166  * @returns the integer
167  */
168 dbus_int64_t
169 _dbus_unpack_int64 (int                  byte_order,
170                     const unsigned char *data)
171 {
172   DBusOctets8 r;
173
174   r = unpack_8_octets (byte_order, data);
175
176   return r.s;
177 }
178
179 #endif /* DBUS_HAVE_INT64 */
180
181 static void
182 pack_4_octets (dbus_uint32_t   value,
183                int             byte_order,
184                unsigned char  *data)
185 {
186   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
187
188   if ((byte_order) == DBUS_LITTLE_ENDIAN)
189     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
190   else
191     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
192 }
193
194 static void
195 swap_8_octets (DBusOctets8    *value,
196                int             byte_order)
197 {
198   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
199     {
200 #ifdef DBUS_HAVE_INT64
201       value->u = DBUS_UINT64_SWAP_LE_BE (value->u);
202 #else
203       swap_bytes ((unsigned char *)value, 8);
204 #endif
205     }
206 }
207
208 static void
209 pack_8_octets (DBusOctets8     value,
210                int             byte_order,
211                unsigned char  *data)
212 {
213   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
214
215 #ifdef DBUS_HAVE_INT64
216   if ((byte_order) == DBUS_LITTLE_ENDIAN)
217     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u);
218   else
219     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
220 #else
221   memcpy (data, &value, 8);
222   swap_8_octets ((DBusOctets8*)data, byte_order);
223 #endif
224 }
225
226 /**
227  * Packs a 32 bit unsigned integer into a data pointer.
228  *
229  * @param value the value
230  * @param byte_order the byte order to use
231  * @param data the data pointer
232  */
233 void
234 _dbus_pack_uint32 (dbus_uint32_t   value,
235                    int             byte_order,
236                    unsigned char  *data)
237 {
238   pack_4_octets (value, byte_order, data);
239 }
240
241 /**
242  * Packs a 32 bit signed integer into a data pointer.
243  *
244  * @param value the value
245  * @param byte_order the byte order to use
246  * @param data the data pointer
247  */
248 void
249 _dbus_pack_int32 (dbus_int32_t   value,
250                   int            byte_order,
251                   unsigned char *data)
252 {
253   pack_4_octets ((dbus_uint32_t) value, byte_order, data);
254 }
255
256 #ifdef DBUS_HAVE_INT64
257 /**
258  * Packs a 64 bit unsigned integer into a data pointer.
259  *
260  * @param value the value
261  * @param byte_order the byte order to use
262  * @param data the data pointer
263  */
264 void
265 _dbus_pack_uint64 (dbus_uint64_t   value,
266                    int             byte_order,
267                    unsigned char  *data)
268 {
269   DBusOctets8 r;
270   r.u = value;
271   pack_8_octets (r, byte_order, data);
272 }
273
274 /**
275  * Packs a 64 bit signed integer into a data pointer.
276  *
277  * @param value the value
278  * @param byte_order the byte order to use
279  * @param data the data pointer
280  */
281 void
282 _dbus_pack_int64 (dbus_int64_t   value,
283                   int            byte_order,
284                   unsigned char *data)
285 {
286   DBusOctets8 r;
287   r.s = value;
288   pack_8_octets (r, byte_order, data);
289 }
290 #endif /* DBUS_HAVE_INT64 */
291
292 static void
293 set_4_octets (DBusString          *str,
294               int                  byte_order,
295               int                  offset,
296               dbus_uint32_t        value)
297 {
298   char *data;
299
300   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
301                 byte_order == DBUS_BIG_ENDIAN);
302
303   data = _dbus_string_get_data_len (str, offset, 4);
304
305   _dbus_pack_uint32 (value, byte_order, data);
306 }
307
308 static void
309 set_8_octets (DBusString          *str,
310               int                  byte_order,
311               int                  offset,
312               DBusOctets8          value)
313 {
314   char *data;
315
316   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
317                 byte_order == DBUS_BIG_ENDIAN);
318
319   data = _dbus_string_get_data_len (str, offset, 8);
320
321   pack_8_octets (value, byte_order, data);
322 }
323
324 /**
325  * Sets the 4 bytes at the given offset to a marshaled signed integer,
326  * replacing anything found there previously.
327  *
328  * @param str the string to write the marshalled int to
329  * @param offset the byte offset where int should be written
330  * @param byte_order the byte order to use
331  * @param value the value
332  *
333  */
334 void
335 _dbus_marshal_set_int32 (DBusString          *str,
336                          int                  byte_order,
337                          int                  offset,
338                          dbus_int32_t         value)
339 {
340   set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
341 }
342
343 /**
344  * Sets the 4 bytes at the given offset to a marshaled unsigned
345  * integer, replacing anything found there previously.
346  *
347  * @param str the string to write the marshalled int to
348  * @param offset the byte offset where int should be written
349  * @param byte_order the byte order to use
350  * @param value the value
351  *
352  */
353 void
354 _dbus_marshal_set_uint32 (DBusString          *str,
355                           int                  byte_order,
356                           int                  offset,
357                           dbus_uint32_t        value)
358 {
359   set_4_octets (str, byte_order, offset, value);
360 }
361
362 #ifdef DBUS_HAVE_INT64
363
364 /**
365  * Sets the 8 bytes at the given offset to a marshaled signed integer,
366  * replacing anything found there previously.
367  *
368  * @param str the string to write the marshalled int to
369  * @param offset the byte offset where int should be written
370  * @param byte_order the byte order to use
371  * @param value the value
372  *
373  */
374 void
375 _dbus_marshal_set_int64 (DBusString          *str,
376                          int                  byte_order,
377                          int                  offset,
378                          dbus_int64_t         value)
379 {
380   DBusOctets8 r;
381   r.s = value;
382   set_8_octets (str, byte_order, offset, r);
383 }
384
385 /**
386  * Sets the 8 bytes at the given offset to a marshaled unsigned
387  * integer, replacing anything found there previously.
388  *
389  * @param str the string to write the marshalled int to
390  * @param offset the byte offset where int should be written
391  * @param byte_order the byte order to use
392  * @param value the value
393  *
394  */
395 void
396 _dbus_marshal_set_uint64 (DBusString          *str,
397                           int                  byte_order,
398                           int                  offset,
399                           dbus_uint64_t        value)
400 {
401   DBusOctets8 r;
402   r.u = value;
403   set_8_octets (str, byte_order, offset, r);
404 }
405 #endif /* DBUS_HAVE_INT64 */
406
407 /**
408  * Sets the existing marshaled string at the given offset with
409  * a new marshaled string. The given offset must point to
410  * an existing string or the wrong length will be deleted
411  * and replaced with the new string.
412  *
413  * Note: no attempt is made by this function to re-align
414  * any data which has been already marshalled after this
415  * string. Use with caution.
416  *
417  * @param str the string to write the marshalled string to
418  * @param offset the byte offset where string should be written
419  * @param byte_order the byte order to use
420  * @param value the value
421  * @param len the length to use
422  * @returns #TRUE on success
423  *
424  */
425 dbus_bool_t
426 _dbus_marshal_set_string (DBusString          *str,
427                           int                  byte_order,
428                           int                  offset,
429                           const DBusString    *value,
430                           int                  len)
431 {
432   int old_len;
433
434   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
435                 byte_order == DBUS_BIG_ENDIAN);
436
437   old_len = _dbus_demarshal_uint32 (str, byte_order,
438                                     offset, NULL);
439
440   if (!_dbus_string_replace_len (value, 0, len,
441                                  str, offset + 4, old_len))
442     return FALSE;
443
444   _dbus_marshal_set_uint32 (str, byte_order,
445                             offset, len);
446
447   return TRUE;
448 }
449
450 static dbus_uint32_t
451 demarshal_4_octets (const DBusString *str,
452                     int               byte_order,
453                     int               pos,
454                     int              *new_pos)
455 {
456   pos = _DBUS_ALIGN_VALUE (pos, 4);
457
458   if (new_pos)
459     *new_pos = pos + 4;
460
461   return unpack_4_octets (byte_order,
462                           _dbus_string_get_const_data (str) + pos);
463 }
464
465 /**
466  * Convenience function to demarshal a 32 bit unsigned integer.
467  *
468  * @param str the string containing the data
469  * @param byte_order the byte order
470  * @param pos the position in the string
471  * @param new_pos the new position of the string
472  * @returns the demarshaled integer.
473  */
474 dbus_uint32_t
475 _dbus_demarshal_uint32  (const DBusString *str,
476                          int               byte_order,
477                          int               pos,
478                          int              *new_pos)
479 {
480   return demarshal_4_octets (str, byte_order, pos, new_pos);
481 }
482
483 /**
484  * Demarshals a basic type
485  *
486  * @param str the string containing the data
487  * @param type type of value to demarshal
488  * @param value pointer to return value data
489  * @param byte_order the byte order
490  * @param pos position in the string
491  * @param new_pos pointer to update with new position, or #NULL
492  **/
493 void
494 _dbus_demarshal_basic_type (const DBusString      *str,
495                             int                    type,
496                             void                  *value,
497                             int                    byte_order,
498                             int                    pos,
499                             int                   *new_pos)
500 {
501   const char *str_data;
502
503   str_data = _dbus_string_get_const_data (str);
504
505   switch (type)
506     {
507     case DBUS_TYPE_BYTE:
508     case DBUS_TYPE_BOOLEAN:
509       *(unsigned char *) value = _dbus_string_get_byte (str, pos);
510       (pos)++;
511       break;
512     case DBUS_TYPE_INT32:
513     case DBUS_TYPE_UINT32:
514       pos = _DBUS_ALIGN_VALUE (pos, 4);
515       *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + pos);
516       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
517         *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
518       pos += 4;
519       break;
520 #ifdef DBUS_HAVE_INT64
521     case DBUS_TYPE_INT64:
522     case DBUS_TYPE_UINT64:
523 #endif /* DBUS_HAVE_INT64 */
524     case DBUS_TYPE_DOUBLE:
525       pos = _DBUS_ALIGN_VALUE (pos, 8);
526       memcpy (value, str_data + pos, 8);
527       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
528 #ifdef DBUS_HAVE_INT64
529         *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
530 #else
531         swap_bytes (value, 8);
532 #endif
533       pos += 8;
534       break;
535     case DBUS_TYPE_STRING:
536     case DBUS_TYPE_OBJECT_PATH:
537       {
538         int len;
539
540         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
541
542         *(const char**) value = str_data + pos;
543
544         pos += len + 1; /* length plus nul */
545       }
546       break;
547     case DBUS_TYPE_SIGNATURE:
548       {
549         int len;
550
551         len = _dbus_string_get_byte (str, pos);
552         pos += 1;
553
554         *(const char**) value = str_data + pos;
555
556         pos += len + 1; /* length plus nul */
557       }
558       break;
559     default:
560       _dbus_warn ("type %s not a basic type\n",
561                   _dbus_type_to_string (type));
562       _dbus_assert_not_reached ("not a basic type");
563       break;
564     }
565
566   if (new_pos)
567     *new_pos = pos;
568 }
569
570 /**
571  * Skips over a basic type, reporting the following position.
572  *
573  * @param str the string containing the data
574  * @param type type of value to demarshal
575  * @param byte_order the byte order
576  * @param pos pointer to position in the string,
577  *            updated on return to new position
578  **/
579 void
580 _dbus_marshal_skip_basic_type (const DBusString      *str,
581                                int                    type,
582                                int                    byte_order,
583                                int                   *pos)
584 {
585   switch (type)
586     {
587     case DBUS_TYPE_BYTE:
588     case DBUS_TYPE_BOOLEAN:
589       (*pos)++;
590       break;
591     case DBUS_TYPE_INT32:
592     case DBUS_TYPE_UINT32:
593       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
594       *pos += 4;
595       break;
596 #ifdef DBUS_HAVE_INT64
597     case DBUS_TYPE_INT64:
598     case DBUS_TYPE_UINT64:
599 #endif /* DBUS_HAVE_INT64 */
600     case DBUS_TYPE_DOUBLE:
601       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
602       *pos += 8;
603       break;
604     case DBUS_TYPE_STRING:
605     case DBUS_TYPE_OBJECT_PATH:
606       {
607         int len;
608
609         len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos);
610
611         *pos += len + 1; /* length plus nul */
612       }
613       break;
614     case DBUS_TYPE_SIGNATURE:
615       {
616         int len;
617
618         len = _dbus_string_get_byte (str, *pos);
619
620         *pos += len + 2; /* length byte plus length plus nul */
621       }
622       break;
623     default:
624       _dbus_warn ("type %s not a basic type\n",
625                   _dbus_type_to_string (type));
626       _dbus_assert_not_reached ("not a basic type");
627       break;
628     }
629 }
630
631 /**
632  * Skips an array, returning the next position.
633  *
634  * @param str the string containing the data
635  * @param byte_order the byte order
636  * @param pos pointer to position in the string,
637  *            updated on return to new position
638  */
639 void
640 _dbus_marshal_skip_array (const DBusString  *str,
641                           int                byte_order,
642                           int                element_type,
643                           int               *pos)
644 {
645   dbus_uint32_t array_len;
646   int i;
647   int alignment;
648
649   i = _DBUS_ALIGN_VALUE (*pos, 4);
650
651   _dbus_demarshal_basic_type (str,
652                               DBUS_TYPE_UINT32,
653                               &array_len,
654                               byte_order,
655                               i,
656                               &i);
657
658   alignment = _dbus_type_get_alignment (element_type);
659
660   i = _DBUS_ALIGN_VALUE (i, alignment);
661
662   *pos = i + array_len;
663 }
664
665 /**
666  * Return #TRUE if the typecode is a valid typecode
667  *
668  * @returns #TRUE if valid
669  */
670 dbus_bool_t
671 _dbus_type_is_valid (int typecode)
672 {
673   switch (typecode)
674     {
675     case DBUS_TYPE_BYTE:
676     case DBUS_TYPE_BOOLEAN:
677     case DBUS_TYPE_INT32:
678     case DBUS_TYPE_UINT32:
679     case DBUS_TYPE_INT64:
680     case DBUS_TYPE_UINT64:
681     case DBUS_TYPE_DOUBLE:
682     case DBUS_TYPE_STRING:
683     case DBUS_TYPE_OBJECT_PATH:
684     case DBUS_TYPE_SIGNATURE:
685     case DBUS_TYPE_ARRAY:
686     case DBUS_TYPE_STRUCT:
687     case DBUS_TYPE_VARIANT:
688       return TRUE;
689
690     default:
691       return FALSE;
692     }
693 }
694
695 /**
696  * Gets the alignment requirement for the given type;
697  * will be 1, 4, or 8.
698  *
699  * @param typecode the type
700  * @returns alignment of 1, 4, or 8
701  */
702 int
703 _dbus_type_get_alignment (int typecode)
704 {
705   switch (typecode)
706     {
707     case DBUS_TYPE_BYTE:
708     case DBUS_TYPE_BOOLEAN:
709     case DBUS_TYPE_VARIANT:
710     case DBUS_TYPE_SIGNATURE:
711       return 1;
712     case DBUS_TYPE_INT32:
713     case DBUS_TYPE_UINT32:
714       /* this stuff is 4 since it starts with a length */
715     case DBUS_TYPE_STRING:
716     case DBUS_TYPE_OBJECT_PATH:
717     case DBUS_TYPE_ARRAY:
718       return 4;
719     case DBUS_TYPE_INT64:
720     case DBUS_TYPE_UINT64:
721     case DBUS_TYPE_DOUBLE:
722       /* struct is 8 since it could contain an 8-aligned item
723        * and it's simpler to just always align structs to 8;
724        * we want the amount of padding in a struct of a given
725        * type to be predictable, not location-dependent.
726        */
727     case DBUS_TYPE_STRUCT:
728       return 8;
729
730     default:
731       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
732       return 0;
733     }
734 }
735
736 /**
737  * If in verbose mode, print a block of binary data.
738  *
739  * @todo right now it prints even if not in verbose mode
740  *
741  * @param data the data
742  * @param len the length of the data
743  * @param offset where to start counting for byte indexes
744  */
745 void
746 _dbus_verbose_bytes (const unsigned char *data,
747                      int                  len,
748                      int                  offset)
749 {
750   int i;
751   const unsigned char *aligned;
752
753   _dbus_assert (len >= 0);
754
755   /* Print blanks on first row if appropriate */
756   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
757   if (aligned > data)
758     aligned -= 4;
759   _dbus_assert (aligned <= data);
760
761   if (aligned != data)
762     {
763       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
764       while (aligned != data)
765         {
766           _dbus_verbose ("    ");
767           ++aligned;
768         }
769     }
770
771   /* now print the bytes */
772   i = 0;
773   while (i < len)
774     {
775       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
776         {
777           _dbus_verbose ("%4d\t%p: ",
778                          offset + i, &data[i]);
779         }
780
781       if (data[i] >= 32 &&
782           data[i] <= 126)
783         _dbus_verbose (" '%c' ", data[i]);
784       else
785         _dbus_verbose ("0x%s%x ",
786                        data[i] <= 0xf ? "0" : "", data[i]);
787
788       ++i;
789
790       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
791         {
792           if (i > 3)
793             _dbus_verbose ("BE: %d LE: %d",
794                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
795                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
796
797           if (i > 7 &&
798               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
799             {
800               _dbus_verbose (" dbl: %g",
801                              *(double*)&data[i-8]);
802             }
803
804           _dbus_verbose ("\n");
805         }
806     }
807
808   _dbus_verbose ("\n");
809 }
810
811 /**
812  * Dump the given part of the string to verbose log.
813  *
814  * @param str the string
815  * @param start the start of range to dump
816  * @param len length of range
817  */
818 void
819 _dbus_verbose_bytes_of_string (const DBusString    *str,
820                                int                  start,
821                                int                  len)
822 {
823   const char *d;
824   int real_len;
825
826   real_len = _dbus_string_get_length (str);
827
828   _dbus_assert (start >= 0);
829
830   if (start > real_len)
831     {
832       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
833                      start, len, real_len);
834       return;
835     }
836
837   if ((start + len) > real_len)
838     {
839       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
840                      start, len, real_len);
841       len = real_len - start;
842     }
843
844   d = _dbus_string_get_const_data_len (str, start, len);
845
846   _dbus_verbose_bytes (d, len, start);
847 }
848
849 static dbus_bool_t
850 marshal_4_octets (DBusString   *str,
851                   int           insert_at,
852                   dbus_uint32_t value,
853                   int           byte_order,
854                   int          *pos_after)
855 {
856   dbus_bool_t retval;
857   int orig_len;
858
859   _dbus_assert (sizeof (value) == 4);
860
861   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
862     value = DBUS_UINT32_SWAP_LE_BE (value);
863
864   orig_len = _dbus_string_get_length (str);
865
866   retval = _dbus_string_insert_4_aligned (str, insert_at,
867                                           (const unsigned char *)&value);
868
869   if (pos_after)
870     {
871       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
872       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
873     }
874
875   return retval;
876 }
877
878 static dbus_bool_t
879 marshal_8_octets (DBusString *str,
880                   int         insert_at,
881                   DBusOctets8 value,
882                   int         byte_order,
883                   int        *pos_after)
884 {
885   dbus_bool_t retval;
886   int orig_len;
887
888   _dbus_assert (sizeof (value) == 8);
889
890   swap_8_octets (&value, byte_order);
891
892   orig_len = _dbus_string_get_length (str);
893
894   retval = _dbus_string_insert_8_aligned (str, insert_at,
895                                           (const unsigned char *)&value);
896
897   if (pos_after)
898     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
899
900   return retval;
901 }
902
903 enum
904   {
905     MARSHAL_AS_STRING,
906     MARSHAL_AS_SIGNATURE,
907     MARSHAL_AS_BYTE_ARRAY
908   };
909
910 static dbus_bool_t
911 marshal_len_followed_by_bytes (int                  marshal_as,
912                                DBusString          *str,
913                                int                  insert_at,
914                                const unsigned char *value,
915                                int                  data_len, /* doesn't include nul if any */
916                                int                  byte_order,
917                                int                 *pos_after)
918 {
919   int pos;
920   DBusString value_str;
921   int value_len;
922
923   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
924     value_len = data_len;
925   else
926     value_len = data_len + 1; /* value has a nul */
927
928   /* FIXME this is probably broken for byte arrays because
929    * DBusString wants strings to be nul-terminated?
930    * Maybe I planned on this when writing init_const_len though
931    */
932   _dbus_string_init_const_len (&value_str, value, value_len);
933
934   pos = insert_at;
935
936   if (marshal_as == MARSHAL_AS_SIGNATURE)
937     {
938       if (!_dbus_string_insert_byte (str, pos, data_len))
939         goto oom;
940
941       pos += 1;
942     }
943   else
944     {
945       if (!marshal_4_octets (str, pos, data_len,
946                              byte_order, &pos))
947         goto oom;
948     }
949
950   if (!_dbus_string_copy_len (&value_str, 0, value_len,
951                               str, pos))
952     goto oom;
953
954 #if 1
955   /* too expensive */
956   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
957                                               str, pos));
958   _dbus_verbose_bytes_of_string (str, pos, value_len);
959 #endif
960
961   pos += value_len;
962
963   if (pos_after)
964     *pos_after = pos;
965
966   return TRUE;
967
968  oom:
969   /* Delete what we've inserted */
970   _dbus_string_delete (str, insert_at, pos - insert_at);
971
972   return FALSE;
973 }
974
975 static dbus_bool_t
976 marshal_string (DBusString    *str,
977                 int            insert_at,
978                 const char    *value,
979                 int            byte_order,
980                 int           *pos_after)
981 {
982   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
983                                         str, insert_at, value,
984                                         strlen (value),
985                                         byte_order, pos_after);
986 }
987
988 static dbus_bool_t
989 marshal_signature (DBusString    *str,
990                    int            insert_at,
991                    const char    *value,
992                    int           *pos_after)
993 {
994   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
995                                         str, insert_at, value,
996                                         strlen (value),
997                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
998                                         pos_after);
999 }
1000
1001 /**
1002  * Marshals a basic type. The "value" pointer is always the
1003  * address of a variable containing the basic type value.
1004  * So for example for int32 it will be dbus_int32_t*, and
1005  * for string it will be const char**. This is for symmetry
1006  * with _dbus_demarshal_basic_type() and to have a simple
1007  * consistent rule.
1008  *
1009  * @param str string to marshal to
1010  * @param insert_at where to insert the value
1011  * @param type type of value
1012  * @param value pointer to a variable containing the value
1013  * @param byte_order byte order
1014  * @param pos_after #NULL or the position after the type
1015  * @returns #TRUE on success
1016  **/
1017 dbus_bool_t
1018 _dbus_marshal_basic_type (DBusString *str,
1019                           int         insert_at,
1020                           char        type,
1021                           const void *value,
1022                           int         byte_order,
1023                           int        *pos_after)
1024 {
1025   switch (type)
1026     {
1027     case DBUS_TYPE_BYTE:
1028     case DBUS_TYPE_BOOLEAN:
1029       if (!_dbus_string_insert_byte (str, insert_at, *(const unsigned char *)value))
1030         return FALSE;
1031       if (pos_after)
1032         *pos_after = insert_at + 1;
1033       return TRUE;
1034       break;
1035     case DBUS_TYPE_INT32:
1036     case DBUS_TYPE_UINT32:
1037       return marshal_4_octets (str, insert_at, *(const dbus_uint32_t *)value,
1038                                byte_order, pos_after);
1039       break;
1040 #ifdef DBUS_HAVE_INT64
1041     case DBUS_TYPE_INT64:
1042     case DBUS_TYPE_UINT64:
1043       {
1044         DBusOctets8 r;
1045         r.u = *(const dbus_uint64_t *)value;
1046         return marshal_8_octets (str, insert_at, r, byte_order, pos_after);
1047       }
1048       break;
1049 #endif /* DBUS_HAVE_INT64 */
1050     case DBUS_TYPE_DOUBLE:
1051       {
1052         DBusOctets8 r;
1053         r.d = *(const double *)value;
1054         return marshal_8_octets (str, insert_at, r, byte_order, pos_after);
1055       }
1056       break;
1057     case DBUS_TYPE_STRING:
1058     case DBUS_TYPE_OBJECT_PATH:
1059       return marshal_string (str, insert_at, *(const char**) value, byte_order, pos_after);
1060       break;
1061     case DBUS_TYPE_SIGNATURE:
1062       return marshal_signature (str, insert_at, *(const char**) value, pos_after);
1063       break;
1064     default:
1065       _dbus_assert_not_reached ("not a basic type");
1066       return FALSE;
1067       break;
1068     }
1069 }
1070
1071 static dbus_bool_t
1072 marshal_1_octets_array (DBusString          *str,
1073                         int                  insert_at,
1074                         const unsigned char *value,
1075                         int                  len,
1076                         int                  byte_order,
1077                         int                 *pos_after)
1078 {
1079   return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
1080                                         str, insert_at, value, len,
1081                                         byte_order, pos_after);
1082 }
1083
1084 static dbus_bool_t
1085 marshal_4_octets_array (DBusString          *str,
1086                         int                  insert_at,
1087                         const dbus_uint32_t *value,
1088                         int                  len,
1089                         int                  byte_order)
1090 {
1091   int old_string_len;
1092   int array_start;
1093
1094   _dbus_assert_not_reached ("FIXME insert_at");
1095
1096   old_string_len = _dbus_string_get_length (str);
1097
1098   if (!marshal_4_octets (str, insert_at, len*4, byte_order, NULL))
1099     goto error;
1100
1101   array_start = _dbus_string_get_length (str);
1102
1103   if (!_dbus_string_append_len (str, (const unsigned char*) value,
1104                                 len * 4))
1105     goto error;
1106
1107   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1108     {
1109       const unsigned char *d;
1110       const unsigned char *end;
1111
1112       d = _dbus_string_get_data (str) + array_start;
1113       end = d + len * 4;
1114       while (d != end)
1115         {
1116           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
1117           d += 4;
1118         }
1119     }
1120
1121   return TRUE;
1122
1123  error:
1124   /* Restore previous length */
1125   _dbus_string_set_length (str, old_string_len);
1126
1127   return FALSE;
1128 }
1129
1130 static dbus_bool_t
1131 marshal_8_octets_array (DBusString          *str,
1132                         int                  insert_at,
1133                         const DBusOctets8   *value,
1134                         int                  len,
1135                         int                  byte_order)
1136 {
1137   int old_string_len;
1138   int array_start;
1139
1140   _dbus_assert_not_reached ("FIXME insert_at");
1141
1142   old_string_len = _dbus_string_get_length (str);
1143
1144   /*  The array length is the length in bytes of the array,
1145    * *excluding* alignment padding.
1146    */
1147   if (!marshal_4_octets (str, insert_at, len*8, byte_order, NULL))
1148     goto error;
1149
1150   array_start = _dbus_string_get_length (str);
1151
1152   /* Note that we do alignment padding unconditionally
1153    * even if the array is empty; this means that
1154    * padding + len is always equal to the number of bytes
1155    * in the array.
1156    */
1157
1158   if (!_dbus_string_align_length (str, 8))
1159     goto error;
1160
1161   if (!_dbus_string_append_len (str, (const unsigned char*) value,
1162                                 len * 8))
1163     goto error;
1164
1165   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1166     {
1167       const unsigned char *d;
1168       const unsigned char *end;
1169
1170       d = _dbus_string_get_data (str) + array_start;
1171       end = d + len * 8;
1172       while (d != end)
1173         {
1174 #ifdef DBUS_HAVE_INT64
1175           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
1176 #else
1177           swap_bytes ((unsigned char*) d, 8);
1178 #endif
1179           d += 8;
1180         }
1181     }
1182
1183   return TRUE;
1184
1185  error:
1186   /* Restore previous length */
1187   _dbus_string_set_length (str, old_string_len);
1188
1189   return FALSE;
1190 }
1191
1192 /**
1193  * Marshals a basic type array
1194  *
1195  * @param str string to marshal to
1196  * @param insert_at where to insert the value
1197  * @param element_type type of array elements
1198  * @param value pointer to value
1199  * @param len length of value data in elements
1200  * @param byte_order byte order
1201  * @param pos_after #NULL or the position after the type
1202  * @returns #TRUE on success
1203  **/
1204 dbus_bool_t
1205 _dbus_marshal_basic_type_array (DBusString *str,
1206                                 int         insert_at,
1207                                 char        element_type,
1208                                 const void *value,
1209                                 int         len,
1210                                 int         byte_order,
1211                                 int        *pos_after)
1212 {
1213   /* FIXME use the insert_at arg and fill in pos_after */
1214
1215   switch (element_type)
1216     {
1217     case DBUS_TYPE_BOOLEAN:
1218       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
1219        * should we here too ? */
1220     case DBUS_TYPE_BYTE:
1221       return marshal_1_octets_array (str, insert_at, value, len, byte_order, pos_after);
1222       break;
1223     case DBUS_TYPE_INT32:
1224     case DBUS_TYPE_UINT32:
1225       return marshal_4_octets_array (str, insert_at, value, len, byte_order);
1226       break;
1227 #ifdef DBUS_HAVE_INT64
1228     case DBUS_TYPE_INT64:
1229     case DBUS_TYPE_UINT64:
1230 #endif /* DBUS_HAVE_INT64 */
1231     case DBUS_TYPE_DOUBLE:
1232       return marshal_8_octets_array (str, insert_at, value, len, byte_order);
1233       break;
1234
1235     case DBUS_TYPE_STRING:
1236     case DBUS_TYPE_OBJECT_PATH:
1237       _dbus_assert_not_reached ("handle string arrays");
1238       break;
1239
1240     case DBUS_TYPE_SIGNATURE:
1241       _dbus_assert_not_reached ("handle signature");
1242       break;
1243
1244     default:
1245       _dbus_assert_not_reached ("non basic type in array");
1246       break;
1247     }
1248
1249   return FALSE;
1250 }
1251
1252 /** @} */
1253
1254 #ifdef DBUS_BUILD_TESTS
1255 #include "dbus-test.h"
1256 #include <stdio.h>
1257
1258 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
1259   do {                                                                  \
1260      v_##typename = literal;                                            \
1261      if (!_dbus_marshal_basic_type (&str, pos, DBUS_TYPE_##typename,    \
1262                                     &v_##typename,                      \
1263                                     byte_order, NULL))                  \
1264        _dbus_assert_not_reached ("no memory");                          \
1265    } while (0)
1266
1267 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
1268   do {                                                                          \
1269     _dbus_demarshal_basic_type (&str, DBUS_TYPE_##typename, &v_##typename,      \
1270                                 byte_order, pos, &pos);                         \
1271   } while (0)
1272
1273 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
1274   do {                                                                                  \
1275     DEMARSHAL_BASIC (typename, byte_order);                                             \
1276     if (literal != v_##typename)                                                        \
1277       {                                                                                 \
1278         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1279                                      _dbus_string_get_length (&str) - dump_pos);        \
1280         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1281       }                                                                                 \
1282   } while (0)
1283
1284 #define MARSHAL_TEST(typename, byte_order, literal)             \
1285   do {                                                          \
1286     MARSHAL_BASIC (typename, byte_order, literal);              \
1287     dump_pos = pos;                                             \
1288     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
1289   } while (0)
1290
1291 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
1292   do {                                                                                  \
1293     MARSHAL_BASIC (typename, byte_order, literal);                                      \
1294     dump_pos = pos;                                                                     \
1295     DEMARSHAL_BASIC (typename, byte_order);                                             \
1296     if (strcmp (literal, v_##typename) != 0)                                            \
1297       {                                                                                 \
1298         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1299                                        _dbus_string_get_length (&str) - dump_pos);      \
1300         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
1301         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1302       }                                                                                 \
1303   } while (0)
1304
1305 dbus_bool_t
1306 _dbus_marshal_test (void)
1307 {
1308   DBusString str;
1309   int pos, dump_pos;
1310 #if 0
1311   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
1312 #ifdef DBUS_HAVE_INT64
1313   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1314                              DBUS_INT64_CONSTANT (0x456ffffffff),
1315                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
1316 #endif
1317 #endif
1318   DBusString t;
1319   double v_DOUBLE;
1320   double t_DOUBLE;
1321   dbus_int32_t v_INT32;
1322   dbus_uint32_t v_UINT32;
1323   dbus_int64_t v_INT64;
1324   dbus_uint64_t v_UINT64;
1325   unsigned char v_BYTE;
1326   unsigned char v_BOOLEAN;
1327   const char *v_STRING;
1328   const char *v_SIGNATURE;
1329   const char *v_OBJECT_PATH;
1330   int byte_order;
1331
1332   if (!_dbus_string_init (&str))
1333     _dbus_assert_not_reached ("failed to init string");
1334
1335   pos = 0;
1336
1337   /* Marshal doubles */
1338   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1339   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1340   t_DOUBLE = 3.14;
1341   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1342     _dbus_assert_not_reached ("got wrong double value");
1343
1344   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1345   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1346   t_DOUBLE = 3.14;
1347   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1348     _dbus_assert_not_reached ("got wrong double value");
1349
1350   /* Marshal signed integers */
1351   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1352   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1353
1354   /* Marshal unsigned integers */
1355   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1356   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1357
1358 #ifdef DBUS_HAVE_INT64
1359   /* Marshal signed integers */
1360   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1361   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1362
1363   /* Marshal unsigned integers */
1364   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1365   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1366 #endif /* DBUS_HAVE_INT64 */
1367
1368   /* Marshal byte */
1369   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1370   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1371
1372   /* Marshal all possible bools! */
1373   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1374   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1375   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1376   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1377
1378   /* Marshal strings */
1379   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1380   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1381   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1382   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1383
1384   /* object paths */
1385   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1386   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1387
1388   /* signatures */
1389   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1390   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1391   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1392   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1393
1394   /* set/pack 64-bit integers */
1395   _dbus_string_set_length (&str, 8);
1396
1397   /* signed little */
1398   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1399                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1400
1401   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1402                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1403                                     _dbus_string_get_const_data (&str)));
1404
1405   /* signed big */
1406   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1407                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1408
1409   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1410                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1411                                     _dbus_string_get_const_data (&str)));
1412
1413   /* signed little pack */
1414   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1415                     DBUS_LITTLE_ENDIAN,
1416                     _dbus_string_get_data (&str));
1417
1418   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1419                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1420                                     _dbus_string_get_const_data (&str)));
1421
1422   /* signed big pack */
1423   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1424                     DBUS_BIG_ENDIAN,
1425                     _dbus_string_get_data (&str));
1426
1427   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1428                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1429                                     _dbus_string_get_const_data (&str)));
1430
1431   /* unsigned little */
1432   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1433                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1434
1435   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1436                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1437                                      _dbus_string_get_const_data (&str)));
1438
1439   /* unsigned big */
1440   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1441                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1442
1443   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1444                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1445                                      _dbus_string_get_const_data (&str)));
1446
1447   /* unsigned little pack */
1448   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1449                      DBUS_LITTLE_ENDIAN,
1450                      _dbus_string_get_data (&str));
1451
1452   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1453                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1454                                      _dbus_string_get_const_data (&str)));
1455
1456   /* unsigned big pack */
1457   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1458                      DBUS_BIG_ENDIAN,
1459                      _dbus_string_get_data (&str));
1460
1461   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1462                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1463                                      _dbus_string_get_const_data (&str)));
1464
1465   /* set/pack 32-bit integers */
1466   _dbus_string_set_length (&str, 4);
1467
1468   /* signed little */
1469   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1470                            0, -0x123456);
1471
1472   _dbus_assert (-0x123456 ==
1473                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1474                                     _dbus_string_get_const_data (&str)));
1475
1476   /* signed big */
1477   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1478                            0, -0x123456);
1479
1480   _dbus_assert (-0x123456 ==
1481                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1482                                     _dbus_string_get_const_data (&str)));
1483
1484   /* signed little pack */
1485   _dbus_pack_int32 (-0x123456,
1486                     DBUS_LITTLE_ENDIAN,
1487                     _dbus_string_get_data (&str));
1488
1489   _dbus_assert (-0x123456 ==
1490                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1491                                     _dbus_string_get_const_data (&str)));
1492
1493   /* signed big pack */
1494   _dbus_pack_int32 (-0x123456,
1495                     DBUS_BIG_ENDIAN,
1496                     _dbus_string_get_data (&str));
1497
1498   _dbus_assert (-0x123456 ==
1499                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1500                                     _dbus_string_get_const_data (&str)));
1501
1502   /* unsigned little */
1503   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
1504                             0, 0x123456);
1505
1506   _dbus_assert (0x123456 ==
1507                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1508                                      _dbus_string_get_const_data (&str)));
1509
1510   /* unsigned big */
1511   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
1512                             0, 0x123456);
1513
1514   _dbus_assert (0x123456 ==
1515                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1516                                      _dbus_string_get_const_data (&str)));
1517
1518   /* unsigned little pack */
1519   _dbus_pack_uint32 (0x123456,
1520                      DBUS_LITTLE_ENDIAN,
1521                      _dbus_string_get_data (&str));
1522
1523   _dbus_assert (0x123456 ==
1524                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1525                                      _dbus_string_get_const_data (&str)));
1526
1527   /* unsigned big pack */
1528   _dbus_pack_uint32 (0x123456,
1529                      DBUS_BIG_ENDIAN,
1530                      _dbus_string_get_data (&str));
1531
1532   _dbus_assert (0x123456 ==
1533                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1534                                      _dbus_string_get_const_data (&str)));
1535
1536   /* Strings in-place set */
1537   byte_order = DBUS_LITTLE_ENDIAN;
1538   while (TRUE)
1539     {
1540       /* Init a string */
1541       _dbus_string_set_length (&str, 0);
1542
1543       /* reset pos for the macros */
1544       pos = 0;
1545
1546       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1547
1548       /* Set it to something longer */
1549       _dbus_string_init_const (&t, "Hello world foo");
1550
1551       _dbus_marshal_set_string (&str, byte_order, 0,
1552                                 &t, _dbus_string_get_length (&t));
1553
1554       _dbus_demarshal_basic_type (&str, DBUS_TYPE_STRING,
1555                                   &v_STRING, byte_order,
1556                                   0, NULL);
1557       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
1558
1559       /* Set it to something shorter */
1560       _dbus_string_init_const (&t, "Hello");
1561
1562       _dbus_marshal_set_string (&str, byte_order, 0,
1563                                 &t, _dbus_string_get_length (&t));
1564       _dbus_demarshal_basic_type (&str, DBUS_TYPE_STRING,
1565                                   &v_STRING, byte_order,
1566                                   0, NULL);
1567       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
1568
1569       /* Do the other byte order */
1570       if (byte_order == DBUS_LITTLE_ENDIAN)
1571         byte_order = DBUS_BIG_ENDIAN;
1572       else
1573         break;
1574     }
1575
1576   /* Clean up */
1577   _dbus_string_free (&str);
1578
1579   return TRUE;
1580 }
1581
1582 #endif /* DBUS_BUILD_TESTS */