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