implement _dbus_type_writer_write_reader() (to copy a block of values)
[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. The "value" pointer is always
485  * the address of a variable of the basic type. So e.g.
486  * if the basic type is "double" then the pointer is
487  * a double*, and if it's "char*" then the pointer is
488  * a "char**".
489  * 
490  * A value of type #DBusBasicValue is guaranteed to be large enough to
491  * hold any of the types that may be returned, which is handy if you
492  * are trying to do things generically. For example you can pass
493  * a DBusBasicValue* in to this function, and then pass the same
494  * DBusBasicValue* in to _dbus_marshal_basic_type() in order to
495  * move a value from one place to another.
496  *
497  * @param str the string containing the data
498  * @param type type of value to demarshal
499  * @param value pointer to return value data
500  * @param byte_order the byte order
501  * @param pos position in the string
502  * @param new_pos pointer to update with new position, or #NULL
503  **/
504 void
505 _dbus_demarshal_basic_type (const DBusString      *str,
506                             int                    type,
507                             void                  *value,
508                             int                    byte_order,
509                             int                    pos,
510                             int                   *new_pos)
511 {
512   const char *str_data;
513   DBusBasicValue *vp;
514
515   str_data = _dbus_string_get_const_data (str);
516   vp = value;
517   
518   switch (type)
519     {
520     case DBUS_TYPE_BYTE:
521     case DBUS_TYPE_BOOLEAN:
522       vp->byt = _dbus_string_get_byte (str, pos);
523       (pos)++;
524       break;
525     case DBUS_TYPE_INT32:
526     case DBUS_TYPE_UINT32:
527       pos = _DBUS_ALIGN_VALUE (pos, 4);
528       vp->u32 = *(dbus_uint32_t *)(str_data + pos);
529       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
530         vp->u32 = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
531       pos += 4;
532       break;
533 #ifdef DBUS_HAVE_INT64
534     case DBUS_TYPE_INT64:
535     case DBUS_TYPE_UINT64:
536 #endif /* DBUS_HAVE_INT64 */
537     case DBUS_TYPE_DOUBLE:
538       pos = _DBUS_ALIGN_VALUE (pos, 8);
539       memcpy (vp, str_data + pos, 8);
540       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
541 #ifdef DBUS_HAVE_INT64
542         vp->u64 = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
543 #else
544       swap_bytes (value, 8);
545 #endif
546       pos += 8;
547       break;
548     case DBUS_TYPE_STRING:
549     case DBUS_TYPE_OBJECT_PATH:
550       {
551         int len;
552
553         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
554
555         vp->str = (char*) str_data + pos;
556
557         pos += len + 1; /* length plus nul */
558       }
559       break;
560     case DBUS_TYPE_SIGNATURE:
561       {
562         int len;
563
564         len = _dbus_string_get_byte (str, pos);
565         pos += 1;
566
567         vp->str = (char*) str_data + pos;
568
569         pos += len + 1; /* length plus nul */
570       }
571       break;
572     default:
573       _dbus_warn ("type %s not a basic type\n",
574                   _dbus_type_to_string (type));
575       _dbus_assert_not_reached ("not a basic type");
576       break;
577     }
578
579   if (new_pos)
580     *new_pos = pos;
581 }
582
583 /**
584  * Skips over a basic type, reporting the following position.
585  *
586  * @param str the string containing the data
587  * @param type type of value to demarshal
588  * @param byte_order the byte order
589  * @param pos pointer to position in the string,
590  *            updated on return to new position
591  **/
592 void
593 _dbus_marshal_skip_basic_type (const DBusString      *str,
594                                int                    type,
595                                int                    byte_order,
596                                int                   *pos)
597 {
598   switch (type)
599     {
600     case DBUS_TYPE_BYTE:
601     case DBUS_TYPE_BOOLEAN:
602       (*pos)++;
603       break;
604     case DBUS_TYPE_INT32:
605     case DBUS_TYPE_UINT32:
606       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
607       *pos += 4;
608       break;
609 #ifdef DBUS_HAVE_INT64
610     case DBUS_TYPE_INT64:
611     case DBUS_TYPE_UINT64:
612 #endif /* DBUS_HAVE_INT64 */
613     case DBUS_TYPE_DOUBLE:
614       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
615       *pos += 8;
616       break;
617     case DBUS_TYPE_STRING:
618     case DBUS_TYPE_OBJECT_PATH:
619       {
620         int len;
621
622         len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos);
623
624         *pos += len + 1; /* length plus nul */
625       }
626       break;
627     case DBUS_TYPE_SIGNATURE:
628       {
629         int len;
630
631         len = _dbus_string_get_byte (str, *pos);
632
633         *pos += len + 2; /* length byte plus length plus nul */
634       }
635       break;
636     default:
637       _dbus_warn ("type %s not a basic type\n",
638                   _dbus_type_to_string (type));
639       _dbus_assert_not_reached ("not a basic type");
640       break;
641     }
642 }
643
644 /**
645  * Skips an array, returning the next position.
646  *
647  * @param str the string containing the data
648  * @param byte_order the byte order
649  * @param pos pointer to position in the string,
650  *            updated on return to new position
651  */
652 void
653 _dbus_marshal_skip_array (const DBusString  *str,
654                           int                byte_order,
655                           int                element_type,
656                           int               *pos)
657 {
658   dbus_uint32_t array_len;
659   int i;
660   int alignment;
661
662   i = _DBUS_ALIGN_VALUE (*pos, 4);
663
664   _dbus_demarshal_basic_type (str,
665                               DBUS_TYPE_UINT32,
666                               &array_len,
667                               byte_order,
668                               i,
669                               &i);
670
671   alignment = _dbus_type_get_alignment (element_type);
672
673   i = _DBUS_ALIGN_VALUE (i, alignment);
674
675   *pos = i + array_len;
676 }
677
678 /**
679  * Return #TRUE if the typecode is a valid typecode
680  *
681  * @returns #TRUE if valid
682  */
683 dbus_bool_t
684 _dbus_type_is_valid (int typecode)
685 {
686   switch (typecode)
687     {
688     case DBUS_TYPE_BYTE:
689     case DBUS_TYPE_BOOLEAN:
690     case DBUS_TYPE_INT32:
691     case DBUS_TYPE_UINT32:
692     case DBUS_TYPE_INT64:
693     case DBUS_TYPE_UINT64:
694     case DBUS_TYPE_DOUBLE:
695     case DBUS_TYPE_STRING:
696     case DBUS_TYPE_OBJECT_PATH:
697     case DBUS_TYPE_SIGNATURE:
698     case DBUS_TYPE_ARRAY:
699     case DBUS_TYPE_STRUCT:
700     case DBUS_TYPE_VARIANT:
701       return TRUE;
702
703     default:
704       return FALSE;
705     }
706 }
707
708 /**
709  * Gets the alignment requirement for the given type;
710  * will be 1, 4, or 8.
711  *
712  * @param typecode the type
713  * @returns alignment of 1, 4, or 8
714  */
715 int
716 _dbus_type_get_alignment (int typecode)
717 {
718   switch (typecode)
719     {
720     case DBUS_TYPE_BYTE:
721     case DBUS_TYPE_BOOLEAN:
722     case DBUS_TYPE_VARIANT:
723     case DBUS_TYPE_SIGNATURE:
724       return 1;
725     case DBUS_TYPE_INT32:
726     case DBUS_TYPE_UINT32:
727       /* this stuff is 4 since it starts with a length */
728     case DBUS_TYPE_STRING:
729     case DBUS_TYPE_OBJECT_PATH:
730     case DBUS_TYPE_ARRAY:
731       return 4;
732     case DBUS_TYPE_INT64:
733     case DBUS_TYPE_UINT64:
734     case DBUS_TYPE_DOUBLE:
735       /* struct is 8 since it could contain an 8-aligned item
736        * and it's simpler to just always align structs to 8;
737        * we want the amount of padding in a struct of a given
738        * type to be predictable, not location-dependent.
739        */
740     case DBUS_TYPE_STRUCT:
741       return 8;
742
743     default:
744       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
745       return 0;
746     }
747 }
748
749 /**
750  * If in verbose mode, print a block of binary data.
751  *
752  * @todo right now it prints even if not in verbose mode
753  *
754  * @param data the data
755  * @param len the length of the data
756  * @param offset where to start counting for byte indexes
757  */
758 void
759 _dbus_verbose_bytes (const unsigned char *data,
760                      int                  len,
761                      int                  offset)
762 {
763   int i;
764   const unsigned char *aligned;
765
766   _dbus_assert (len >= 0);
767
768   /* Print blanks on first row if appropriate */
769   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
770   if (aligned > data)
771     aligned -= 4;
772   _dbus_assert (aligned <= data);
773
774   if (aligned != data)
775     {
776       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
777       while (aligned != data)
778         {
779           _dbus_verbose ("    ");
780           ++aligned;
781         }
782     }
783
784   /* now print the bytes */
785   i = 0;
786   while (i < len)
787     {
788       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
789         {
790           _dbus_verbose ("%4d\t%p: ",
791                          offset + i, &data[i]);
792         }
793
794       if (data[i] >= 32 &&
795           data[i] <= 126)
796         _dbus_verbose (" '%c' ", data[i]);
797       else
798         _dbus_verbose ("0x%s%x ",
799                        data[i] <= 0xf ? "0" : "", data[i]);
800
801       ++i;
802
803       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
804         {
805           if (i > 3)
806             _dbus_verbose ("BE: %d LE: %d",
807                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
808                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
809
810           if (i > 7 &&
811               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
812             {
813               _dbus_verbose (" dbl: %g",
814                              *(double*)&data[i-8]);
815             }
816
817           _dbus_verbose ("\n");
818         }
819     }
820
821   _dbus_verbose ("\n");
822 }
823
824 /**
825  * Dump the given part of the string to verbose log.
826  *
827  * @param str the string
828  * @param start the start of range to dump
829  * @param len length of range
830  */
831 void
832 _dbus_verbose_bytes_of_string (const DBusString    *str,
833                                int                  start,
834                                int                  len)
835 {
836   const char *d;
837   int real_len;
838
839   real_len = _dbus_string_get_length (str);
840
841   _dbus_assert (start >= 0);
842
843   if (start > real_len)
844     {
845       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
846                      start, len, real_len);
847       return;
848     }
849
850   if ((start + len) > real_len)
851     {
852       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
853                      start, len, real_len);
854       len = real_len - start;
855     }
856
857   d = _dbus_string_get_const_data_len (str, start, len);
858
859   _dbus_verbose_bytes (d, len, start);
860 }
861
862 static dbus_bool_t
863 marshal_4_octets (DBusString   *str,
864                   int           insert_at,
865                   dbus_uint32_t value,
866                   int           byte_order,
867                   int          *pos_after)
868 {
869   dbus_bool_t retval;
870   int orig_len;
871
872   _dbus_assert (sizeof (value) == 4);
873
874   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
875     value = DBUS_UINT32_SWAP_LE_BE (value);
876
877   orig_len = _dbus_string_get_length (str);
878
879   retval = _dbus_string_insert_4_aligned (str, insert_at,
880                                           (const unsigned char *)&value);
881
882   if (pos_after)
883     {
884       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
885       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
886     }
887
888   return retval;
889 }
890
891 static dbus_bool_t
892 marshal_8_octets (DBusString *str,
893                   int         insert_at,
894                   DBusOctets8 value,
895                   int         byte_order,
896                   int        *pos_after)
897 {
898   dbus_bool_t retval;
899   int orig_len;
900
901   _dbus_assert (sizeof (value) == 8);
902
903   swap_8_octets (&value, byte_order);
904
905   orig_len = _dbus_string_get_length (str);
906
907   retval = _dbus_string_insert_8_aligned (str, insert_at,
908                                           (const unsigned char *)&value);
909
910   if (pos_after)
911     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
912
913   return retval;
914 }
915
916 enum
917   {
918     MARSHAL_AS_STRING,
919     MARSHAL_AS_SIGNATURE,
920     MARSHAL_AS_BYTE_ARRAY
921   };
922
923 static dbus_bool_t
924 marshal_len_followed_by_bytes (int                  marshal_as,
925                                DBusString          *str,
926                                int                  insert_at,
927                                const unsigned char *value,
928                                int                  data_len, /* doesn't include nul if any */
929                                int                  byte_order,
930                                int                 *pos_after)
931 {
932   int pos;
933   DBusString value_str;
934   int value_len;
935
936   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
937     value_len = data_len;
938   else
939     value_len = data_len + 1; /* value has a nul */
940
941   /* FIXME this is probably broken for byte arrays because
942    * DBusString wants strings to be nul-terminated?
943    * Maybe I planned on this when writing init_const_len though
944    */
945   _dbus_string_init_const_len (&value_str, value, value_len);
946
947   pos = insert_at;
948
949   if (marshal_as == MARSHAL_AS_SIGNATURE)
950     {
951       if (!_dbus_string_insert_byte (str, pos, data_len))
952         goto oom;
953
954       pos += 1;
955     }
956   else
957     {
958       if (!marshal_4_octets (str, pos, data_len,
959                              byte_order, &pos))
960         goto oom;
961     }
962
963   if (!_dbus_string_copy_len (&value_str, 0, value_len,
964                               str, pos))
965     goto oom;
966
967 #if 1
968   /* too expensive */
969   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
970                                               str, pos));
971   _dbus_verbose_bytes_of_string (str, pos, value_len);
972 #endif
973
974   pos += value_len;
975
976   if (pos_after)
977     *pos_after = pos;
978
979   return TRUE;
980
981  oom:
982   /* Delete what we've inserted */
983   _dbus_string_delete (str, insert_at, pos - insert_at);
984
985   return FALSE;
986 }
987
988 static dbus_bool_t
989 marshal_string (DBusString    *str,
990                 int            insert_at,
991                 const char    *value,
992                 int            byte_order,
993                 int           *pos_after)
994 {
995   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
996                                         str, insert_at, value,
997                                         strlen (value),
998                                         byte_order, pos_after);
999 }
1000
1001 static dbus_bool_t
1002 marshal_signature (DBusString    *str,
1003                    int            insert_at,
1004                    const char    *value,
1005                    int           *pos_after)
1006 {
1007   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
1008                                         str, insert_at, value,
1009                                         strlen (value),
1010                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
1011                                         pos_after);
1012 }
1013
1014 /**
1015  * Marshals a basic type. The "value" pointer is always the
1016  * address of a variable containing the basic type value.
1017  * So for example for int32 it will be dbus_int32_t*, and
1018  * for string it will be const char**. This is for symmetry
1019  * with _dbus_demarshal_basic_type() and to have a simple
1020  * consistent rule.
1021  *
1022  * @param str string to marshal to
1023  * @param insert_at where to insert the value
1024  * @param type type of value
1025  * @param value pointer to a variable containing the value
1026  * @param byte_order byte order
1027  * @param pos_after #NULL or the position after the type
1028  * @returns #TRUE on success
1029  **/
1030 dbus_bool_t
1031 _dbus_marshal_basic_type (DBusString *str,
1032                           int         insert_at,
1033                           char        type,
1034                           const void *value,
1035                           int         byte_order,
1036                           int        *pos_after)
1037 {
1038   const DBusBasicValue *vp;
1039
1040   vp = value;
1041   
1042   switch (type)
1043     {
1044     case DBUS_TYPE_BYTE:
1045     case DBUS_TYPE_BOOLEAN:
1046       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
1047         return FALSE;
1048       if (pos_after)
1049         *pos_after = insert_at + 1;
1050       return TRUE;
1051       break;
1052     case DBUS_TYPE_INT32:
1053     case DBUS_TYPE_UINT32:
1054       return marshal_4_octets (str, insert_at, vp->u32,
1055                                byte_order, pos_after);
1056       break;
1057 #ifdef DBUS_HAVE_INT64
1058     case DBUS_TYPE_INT64:
1059     case DBUS_TYPE_UINT64:
1060       {
1061         DBusOctets8 r;
1062         r.u = vp->u64;
1063         return marshal_8_octets (str, insert_at, r, byte_order, pos_after);
1064       }
1065       break;
1066 #endif /* DBUS_HAVE_INT64 */
1067     case DBUS_TYPE_DOUBLE:
1068       {
1069         DBusOctets8 r;
1070         r.d = vp->dbl;
1071         return marshal_8_octets (str, insert_at, r, byte_order, pos_after);
1072       }
1073       break;
1074     case DBUS_TYPE_STRING:
1075     case DBUS_TYPE_OBJECT_PATH:
1076       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
1077       break;
1078     case DBUS_TYPE_SIGNATURE:
1079       return marshal_signature (str, insert_at, vp->str, pos_after);
1080       break;
1081     default:
1082       _dbus_assert_not_reached ("not a basic type");
1083       return FALSE;
1084       break;
1085     }
1086 }
1087
1088 static dbus_bool_t
1089 marshal_1_octets_array (DBusString          *str,
1090                         int                  insert_at,
1091                         const unsigned char *value,
1092                         int                  len,
1093                         int                  byte_order,
1094                         int                 *pos_after)
1095 {
1096   return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
1097                                         str, insert_at, value, len,
1098                                         byte_order, pos_after);
1099 }
1100
1101 static dbus_bool_t
1102 marshal_4_octets_array (DBusString          *str,
1103                         int                  insert_at,
1104                         const dbus_uint32_t *value,
1105                         int                  len,
1106                         int                  byte_order)
1107 {
1108   int old_string_len;
1109   int array_start;
1110
1111   _dbus_assert_not_reached ("FIXME insert_at");
1112
1113   old_string_len = _dbus_string_get_length (str);
1114
1115   if (!marshal_4_octets (str, insert_at, len*4, byte_order, NULL))
1116     goto error;
1117
1118   array_start = _dbus_string_get_length (str);
1119
1120   if (!_dbus_string_append_len (str, (const unsigned char*) value,
1121                                 len * 4))
1122     goto error;
1123
1124   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1125     {
1126       const unsigned char *d;
1127       const unsigned char *end;
1128
1129       d = _dbus_string_get_data (str) + array_start;
1130       end = d + len * 4;
1131       while (d != end)
1132         {
1133           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
1134           d += 4;
1135         }
1136     }
1137
1138   return TRUE;
1139
1140  error:
1141   /* Restore previous length */
1142   _dbus_string_set_length (str, old_string_len);
1143
1144   return FALSE;
1145 }
1146
1147 static dbus_bool_t
1148 marshal_8_octets_array (DBusString          *str,
1149                         int                  insert_at,
1150                         const DBusOctets8   *value,
1151                         int                  len,
1152                         int                  byte_order)
1153 {
1154   int old_string_len;
1155   int array_start;
1156
1157   _dbus_assert_not_reached ("FIXME insert_at");
1158
1159   old_string_len = _dbus_string_get_length (str);
1160
1161   /*  The array length is the length in bytes of the array,
1162    * *excluding* alignment padding.
1163    */
1164   if (!marshal_4_octets (str, insert_at, len*8, byte_order, NULL))
1165     goto error;
1166
1167   array_start = _dbus_string_get_length (str);
1168
1169   /* Note that we do alignment padding unconditionally
1170    * even if the array is empty; this means that
1171    * padding + len is always equal to the number of bytes
1172    * in the array.
1173    */
1174
1175   if (!_dbus_string_align_length (str, 8))
1176     goto error;
1177
1178   if (!_dbus_string_append_len (str, (const unsigned char*) value,
1179                                 len * 8))
1180     goto error;
1181
1182   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1183     {
1184       const unsigned char *d;
1185       const unsigned char *end;
1186
1187       d = _dbus_string_get_data (str) + array_start;
1188       end = d + len * 8;
1189       while (d != end)
1190         {
1191 #ifdef DBUS_HAVE_INT64
1192           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
1193 #else
1194           swap_bytes ((unsigned char*) d, 8);
1195 #endif
1196           d += 8;
1197         }
1198     }
1199
1200   return TRUE;
1201
1202  error:
1203   /* Restore previous length */
1204   _dbus_string_set_length (str, old_string_len);
1205
1206   return FALSE;
1207 }
1208
1209 /**
1210  * Marshals a basic type array
1211  *
1212  * @param str string to marshal to
1213  * @param insert_at where to insert the value
1214  * @param element_type type of array elements
1215  * @param value pointer to value
1216  * @param len length of value data in elements
1217  * @param byte_order byte order
1218  * @param pos_after #NULL or the position after the type
1219  * @returns #TRUE on success
1220  **/
1221 dbus_bool_t
1222 _dbus_marshal_basic_type_array (DBusString *str,
1223                                 int         insert_at,
1224                                 char        element_type,
1225                                 const void *value,
1226                                 int         len,
1227                                 int         byte_order,
1228                                 int        *pos_after)
1229 {
1230   /* FIXME use the insert_at arg and fill in pos_after */
1231
1232   switch (element_type)
1233     {
1234     case DBUS_TYPE_BOOLEAN:
1235       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
1236        * should we here too ? */
1237     case DBUS_TYPE_BYTE:
1238       return marshal_1_octets_array (str, insert_at, value, len, byte_order, pos_after);
1239       break;
1240     case DBUS_TYPE_INT32:
1241     case DBUS_TYPE_UINT32:
1242       return marshal_4_octets_array (str, insert_at, value, len, byte_order);
1243       break;
1244 #ifdef DBUS_HAVE_INT64
1245     case DBUS_TYPE_INT64:
1246     case DBUS_TYPE_UINT64:
1247 #endif /* DBUS_HAVE_INT64 */
1248     case DBUS_TYPE_DOUBLE:
1249       return marshal_8_octets_array (str, insert_at, value, len, byte_order);
1250       break;
1251
1252     case DBUS_TYPE_STRING:
1253     case DBUS_TYPE_OBJECT_PATH:
1254       _dbus_assert_not_reached ("handle string arrays");
1255       break;
1256
1257     case DBUS_TYPE_SIGNATURE:
1258       _dbus_assert_not_reached ("handle signature");
1259       break;
1260
1261     default:
1262       _dbus_assert_not_reached ("non basic type in array");
1263       break;
1264     }
1265
1266   return FALSE;
1267 }
1268
1269 /** @} */
1270
1271 #ifdef DBUS_BUILD_TESTS
1272 #include "dbus-test.h"
1273 #include <stdio.h>
1274
1275 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
1276   do {                                                                  \
1277      v_##typename = literal;                                            \
1278      if (!_dbus_marshal_basic_type (&str, pos, DBUS_TYPE_##typename,    \
1279                                     &v_##typename,                      \
1280                                     byte_order, NULL))                  \
1281        _dbus_assert_not_reached ("no memory");                          \
1282    } while (0)
1283
1284 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
1285   do {                                                                          \
1286     _dbus_demarshal_basic_type (&str, DBUS_TYPE_##typename, &v_##typename,      \
1287                                 byte_order, pos, &pos);                         \
1288   } while (0)
1289
1290 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
1291   do {                                                                                  \
1292     DEMARSHAL_BASIC (typename, byte_order);                                             \
1293     if (literal != v_##typename)                                                        \
1294       {                                                                                 \
1295         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1296                                      _dbus_string_get_length (&str) - dump_pos);        \
1297         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1298       }                                                                                 \
1299   } while (0)
1300
1301 #define MARSHAL_TEST(typename, byte_order, literal)             \
1302   do {                                                          \
1303     MARSHAL_BASIC (typename, byte_order, literal);              \
1304     dump_pos = pos;                                             \
1305     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
1306   } while (0)
1307
1308 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
1309   do {                                                                                  \
1310     MARSHAL_BASIC (typename, byte_order, literal);                                      \
1311     dump_pos = pos;                                                                     \
1312     DEMARSHAL_BASIC (typename, byte_order);                                             \
1313     if (strcmp (literal, v_##typename) != 0)                                            \
1314       {                                                                                 \
1315         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1316                                        _dbus_string_get_length (&str) - dump_pos);      \
1317         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
1318         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1319       }                                                                                 \
1320   } while (0)
1321
1322 dbus_bool_t
1323 _dbus_marshal_test (void)
1324 {
1325   DBusString str;
1326   int pos, dump_pos;
1327 #if 0
1328   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
1329 #ifdef DBUS_HAVE_INT64
1330   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1331                              DBUS_INT64_CONSTANT (0x456ffffffff),
1332                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
1333 #endif
1334 #endif
1335   DBusString t;
1336   double v_DOUBLE;
1337   double t_DOUBLE;
1338   dbus_int32_t v_INT32;
1339   dbus_uint32_t v_UINT32;
1340   dbus_int64_t v_INT64;
1341   dbus_uint64_t v_UINT64;
1342   unsigned char v_BYTE;
1343   unsigned char v_BOOLEAN;
1344   const char *v_STRING;
1345   const char *v_SIGNATURE;
1346   const char *v_OBJECT_PATH;
1347   int byte_order;
1348
1349   if (!_dbus_string_init (&str))
1350     _dbus_assert_not_reached ("failed to init string");
1351
1352   pos = 0;
1353
1354   /* Marshal doubles */
1355   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1356   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1357   t_DOUBLE = 3.14;
1358   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1359     _dbus_assert_not_reached ("got wrong double value");
1360
1361   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1362   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1363   t_DOUBLE = 3.14;
1364   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1365     _dbus_assert_not_reached ("got wrong double value");
1366
1367   /* Marshal signed integers */
1368   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1369   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1370
1371   /* Marshal unsigned integers */
1372   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1373   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1374
1375 #ifdef DBUS_HAVE_INT64
1376   /* Marshal signed integers */
1377   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1378   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1379
1380   /* Marshal unsigned integers */
1381   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1382   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1383 #endif /* DBUS_HAVE_INT64 */
1384
1385   /* Marshal byte */
1386   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1387   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1388
1389   /* Marshal all possible bools! */
1390   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1391   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1392   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1393   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1394
1395   /* Marshal strings */
1396   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1397   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1398   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1399   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1400
1401   /* object paths */
1402   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1403   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1404
1405   /* signatures */
1406   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1407   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1408   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1409   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1410
1411   /* set/pack 64-bit integers */
1412   _dbus_string_set_length (&str, 8);
1413
1414   /* signed little */
1415   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1416                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
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 */
1423   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1424                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1425
1426   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1427                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1428                                     _dbus_string_get_const_data (&str)));
1429
1430   /* signed little pack */
1431   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1432                     DBUS_LITTLE_ENDIAN,
1433                     _dbus_string_get_data (&str));
1434
1435   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1436                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1437                                     _dbus_string_get_const_data (&str)));
1438
1439   /* signed big pack */
1440   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1441                     DBUS_BIG_ENDIAN,
1442                     _dbus_string_get_data (&str));
1443
1444   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1445                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1446                                     _dbus_string_get_const_data (&str)));
1447
1448   /* unsigned little */
1449   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1450                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
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 */
1457   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1458                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1459
1460   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1461                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1462                                      _dbus_string_get_const_data (&str)));
1463
1464   /* unsigned little pack */
1465   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1466                      DBUS_LITTLE_ENDIAN,
1467                      _dbus_string_get_data (&str));
1468
1469   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1470                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1471                                      _dbus_string_get_const_data (&str)));
1472
1473   /* unsigned big pack */
1474   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1475                      DBUS_BIG_ENDIAN,
1476                      _dbus_string_get_data (&str));
1477
1478   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1479                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1480                                      _dbus_string_get_const_data (&str)));
1481
1482   /* set/pack 32-bit integers */
1483   _dbus_string_set_length (&str, 4);
1484
1485   /* signed little */
1486   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1487                            0, -0x123456);
1488
1489   _dbus_assert (-0x123456 ==
1490                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1491                                     _dbus_string_get_const_data (&str)));
1492
1493   /* signed big */
1494   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1495                            0, -0x123456);
1496
1497   _dbus_assert (-0x123456 ==
1498                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1499                                     _dbus_string_get_const_data (&str)));
1500
1501   /* signed little pack */
1502   _dbus_pack_int32 (-0x123456,
1503                     DBUS_LITTLE_ENDIAN,
1504                     _dbus_string_get_data (&str));
1505
1506   _dbus_assert (-0x123456 ==
1507                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1508                                     _dbus_string_get_const_data (&str)));
1509
1510   /* signed big pack */
1511   _dbus_pack_int32 (-0x123456,
1512                     DBUS_BIG_ENDIAN,
1513                     _dbus_string_get_data (&str));
1514
1515   _dbus_assert (-0x123456 ==
1516                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1517                                     _dbus_string_get_const_data (&str)));
1518
1519   /* unsigned little */
1520   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
1521                             0, 0x123456);
1522
1523   _dbus_assert (0x123456 ==
1524                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1525                                      _dbus_string_get_const_data (&str)));
1526
1527   /* unsigned big */
1528   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
1529                             0, 0x123456);
1530
1531   _dbus_assert (0x123456 ==
1532                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1533                                      _dbus_string_get_const_data (&str)));
1534
1535   /* unsigned little pack */
1536   _dbus_pack_uint32 (0x123456,
1537                      DBUS_LITTLE_ENDIAN,
1538                      _dbus_string_get_data (&str));
1539
1540   _dbus_assert (0x123456 ==
1541                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1542                                      _dbus_string_get_const_data (&str)));
1543
1544   /* unsigned big pack */
1545   _dbus_pack_uint32 (0x123456,
1546                      DBUS_BIG_ENDIAN,
1547                      _dbus_string_get_data (&str));
1548
1549   _dbus_assert (0x123456 ==
1550                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1551                                      _dbus_string_get_const_data (&str)));
1552
1553   /* Strings in-place set */
1554   byte_order = DBUS_LITTLE_ENDIAN;
1555   while (TRUE)
1556     {
1557       /* Init a string */
1558       _dbus_string_set_length (&str, 0);
1559
1560       /* reset pos for the macros */
1561       pos = 0;
1562
1563       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1564
1565       /* Set it to something longer */
1566       _dbus_string_init_const (&t, "Hello world foo");
1567
1568       _dbus_marshal_set_string (&str, byte_order, 0,
1569                                 &t, _dbus_string_get_length (&t));
1570
1571       _dbus_demarshal_basic_type (&str, DBUS_TYPE_STRING,
1572                                   &v_STRING, byte_order,
1573                                   0, NULL);
1574       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
1575
1576       /* Set it to something shorter */
1577       _dbus_string_init_const (&t, "Hello");
1578
1579       _dbus_marshal_set_string (&str, byte_order, 0,
1580                                 &t, _dbus_string_get_length (&t));
1581       _dbus_demarshal_basic_type (&str, DBUS_TYPE_STRING,
1582                                   &v_STRING, byte_order,
1583                                   0, NULL);
1584       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
1585
1586       /* Do the other byte order */
1587       if (byte_order == DBUS_LITTLE_ENDIAN)
1588         byte_order = DBUS_BIG_ENDIAN;
1589       else
1590         break;
1591     }
1592
1593   /* Clean up */
1594   _dbus_string_free (&str);
1595
1596   return TRUE;
1597 }
1598
1599 #endif /* DBUS_BUILD_TESTS */