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