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