finish off my TODO list for stuff needed to port dbus-message.c. Next
[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       pos = _DBUS_ALIGN_VALUE (pos, 4);
387       set_4_octets (str, pos, vp->u32, byte_order);
388       if (old_end_pos)
389         *old_end_pos = pos + 4;
390       if (new_end_pos)
391         *new_end_pos = pos + 4;
392       return TRUE;
393       break;
394     case DBUS_TYPE_INT64:
395     case DBUS_TYPE_UINT64:
396     case DBUS_TYPE_DOUBLE:
397       pos = _DBUS_ALIGN_VALUE (pos, 8);
398       set_8_octets (str, pos, *vp, byte_order);
399       if (old_end_pos)
400         *old_end_pos = pos + 8;
401       if (new_end_pos)
402         *new_end_pos = pos + 8;
403       return TRUE;
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 /**
557  * Reads an array of fixed-length basic values.  Does not work for
558  * arrays of string or container types.
559  *
560  * This function returns the array in-place; it does not make a copy,
561  * and it does not swap the bytes.
562  *
563  * If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
564  * and the "value" argument should be a "const double**" and so on.
565  *
566  * @todo last I checked only the test suite uses this function
567  *
568  * @param str the string to read from
569  * @param pos position to read from
570  * @param element_type type of array elements
571  * @param value place to return the array
572  * @param n_elements place to return number of array elements
573  * @param byte_order the byte order, used to read the array length
574  * @param new_pos #NULL or location to store a position after the elements
575  */
576 void
577 _dbus_marshal_read_fixed_array  (const DBusString *str,
578                                  int               pos,
579                                  int               element_type,
580                                  void             *value,
581                                  int              *n_elements,
582                                  int               byte_order,
583                                  int              *new_pos)
584 {
585   dbus_uint32_t array_len;
586   int alignment;
587
588   _dbus_assert (_dbus_type_is_fixed (element_type));
589   _dbus_assert (_dbus_type_is_basic (element_type));
590
591   pos = _DBUS_ALIGN_VALUE (pos, 4);
592
593   array_len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
594
595   alignment = _dbus_type_get_alignment (element_type);
596
597   pos = _DBUS_ALIGN_VALUE (pos, alignment);
598
599   *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
600
601   *n_elements = array_len / alignment;
602
603   if (new_pos)
604     *new_pos = pos + array_len;
605 }
606
607 static dbus_bool_t
608 marshal_4_octets (DBusString   *str,
609                   int           insert_at,
610                   dbus_uint32_t value,
611                   int           byte_order,
612                   int          *pos_after)
613 {
614   dbus_bool_t retval;
615   int orig_len;
616
617   _dbus_assert (sizeof (value) == 4);
618
619   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
620     value = DBUS_UINT32_SWAP_LE_BE (value);
621
622   orig_len = _dbus_string_get_length (str);
623
624   retval = _dbus_string_insert_4_aligned (str, insert_at,
625                                           (const unsigned char *)&value);
626
627   if (pos_after)
628     {
629       *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
630       _dbus_assert (*pos_after <= _dbus_string_get_length (str));
631     }
632
633   return retval;
634 }
635
636 static dbus_bool_t
637 marshal_8_octets (DBusString    *str,
638                   int            insert_at,
639                   DBusBasicValue value,
640                   int            byte_order,
641                   int           *pos_after)
642 {
643   dbus_bool_t retval;
644   int orig_len;
645
646   _dbus_assert (sizeof (value) == 8);
647
648   swap_8_octets (&value, byte_order);
649
650   orig_len = _dbus_string_get_length (str);
651
652   retval = _dbus_string_insert_8_aligned (str, insert_at,
653                                           (const unsigned char *)&value);
654
655   if (pos_after)
656     *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
657
658   return retval;
659 }
660
661 enum
662   {
663     MARSHAL_AS_STRING,
664     MARSHAL_AS_SIGNATURE,
665     MARSHAL_AS_BYTE_ARRAY
666   };
667
668 static dbus_bool_t
669 marshal_len_followed_by_bytes (int                  marshal_as,
670                                DBusString          *str,
671                                int                  insert_at,
672                                const unsigned char *value,
673                                int                  data_len, /* doesn't include nul if any */
674                                int                  byte_order,
675                                int                 *pos_after)
676 {
677   int pos;
678   DBusString value_str;
679   int value_len;
680
681   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
682   if (insert_at > _dbus_string_get_length (str))
683     _dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
684                 insert_at, _dbus_string_get_length (str), data_len);
685
686   if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
687     value_len = data_len;
688   else
689     value_len = data_len + 1; /* value has a nul */
690
691   /* FIXME this is probably broken for byte arrays because
692    * DBusString wants strings to be nul-terminated?
693    * Maybe I planned on this when writing init_const_len though
694    */
695   _dbus_string_init_const_len (&value_str, value, value_len);
696
697   pos = insert_at;
698
699   if (marshal_as == MARSHAL_AS_SIGNATURE)
700     {
701       if (!_dbus_string_insert_byte (str, pos, data_len))
702         goto oom;
703
704       pos += 1;
705     }
706   else
707     {
708       if (!marshal_4_octets (str, pos, data_len,
709                              byte_order, &pos))
710         goto oom;
711     }
712
713   if (!_dbus_string_copy_len (&value_str, 0, value_len,
714                               str, pos))
715     goto oom;
716
717 #if 0
718   /* too expensive */
719   _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
720                                               str, pos));
721   _dbus_verbose_bytes_of_string (str, pos, value_len);
722 #endif
723
724   pos += value_len;
725
726   if (pos_after)
727     *pos_after = pos;
728
729   return TRUE;
730
731  oom:
732   /* Delete what we've inserted */
733   _dbus_string_delete (str, insert_at, pos - insert_at);
734
735   return FALSE;
736 }
737
738 static dbus_bool_t
739 marshal_string (DBusString    *str,
740                 int            insert_at,
741                 const char    *value,
742                 int            byte_order,
743                 int           *pos_after)
744 {
745   return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
746                                         str, insert_at, value,
747                                         strlen (value),
748                                         byte_order, pos_after);
749 }
750
751 static dbus_bool_t
752 marshal_signature (DBusString    *str,
753                    int            insert_at,
754                    const char    *value,
755                    int           *pos_after)
756 {
757   return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
758                                         str, insert_at, value,
759                                         strlen (value),
760                                         DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
761                                         pos_after);
762 }
763
764 /**
765  * Marshals a basic-typed value. The "value" pointer is always the
766  * address of a variable containing the basic type value.
767  * So for example for int32 it will be dbus_int32_t*, and
768  * for string it will be const char**. This is for symmetry
769  * with _dbus_marshal_read_basic() and to have a simple
770  * consistent rule.
771  *
772  * @param str string to marshal to
773  * @param insert_at where to insert the value
774  * @param type type of value
775  * @param value pointer to a variable containing the value
776  * @param byte_order byte order
777  * @param pos_after #NULL or the position after the type
778  * @returns #TRUE on success
779  **/
780 dbus_bool_t
781 _dbus_marshal_write_basic (DBusString *str,
782                            int         insert_at,
783                            int         type,
784                            const void *value,
785                            int         byte_order,
786                            int        *pos_after)
787 {
788   const DBusBasicValue *vp;
789
790   _dbus_assert (_dbus_type_is_basic (type));
791
792   vp = value;
793
794   switch (type)
795     {
796     case DBUS_TYPE_BYTE:
797     case DBUS_TYPE_BOOLEAN:
798       if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
799         return FALSE;
800       if (pos_after)
801         *pos_after = insert_at + 1;
802       return TRUE;
803       break;
804     case DBUS_TYPE_INT32:
805     case DBUS_TYPE_UINT32:
806       return marshal_4_octets (str, insert_at, vp->u32,
807                                byte_order, pos_after);
808       break;
809     case DBUS_TYPE_INT64:
810     case DBUS_TYPE_UINT64:
811     case DBUS_TYPE_DOUBLE:
812       return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
813       break;
814
815     case DBUS_TYPE_STRING:
816     case DBUS_TYPE_OBJECT_PATH:
817       return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
818       break;
819     case DBUS_TYPE_SIGNATURE:
820       return marshal_signature (str, insert_at, vp->str, pos_after);
821       break;
822     default:
823       _dbus_assert_not_reached ("not a basic type");
824       return FALSE;
825       break;
826     }
827 }
828
829 static dbus_bool_t
830 marshal_1_octets_array (DBusString          *str,
831                         int                  insert_at,
832                         const unsigned char *value,
833                         int                  n_elements,
834                         int                  byte_order,
835                         int                 *pos_after)
836 {
837   return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
838                                         str, insert_at, value, n_elements,
839                                         byte_order, pos_after);
840 }
841
842 static void
843 swap_array (DBusString *str,
844             int         array_start,
845             int         n_elements,
846             int         byte_order,
847             int         alignment)
848 {
849   _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
850
851   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
852     {
853       unsigned char *d;
854       unsigned char *end;
855
856       /* we use const_data and cast it off so DBusString can be a const string
857        * for the unit tests. don't ask.
858        */
859       d = (unsigned char*) _dbus_string_get_const_data (str) + array_start;
860       end = d + n_elements * alignment;
861
862       if (alignment == 8)
863         {
864           while (d != end)
865             {
866 #ifdef DBUS_HAVE_INT64
867               *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
868 #else
869               swap_8_bytes ((DBusBasicValue*) d);
870 #endif
871               d += 8;
872             }
873         }
874       else
875         {
876           _dbus_assert (alignment == 4);
877
878           while (d != end)
879             {
880               *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
881               d += 4;
882             }
883         }
884     }
885 }
886
887 static dbus_bool_t
888 marshal_fixed_array (DBusString           *str,
889                      int                   insert_at,
890                      const DBusBasicValue *value,
891                      int                   n_elements,
892                      int                   byte_order,
893                      int                   alignment,
894                      int                  *pos_after)
895 {
896   int old_string_len;
897   int array_start;
898   DBusString t;
899
900   old_string_len = _dbus_string_get_length (str);
901
902   /*  The array length is the length in bytes of the array,
903    * *excluding* alignment padding.
904    */
905   if (!marshal_4_octets (str, insert_at, n_elements * alignment,
906                          byte_order, &array_start))
907     goto error;
908
909   _dbus_verbose ("marshaled len %d at %d array start %d\n", n_elements * alignment, insert_at, array_start);
910
911   /* Note that we do alignment padding unconditionally
912    * even if the array is empty; this means that
913    * padding + len is always equal to the number of bytes
914    * in the array.
915    */
916
917   if (!_dbus_string_insert_alignment (str, &array_start, alignment))
918     goto error;
919
920   _dbus_string_init_const_len (&t,
921                                (const unsigned char*) value,
922                                n_elements * alignment);
923
924   if (!_dbus_string_copy (&t, 0,
925                           str, array_start))
926     goto error;
927
928   swap_array (str, array_start, n_elements, byte_order, alignment);
929
930   return TRUE;
931
932  error:
933   _dbus_string_delete (str, insert_at,
934                        _dbus_string_get_length (str) - old_string_len);
935
936   return FALSE;
937 }
938
939 /**
940  * Marshals an array of values of fixed-length type.
941  * _dbus_type_is_fixed() returns #TRUE for these types,
942  * which are the basic types minus the string-like types.
943  *
944  * The value argument should be the adddress of an
945  * array, so e.g. "const dbus_uint32_t**"
946  *
947  * @param str string to marshal to
948  * @param insert_at where to insert the value
949  * @param element_type type of array elements
950  * @param value address of an array to marshal
951  * @param len number of elements in the array
952  * @param byte_order byte order
953  * @param pos_after #NULL or the position after the type
954  * @returns #TRUE on success
955  **/
956 dbus_bool_t
957 _dbus_marshal_write_fixed_array (DBusString *str,
958                                  int         insert_at,
959                                  int         element_type,
960                                  const void *value,
961                                  int         n_elements,
962                                  int         byte_order,
963                                  int        *pos_after)
964 {
965   const void* vp = *(const DBusBasicValue**)value;
966
967   _dbus_assert (_dbus_type_is_fixed (element_type));
968
969   switch (element_type)
970     {
971     case DBUS_TYPE_BOOLEAN:
972       /* FIXME: we canonicalize to 0 or 1 for the single boolean case
973        * should we here too ? */
974     case DBUS_TYPE_BYTE:
975       return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
976       break;
977     case DBUS_TYPE_INT32:
978     case DBUS_TYPE_UINT32:
979       return marshal_fixed_array (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
980       break;
981     case DBUS_TYPE_INT64:
982     case DBUS_TYPE_UINT64:
983     case DBUS_TYPE_DOUBLE:
984       return marshal_fixed_array (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
985       break;
986
987     default:
988       _dbus_assert_not_reached ("non fixed type in array write");
989       break;
990     }
991
992   return FALSE;
993 }
994
995
996 /**
997  * Skips over a basic-typed value, reporting the following position.
998  *
999  * @param str the string containing the data
1000  * @param type type of value to read
1001  * @param byte_order the byte order
1002  * @param pos pointer to position in the string,
1003  *            updated on return to new position
1004  **/
1005 void
1006 _dbus_marshal_skip_basic (const DBusString      *str,
1007                           int                    type,
1008                           int                    byte_order,
1009                           int                   *pos)
1010 {
1011   switch (type)
1012     {
1013     case DBUS_TYPE_BYTE:
1014     case DBUS_TYPE_BOOLEAN:
1015       (*pos)++;
1016       break;
1017     case DBUS_TYPE_INT32:
1018     case DBUS_TYPE_UINT32:
1019       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1020       *pos += 4;
1021       break;
1022     case DBUS_TYPE_INT64:
1023     case DBUS_TYPE_UINT64:
1024     case DBUS_TYPE_DOUBLE:
1025       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1026       *pos += 8;
1027       break;
1028     case DBUS_TYPE_STRING:
1029     case DBUS_TYPE_OBJECT_PATH:
1030       {
1031         int len;
1032
1033         len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
1034
1035         *pos += len + 1; /* length plus nul */
1036       }
1037       break;
1038     case DBUS_TYPE_SIGNATURE:
1039       {
1040         int len;
1041
1042         len = _dbus_string_get_byte (str, *pos);
1043
1044         *pos += len + 2; /* length byte plus length plus nul */
1045       }
1046       break;
1047     default:
1048       _dbus_warn ("type %s not a basic type\n",
1049                   _dbus_type_to_string (type));
1050       _dbus_assert_not_reached ("not a basic type");
1051       break;
1052     }
1053 }
1054
1055 /**
1056  * Skips an array, returning the next position.
1057  *
1058  * @param str the string containing the data
1059  * @param element_type the type of array elements
1060  * @param byte_order the byte order
1061  * @param pos pointer to position in the string,
1062  *            updated on return to new position
1063  */
1064 void
1065 _dbus_marshal_skip_array (const DBusString  *str,
1066                           int                element_type,
1067                           int                byte_order,
1068                           int               *pos)
1069 {
1070   dbus_uint32_t array_len;
1071   int i;
1072   int alignment;
1073
1074   i = _DBUS_ALIGN_VALUE (*pos, 4);
1075
1076   array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
1077
1078   alignment = _dbus_type_get_alignment (element_type);
1079
1080   i = _DBUS_ALIGN_VALUE (i, alignment);
1081
1082   *pos = i + array_len;
1083 }
1084
1085 /**
1086  * Gets the alignment requirement for the given type;
1087  * will be 1, 4, or 8.
1088  *
1089  * @param typecode the type
1090  * @returns alignment of 1, 4, or 8
1091  */
1092 int
1093 _dbus_type_get_alignment (int typecode)
1094 {
1095   switch (typecode)
1096     {
1097     case DBUS_TYPE_BYTE:
1098     case DBUS_TYPE_BOOLEAN:
1099     case DBUS_TYPE_VARIANT:
1100     case DBUS_TYPE_SIGNATURE:
1101       return 1;
1102     case DBUS_TYPE_INT32:
1103     case DBUS_TYPE_UINT32:
1104       /* this stuff is 4 since it starts with a length */
1105     case DBUS_TYPE_STRING:
1106     case DBUS_TYPE_OBJECT_PATH:
1107     case DBUS_TYPE_ARRAY:
1108       return 4;
1109     case DBUS_TYPE_INT64:
1110     case DBUS_TYPE_UINT64:
1111     case DBUS_TYPE_DOUBLE:
1112       /* struct is 8 since it could contain an 8-aligned item
1113        * and it's simpler to just always align structs to 8;
1114        * we want the amount of padding in a struct of a given
1115        * type to be predictable, not location-dependent.
1116        */
1117     case DBUS_TYPE_STRUCT:
1118       return 8;
1119
1120     default:
1121       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
1122       return 0;
1123     }
1124 }
1125
1126
1127 /**
1128  * Return #TRUE if the typecode is a valid typecode.
1129  * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
1130  * random unknown bytes aren't either. This function is safe with
1131  * untrusted data.
1132  *
1133  * @returns #TRUE if valid
1134  */
1135 dbus_bool_t
1136 _dbus_type_is_valid (int typecode)
1137 {
1138   switch (typecode)
1139     {
1140     case DBUS_TYPE_BYTE:
1141     case DBUS_TYPE_BOOLEAN:
1142     case DBUS_TYPE_INT32:
1143     case DBUS_TYPE_UINT32:
1144     case DBUS_TYPE_INT64:
1145     case DBUS_TYPE_UINT64:
1146     case DBUS_TYPE_DOUBLE:
1147     case DBUS_TYPE_STRING:
1148     case DBUS_TYPE_OBJECT_PATH:
1149     case DBUS_TYPE_SIGNATURE:
1150     case DBUS_TYPE_ARRAY:
1151     case DBUS_TYPE_STRUCT:
1152     case DBUS_TYPE_VARIANT:
1153       return TRUE;
1154
1155     default:
1156       return FALSE;
1157     }
1158 }
1159
1160 #define TYPE_IS_CONTAINER(typecode)             \
1161     ((typecode) == DBUS_TYPE_STRUCT ||          \
1162      (typecode) == DBUS_TYPE_VARIANT ||         \
1163      (typecode) == DBUS_TYPE_ARRAY)
1164
1165 /**
1166  * A "container type" can contain basic types, or nested
1167  * container types. #DBUS_TYPE_INVALID is not a container type.
1168  * This function will crash if passed a typecode that isn't
1169  * in dbus-protocol.h
1170  *
1171  * @returns #TRUE if type is a container
1172  */
1173 dbus_bool_t
1174 _dbus_type_is_container (int typecode)
1175 {
1176   /* only reasonable (non-line-noise) typecodes are allowed */
1177   _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
1178   return TYPE_IS_CONTAINER (typecode);
1179 }
1180
1181 /**
1182  * A "basic type" is a somewhat arbitrary concept, but the intent
1183  * is to include those types that are fully-specified by a single
1184  * typecode, with no additional type information or nested
1185  * values. So all numbers and strings are basic types and
1186  * structs, arrays, and variants are not basic types.
1187  * #DBUS_TYPE_INVALID is not a basic type.
1188  *
1189  * This function is defined to return #TRUE for exactly those
1190  * types that can be written with _dbus_marshal_basic_type()
1191  * and read with _dbus_marshal_read_basic().
1192  *
1193  * This function will crash if passed a typecode that isn't
1194  * in dbus-protocol.h
1195  *
1196  * @returns #TRUE if type is basic
1197  */
1198 dbus_bool_t
1199 _dbus_type_is_basic (int typecode)
1200 {
1201   /* only reasonable (non-line-noise) typecodes are allowed */
1202   _dbus_assert (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID);
1203
1204   /* everything that isn't invalid or a container */
1205   return !(typecode == DBUS_TYPE_INVALID || TYPE_IS_CONTAINER (typecode));
1206 }
1207
1208 /**
1209  * Tells you whether values of this type can change length if you set
1210  * them to some other value. For this purpose, you assume that the
1211  * first byte of the old and new value would be in the same location,
1212  * so alignment padding is not a factor.
1213  *
1214  * @returns #FALSE if the type can occupy different lengths
1215  */
1216 dbus_bool_t
1217 _dbus_type_is_fixed (int typecode)
1218 {
1219   switch (typecode)
1220     {
1221     case DBUS_TYPE_BYTE:
1222     case DBUS_TYPE_BOOLEAN:
1223     case DBUS_TYPE_INT32:
1224     case DBUS_TYPE_UINT32:
1225     case DBUS_TYPE_INT64:
1226     case DBUS_TYPE_UINT64:
1227     case DBUS_TYPE_DOUBLE:
1228       return TRUE;
1229     default:
1230       return FALSE;
1231     }
1232 }
1233
1234 /**
1235  * If in verbose mode, print a block of binary data.
1236  *
1237  * @todo right now it prints even if not in verbose mode
1238  *
1239  * @param data the data
1240  * @param len the length of the data
1241  * @param offset where to start counting for byte indexes
1242  */
1243 void
1244 _dbus_verbose_bytes (const unsigned char *data,
1245                      int                  len,
1246                      int                  offset)
1247 {
1248   int i;
1249   const unsigned char *aligned;
1250
1251   _dbus_assert (len >= 0);
1252
1253   /* Print blanks on first row if appropriate */
1254   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1255   if (aligned > data)
1256     aligned -= 4;
1257   _dbus_assert (aligned <= data);
1258
1259   if (aligned != data)
1260     {
1261       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned);
1262       while (aligned != data)
1263         {
1264           _dbus_verbose ("    ");
1265           ++aligned;
1266         }
1267     }
1268
1269   /* now print the bytes */
1270   i = 0;
1271   while (i < len)
1272     {
1273       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1274         {
1275           _dbus_verbose ("%4d\t%p: ",
1276                          offset + i, &data[i]);
1277         }
1278
1279       if (data[i] >= 32 &&
1280           data[i] <= 126)
1281         _dbus_verbose (" '%c' ", data[i]);
1282       else
1283         _dbus_verbose ("0x%s%x ",
1284                        data[i] <= 0xf ? "0" : "", data[i]);
1285
1286       ++i;
1287
1288       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1289         {
1290           if (i > 3)
1291             _dbus_verbose ("BE: %d LE: %d",
1292                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1293                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1294
1295           if (i > 7 &&
1296               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1297             {
1298 #ifdef DBUS_HAVE_INT64
1299               /* I think I probably mean "GNU libc printf" and not "GNUC"
1300                * but we'll wait until someone complains. If you hit this,
1301                * just turn off verbose mode as a workaround.
1302                */
1303 #if __GNUC__
1304               _dbus_verbose (" u64: 0x%llx",
1305                              *(dbus_uint64_t*)&data[i-8]);
1306 #endif
1307 #endif
1308               _dbus_verbose (" dbl: %g",
1309                              *(double*)&data[i-8]);
1310             }
1311
1312           _dbus_verbose ("\n");
1313         }
1314     }
1315
1316   _dbus_verbose ("\n");
1317 }
1318
1319 /**
1320  * Dump the given part of the string to verbose log.
1321  *
1322  * @param str the string
1323  * @param start the start of range to dump
1324  * @param len length of range
1325  */
1326 void
1327 _dbus_verbose_bytes_of_string (const DBusString    *str,
1328                                int                  start,
1329                                int                  len)
1330 {
1331   const char *d;
1332   int real_len;
1333
1334   real_len = _dbus_string_get_length (str);
1335
1336   _dbus_assert (start >= 0);
1337
1338   if (start > real_len)
1339     {
1340       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1341                      start, len, real_len);
1342       return;
1343     }
1344
1345   if ((start + len) > real_len)
1346     {
1347       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1348                      start, len, real_len);
1349       len = real_len - start;
1350     }
1351
1352   d = _dbus_string_get_const_data_len (str, start, len);
1353
1354   _dbus_verbose_bytes (d, len, start);
1355 }
1356
1357 /** @} */
1358
1359 #ifdef DBUS_BUILD_TESTS
1360 #include "dbus-test.h"
1361 #include <stdio.h>
1362
1363 static void
1364 swap_test_array (void *array,
1365                  int   len_bytes,
1366                  int   byte_order,
1367                  int   alignment)
1368 {
1369   DBusString t;
1370   _dbus_string_init_const_len (&t, array, len_bytes);
1371   swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
1372 }
1373
1374 #define MARSHAL_BASIC(typename, byte_order, literal)                    \
1375   do {                                                                  \
1376      v_##typename = literal;                                            \
1377      if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename,   \
1378                                     &v_##typename,                      \
1379                                     byte_order, NULL))                  \
1380        _dbus_assert_not_reached ("no memory");                          \
1381    } while (0)
1382
1383 #define DEMARSHAL_BASIC(typename, byte_order)                                   \
1384   do {                                                                          \
1385     _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename,   \
1386                               byte_order, &pos);                                \
1387   } while (0)
1388
1389 #define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal)                        \
1390   do {                                                                                  \
1391     DEMARSHAL_BASIC (typename, byte_order);                                             \
1392     if (literal != v_##typename)                                                        \
1393       {                                                                                 \
1394         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1395                                      _dbus_string_get_length (&str) - dump_pos);        \
1396         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1397       }                                                                                 \
1398   } while (0)
1399
1400 #define MARSHAL_TEST(typename, byte_order, literal)             \
1401   do {                                                          \
1402     MARSHAL_BASIC (typename, byte_order, literal);              \
1403     dump_pos = pos;                                             \
1404     DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal);  \
1405   } while (0)
1406
1407 #define MARSHAL_TEST_STRCMP(typename, byte_order, literal)                              \
1408   do {                                                                                  \
1409     MARSHAL_BASIC (typename, byte_order, literal);                                      \
1410     dump_pos = pos;                                                                     \
1411     DEMARSHAL_BASIC (typename, byte_order);                                             \
1412     if (strcmp (literal, v_##typename) != 0)                                            \
1413       {                                                                                 \
1414         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1415                                        _dbus_string_get_length (&str) - dump_pos);      \
1416         _dbus_warn ("literal '%s'\nvalue  '%s'\n", literal, v_##typename);              \
1417         _dbus_assert_not_reached ("demarshaled wrong value");                           \
1418       }                                                                                 \
1419   } while (0)
1420
1421 #define MARSHAL_FIXED_ARRAY(typename, byte_order, literal)                                      \
1422   do {                                                                                          \
1423      v_ARRAY_##typename = literal;                                                              \
1424      if (!_dbus_marshal_write_fixed_array (&str, pos, DBUS_TYPE_##typename,                     \
1425                                            &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal),      \
1426                                            byte_order, NULL))                                   \
1427        _dbus_assert_not_reached ("no memory");                                                  \
1428    } while (0)
1429
1430 #define DEMARSHAL_FIXED_ARRAY(typename, byte_order)                                             \
1431   do {                                                                                          \
1432     _dbus_marshal_read_fixed_array (&str, pos, DBUS_TYPE_##typename, &v_ARRAY_##typename,       \
1433                                     &n_elements, byte_order, &pos);                             \
1434     swap_test_array (v_ARRAY_##typename, n_elements * sizeof(v_ARRAY_##typename[0]),            \
1435                      byte_order, sizeof(v_ARRAY_##typename[0]));                                \
1436   } while (0)
1437
1438 #define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal)                  \
1439   do {                                                                                  \
1440     DEMARSHAL_FIXED_ARRAY (typename, byte_order);                                       \
1441     if (memcmp (literal, v_ARRAY_##typename, sizeof (literal) != 0))                    \
1442       {                                                                                 \
1443         _dbus_verbose ("MARSHALED DATA\n");                                             \
1444         _dbus_verbose_bytes_of_string (&str, dump_pos,                                  \
1445                                       _dbus_string_get_length (&str) - dump_pos);       \
1446         _dbus_verbose ("LITERAL DATA\n");                                               \
1447         _dbus_verbose_bytes ((char*)literal, sizeof (literal), 0);                      \
1448         _dbus_verbose ("READ DATA\n");                                                  \
1449         _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0);           \
1450         _dbus_assert_not_reached ("demarshaled wrong fixed array value");               \
1451       }                                                                                 \
1452   } while (0)
1453
1454 #define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal)         \
1455   do {                                                                  \
1456     MARSHAL_FIXED_ARRAY (typename, byte_order, literal);                \
1457     dump_pos = pos;                                                     \
1458     DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal);    \
1459   } while (0)
1460
1461 dbus_bool_t
1462 _dbus_marshal_test (void)
1463 {
1464   DBusString str;
1465   int pos, dump_pos;
1466   int n_elements;
1467   dbus_int32_t array4[3] = { 123, 456, 789 };
1468 #ifdef DBUS_HAVE_INT64
1469   dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1470                              DBUS_INT64_CONSTANT (0x456ffffffff),
1471                              DBUS_INT64_CONSTANT (0x789ffffffff) };
1472   dbus_int64_t *v_ARRAY_INT64;
1473 #endif
1474   dbus_int32_t *v_ARRAY_INT32;
1475   double *v_ARRAY_DOUBLE;
1476   DBusString t;
1477   double v_DOUBLE;
1478   double t_DOUBLE;
1479   dbus_int32_t v_INT32;
1480   dbus_uint32_t v_UINT32;
1481   dbus_int64_t v_INT64;
1482   dbus_uint64_t v_UINT64;
1483   unsigned char v_BYTE;
1484   unsigned char v_BOOLEAN;
1485   const char *v_STRING;
1486   const char *v_SIGNATURE;
1487   const char *v_OBJECT_PATH;
1488   int byte_order;
1489
1490   if (!_dbus_string_init (&str))
1491     _dbus_assert_not_reached ("failed to init string");
1492
1493   pos = 0;
1494
1495   /* Marshal doubles */
1496   MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1497   DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1498   t_DOUBLE = 3.14;
1499   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1500     _dbus_assert_not_reached ("got wrong double value");
1501
1502   MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1503   DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1504   t_DOUBLE = 3.14;
1505   if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1506     _dbus_assert_not_reached ("got wrong double value");
1507
1508   /* Marshal signed integers */
1509   MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1510   MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1511
1512   /* Marshal unsigned integers */
1513   MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1514   MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1515
1516 #ifdef DBUS_HAVE_INT64
1517   /* Marshal signed integers */
1518   MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1519   MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1520
1521   /* Marshal unsigned integers */
1522   MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1523   MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1524 #endif /* DBUS_HAVE_INT64 */
1525
1526   /* Marshal byte */
1527   MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1528   MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1529
1530   /* Marshal all possible bools! */
1531   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1532   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1533   MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1534   MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1535
1536   /* Marshal strings */
1537   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1538   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1539   MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1540   MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1541
1542   /* object paths */
1543   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1544   MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1545
1546   /* signatures */
1547   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1548   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1549   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1550   MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1551
1552   /* Arrays */
1553   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
1554   MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
1555
1556 #ifdef DBUS_HAVE_INT64
1557   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
1558   MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
1559 #endif
1560
1561 #if 0
1562
1563   /*
1564    * FIXME restore the set/pack tests
1565    */
1566
1567 #ifdef DBUS_HAVE_INT64
1568   /* set/pack 64-bit integers */
1569   _dbus_string_set_length (&str, 8);
1570
1571   /* signed little */
1572   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1573                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1574
1575   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1576                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1577                                     _dbus_string_get_const_data (&str)));
1578
1579   /* signed big */
1580   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1581                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1582
1583   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1584                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1585                                     _dbus_string_get_const_data (&str)));
1586
1587   /* signed little pack */
1588   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1589                     DBUS_LITTLE_ENDIAN,
1590                     _dbus_string_get_data (&str));
1591
1592   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1593                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1594                                     _dbus_string_get_const_data (&str)));
1595
1596   /* signed big pack */
1597   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1598                     DBUS_BIG_ENDIAN,
1599                     _dbus_string_get_data (&str));
1600
1601   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1602                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1603                                     _dbus_string_get_const_data (&str)));
1604
1605   /* unsigned little */
1606   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1607                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1608
1609   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1610                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1611                                      _dbus_string_get_const_data (&str)));
1612
1613   /* unsigned big */
1614   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1615                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1616
1617   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1618                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1619                                      _dbus_string_get_const_data (&str)));
1620
1621   /* unsigned little pack */
1622   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1623                      DBUS_LITTLE_ENDIAN,
1624                      _dbus_string_get_data (&str));
1625
1626   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1627                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1628                                      _dbus_string_get_const_data (&str)));
1629
1630   /* unsigned big pack */
1631   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1632                      DBUS_BIG_ENDIAN,
1633                      _dbus_string_get_data (&str));
1634
1635   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1636                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1637                                      _dbus_string_get_const_data (&str)));
1638 #endif /* DBUS_HAVE_INT64 */
1639
1640   /* set/pack 32-bit integers */
1641   _dbus_string_set_length (&str, 4);
1642
1643   /* signed little */
1644   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1645                            0, -0x123456);
1646
1647   _dbus_assert (-0x123456 ==
1648                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1649                                     _dbus_string_get_const_data (&str)));
1650
1651   /* signed big */
1652   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1653                            0, -0x123456);
1654
1655   _dbus_assert (-0x123456 ==
1656                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1657                                     _dbus_string_get_const_data (&str)));
1658
1659   /* signed little pack */
1660   _dbus_pack_int32 (-0x123456,
1661                     DBUS_LITTLE_ENDIAN,
1662                     _dbus_string_get_data (&str));
1663
1664   _dbus_assert (-0x123456 ==
1665                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1666                                     _dbus_string_get_const_data (&str)));
1667
1668   /* signed big pack */
1669   _dbus_pack_int32 (-0x123456,
1670                     DBUS_BIG_ENDIAN,
1671                     _dbus_string_get_data (&str));
1672
1673   _dbus_assert (-0x123456 ==
1674                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1675                                     _dbus_string_get_const_data (&str)));
1676
1677   /* unsigned little */
1678   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
1679                             0, 0x123456);
1680
1681   _dbus_assert (0x123456 ==
1682                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1683                                      _dbus_string_get_const_data (&str)));
1684
1685   /* unsigned big */
1686   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
1687                             0, 0x123456);
1688
1689   _dbus_assert (0x123456 ==
1690                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1691                                      _dbus_string_get_const_data (&str)));
1692
1693   /* unsigned little pack */
1694   _dbus_pack_uint32 (0x123456,
1695                      DBUS_LITTLE_ENDIAN,
1696                      _dbus_string_get_data (&str));
1697
1698   _dbus_assert (0x123456 ==
1699                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
1700                                      _dbus_string_get_const_data (&str)));
1701
1702   /* unsigned big pack */
1703   _dbus_pack_uint32 (0x123456,
1704                      DBUS_BIG_ENDIAN,
1705                      _dbus_string_get_data (&str));
1706
1707   _dbus_assert (0x123456 ==
1708                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
1709                                      _dbus_string_get_const_data (&str)));
1710
1711 #endif /* set/pack tests for integers */
1712
1713   /* Strings in-place set */
1714   byte_order = DBUS_LITTLE_ENDIAN;
1715   while (TRUE)
1716     {
1717       /* Init a string */
1718       _dbus_string_set_length (&str, 0);
1719
1720       /* reset pos for the macros */
1721       pos = 0;
1722
1723       MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1724
1725       /* Set it to something longer */
1726       _dbus_string_init_const (&t, "Hello world foo");
1727
1728       v_STRING = _dbus_string_get_const_data (&t);
1729       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
1730                                &v_STRING, byte_order, NULL, NULL);
1731
1732       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
1733                                 &v_STRING, byte_order,
1734                                 NULL);
1735       _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
1736
1737       /* Set it to something shorter */
1738       _dbus_string_init_const (&t, "Hello");
1739
1740       v_STRING = _dbus_string_get_const_data (&t);
1741       _dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
1742                                &v_STRING, byte_order, NULL, NULL);
1743       _dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
1744                                 &v_STRING, byte_order,
1745                                 NULL);
1746       _dbus_assert (strcmp (v_STRING, "Hello") == 0);
1747
1748       /* Do the other byte order */
1749       if (byte_order == DBUS_LITTLE_ENDIAN)
1750         byte_order = DBUS_BIG_ENDIAN;
1751       else
1752         break;
1753     }
1754
1755   /* Clean up */
1756   _dbus_string_free (&str);
1757
1758   return TRUE;
1759 }
1760
1761 #endif /* DBUS_BUILD_TESTS */