back up some files I'm working on that don't do anything yet
[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 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-marshal-basic.h"
26 #include "dbus-internals.h"
27 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
28 #include "dbus-string-private.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 dbus_uint32_t
48 unpack_4_octets (int                  byte_order,
49                  const unsigned char *data)
50 {
51   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
52   
53   if (byte_order == DBUS_LITTLE_ENDIAN)
54     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
55   else
56     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
57 }
58
59 #ifndef DBUS_HAVE_INT64
60 /* from ORBit */
61 static void
62 swap_bytes (unsigned char *data,
63             unsigned int   len)
64 {
65   unsigned char *p1 = data;
66   unsigned char *p2 = data + len - 1;
67
68   while (p1 < p2)
69     {
70       unsigned char tmp = *p1;
71       *p1 = *p2;
72       *p2 = tmp;
73
74       --p2;
75       ++p1;
76     }
77 }
78 #endif /* !DBUS_HAVE_INT64 */
79
80 /**
81  * Union used to manipulate 8 bytes as if they
82  * were various types. 
83  */
84 typedef union
85 {
86 #ifdef DBUS_HAVE_INT64
87   dbus_int64_t  s; /**< 64-bit integer */
88   dbus_uint64_t u; /**< 64-bit unsinged integer */
89 #endif
90   double d;        /**< double */
91 } DBusOctets8;
92
93 static DBusOctets8
94 unpack_8_octets (int                  byte_order,
95                  const unsigned char *data)
96 {
97   DBusOctets8 r;
98   
99   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
100   _dbus_assert (sizeof (r) == 8);
101   
102 #ifdef DBUS_HAVE_INT64
103   if (byte_order == DBUS_LITTLE_ENDIAN)
104     r.u = DBUS_UINT64_FROM_LE (*(dbus_uint64_t*)data);
105   else
106     r.u = DBUS_UINT64_FROM_BE (*(dbus_uint64_t*)data);
107 #else
108   r.d = *(double*)data;
109   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
110     swap_bytes ((unsigned char*) &r, sizeof (r));
111 #endif
112   
113   return r;
114 }
115
116 /**
117  * Unpacks a 32 bit unsigned integer from a data pointer
118  *
119  * @param byte_order The byte order to use
120  * @param data the data pointer
121  * @returns the integer
122  */
123 dbus_uint32_t
124 _dbus_unpack_uint32 (int                  byte_order,
125                      const unsigned char *data)
126 {
127   return unpack_4_octets (byte_order, data);
128 }  
129
130 /**
131  * Unpacks a 32 bit signed integer from a data pointer
132  *
133  * @param byte_order The byte order to use
134  * @param data the data pointer
135  * @returns the integer
136  */
137 dbus_int32_t
138 _dbus_unpack_int32 (int                  byte_order,
139                     const unsigned char *data)
140 {
141   return (dbus_int32_t) unpack_4_octets (byte_order, data);
142 }
143
144 #ifdef DBUS_HAVE_INT64
145 /**
146  * Unpacks a 64 bit unsigned integer from a data pointer
147  *
148  * @param byte_order The byte order to use
149  * @param data the data pointer
150  * @returns the integer
151  */
152 dbus_uint64_t
153 _dbus_unpack_uint64 (int                  byte_order,
154                      const unsigned char *data)
155 {
156   DBusOctets8 r;
157   
158   r = unpack_8_octets (byte_order, data);
159
160   return r.u;
161 }  
162
163 /**
164  * Unpacks a 64 bit signed integer from a data pointer
165  *
166  * @param byte_order The byte order to use
167  * @param data the data pointer
168  * @returns the integer
169  */
170 dbus_int64_t
171 _dbus_unpack_int64 (int                  byte_order,
172                     const unsigned char *data)
173 {
174   DBusOctets8 r;
175   
176   r = unpack_8_octets (byte_order, data);
177
178   return r.s;
179 }
180
181 #endif /* DBUS_HAVE_INT64 */
182
183 static void
184 pack_4_octets (dbus_uint32_t   value,
185                int             byte_order,
186                unsigned char  *data)
187 {
188   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
189   
190   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
191     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
192   else
193     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
194 }
195
196 static void
197 pack_8_octets (DBusOctets8     value,
198                int             byte_order,
199                unsigned char  *data)
200 {
201   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
202
203 #ifdef DBUS_HAVE_INT64
204   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
205     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u); 
206   else
207     *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u);
208 #else
209   memcpy (data, &value, 8);
210   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
211     swap_bytes ((unsigned char *)data, 8);
212 #endif
213 }
214
215 /**
216  * Packs a 32 bit unsigned integer into a data pointer.
217  *
218  * @param value the value
219  * @param byte_order the byte order to use
220  * @param data the data pointer
221  */
222 void
223 _dbus_pack_uint32 (dbus_uint32_t   value,
224                    int             byte_order,
225                    unsigned char  *data)
226 {
227   pack_4_octets (value, byte_order, data);
228 }
229
230 /**
231  * Packs a 32 bit signed integer into a data pointer.
232  *
233  * @param value the value
234  * @param byte_order the byte order to use
235  * @param data the data pointer
236  */
237 void
238 _dbus_pack_int32 (dbus_int32_t   value,
239                   int            byte_order,
240                   unsigned char *data)
241 {
242   pack_4_octets ((dbus_uint32_t) value, byte_order, data);
243 }
244
245 #ifdef DBUS_HAVE_INT64
246 /**
247  * Packs a 64 bit unsigned integer into a data pointer.
248  *
249  * @param value the value
250  * @param byte_order the byte order to use
251  * @param data the data pointer
252  */
253 void
254 _dbus_pack_uint64 (dbus_uint64_t   value,
255                    int             byte_order,
256                    unsigned char  *data)
257 {
258   DBusOctets8 r;
259   r.u = value;
260   pack_8_octets (r, byte_order, data);
261 }
262
263 /**
264  * Packs a 64 bit signed integer into a data pointer.
265  *
266  * @param value the value
267  * @param byte_order the byte order to use
268  * @param data the data pointer
269  */
270 void
271 _dbus_pack_int64 (dbus_int64_t   value,
272                   int            byte_order,
273                   unsigned char *data)
274 {
275   DBusOctets8 r;
276   r.s = value;
277   pack_8_octets (r, byte_order, data);
278 }
279 #endif /* DBUS_HAVE_INT64 */
280
281 static void
282 set_4_octets (DBusString          *str,
283               int                  byte_order,
284               int                  offset,
285               dbus_uint32_t        value)
286 {
287   char *data;
288   
289   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
290                 byte_order == DBUS_BIG_ENDIAN);
291   
292   data = _dbus_string_get_data_len (str, offset, 4);
293
294   _dbus_pack_uint32 (value, byte_order, data);
295 }
296
297 static void
298 set_8_octets (DBusString          *str,
299               int                  byte_order,
300               int                  offset,
301               DBusOctets8          value)
302 {
303   char *data;
304   
305   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
306                 byte_order == DBUS_BIG_ENDIAN);
307   
308   data = _dbus_string_get_data_len (str, offset, 8);
309
310   pack_8_octets (value, byte_order, data);
311 }
312
313 /**
314  * Sets the 4 bytes at the given offset to a marshaled signed integer,
315  * replacing anything found there previously.
316  *
317  * @param str the string to write the marshalled int to
318  * @param offset the byte offset where int should be written
319  * @param byte_order the byte order to use
320  * @param value the value
321  * 
322  */
323 void
324 _dbus_marshal_set_int32 (DBusString          *str,
325                          int                  byte_order,
326                          int                  offset,
327                          dbus_int32_t         value)
328 {
329   set_4_octets (str, byte_order, offset, (dbus_uint32_t) value);
330 }
331
332 /**
333  * Sets the 4 bytes at the given offset to a marshaled unsigned
334  * integer, replacing anything found there previously.
335  *
336  * @param str the string to write the marshalled int to
337  * @param offset the byte offset where int should be written
338  * @param byte_order the byte order to use
339  * @param value the value
340  * 
341  */
342 void
343 _dbus_marshal_set_uint32 (DBusString          *str,
344                           int                  byte_order,
345                           int                  offset,
346                           dbus_uint32_t        value)
347 {
348   set_4_octets (str, byte_order, offset, value);
349 }
350
351 #ifdef DBUS_HAVE_INT64
352
353 /**
354  * Sets the 8 bytes at the given offset to a marshaled signed integer,
355  * replacing anything found there previously.
356  *
357  * @param str the string to write the marshalled int to
358  * @param offset the byte offset where int should be written
359  * @param byte_order the byte order to use
360  * @param value the value
361  * 
362  */
363 void
364 _dbus_marshal_set_int64 (DBusString          *str,
365                          int                  byte_order,
366                          int                  offset,
367                          dbus_int64_t         value)
368 {
369   DBusOctets8 r;
370   r.s = value;
371   set_8_octets (str, byte_order, offset, r);
372 }
373
374 /**
375  * Sets the 8 bytes at the given offset to a marshaled unsigned
376  * integer, replacing anything found there previously.
377  *
378  * @param str the string to write the marshalled int to
379  * @param offset the byte offset where int should be written
380  * @param byte_order the byte order to use
381  * @param value the value
382  * 
383  */
384 void
385 _dbus_marshal_set_uint64 (DBusString          *str,
386                           int                  byte_order,
387                           int                  offset,
388                           dbus_uint64_t        value)
389 {
390   DBusOctets8 r;
391   r.u = value;
392   set_8_octets (str, byte_order, offset, r);
393 }
394 #endif /* DBUS_HAVE_INT64 */
395
396 /**
397  * Sets the existing marshaled string at the given offset with
398  * a new marshaled string. The given offset must point to
399  * an existing string or the wrong length will be deleted
400  * and replaced with the new string.
401  *
402  * Note: no attempt is made by this function to re-align
403  * any data which has been already marshalled after this
404  * string. Use with caution.
405  *
406  * @param str the string to write the marshalled string to
407  * @param offset the byte offset where string should be written
408  * @param byte_order the byte order to use
409  * @param value the value
410  * @param len the length to use
411  * @returns #TRUE on success
412  * 
413  */
414 dbus_bool_t
415 _dbus_marshal_set_string (DBusString          *str,
416                           int                  byte_order,
417                           int                  offset,
418                           const DBusString    *value,
419                           int                  len)
420 {
421   int old_len;
422   
423   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
424                 byte_order == DBUS_BIG_ENDIAN);
425   
426   old_len = _dbus_demarshal_uint32 (str, byte_order,
427                                     offset, NULL);
428
429   if (!_dbus_string_replace_len (value, 0, len,
430                                  str, offset + 4, old_len))
431     return FALSE;
432
433   _dbus_marshal_set_uint32 (str, byte_order,
434                             offset, len);
435
436   return TRUE;
437 }
438
439 /**
440  * Sets the existing marshaled object path at the given offset to a new
441  * value. The given offset must point to an existing object path or this
442  * function doesn't make sense.
443  *
444  * @todo implement this function
445  *
446  * @param str the string to write the marshalled path to
447  * @param offset the byte offset where path should be written
448  * @param byte_order the byte order to use
449  * @param path the new path
450  * @param path_len number of elements in the path
451  */
452 void
453 _dbus_marshal_set_object_path (DBusString         *str,
454                                int                 byte_order,
455                                int                 offset,
456                                const char        **path,
457                                int                 path_len)
458 {
459
460   /* FIXME */
461 }
462
463 static dbus_bool_t
464 marshal_4_octets (DBusString   *str,
465                   int           byte_order,
466                   dbus_uint32_t value)
467 {
468   _dbus_assert (sizeof (value) == 4);
469   
470   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
471     value = DBUS_UINT32_SWAP_LE_BE (value);
472
473   return _dbus_string_append_4_aligned (str,
474                                         (const unsigned char *)&value);
475 }
476
477 static dbus_bool_t
478 marshal_8_octets (DBusString *str,
479                   int         byte_order,
480                   DBusOctets8 value)
481 {
482   _dbus_assert (sizeof (value) == 8);
483   
484   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
485     pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
486
487   return _dbus_string_append_8_aligned (str,
488                                         (const unsigned char *)&value);
489 }
490
491 /**
492  * Marshals a double value.
493  *
494  * @param str the string to append the marshalled value to
495  * @param byte_order the byte order to use
496  * @param value the value
497  * @returns #TRUE on success
498  */
499 dbus_bool_t
500 _dbus_marshal_double (DBusString *str,
501                       int         byte_order,
502                       double      value)
503 {
504   DBusOctets8 r;
505   r.d = value;
506   return marshal_8_octets (str, byte_order, r);
507 }
508
509 /**
510  * Marshals a 32 bit signed integer value.
511  *
512  * @param str the string to append the marshalled value to
513  * @param byte_order the byte order to use
514  * @param value the value
515  * @returns #TRUE on success
516  */
517 dbus_bool_t
518 _dbus_marshal_int32  (DBusString   *str,
519                       int           byte_order,
520                       dbus_int32_t  value)
521 {
522   return marshal_4_octets (str, byte_order, (dbus_uint32_t) value);
523 }
524
525 /**
526  * Marshals a 32 bit unsigned integer value.
527  *
528  * @param str the string to append the marshalled value to
529  * @param byte_order the byte order to use
530  * @param value the value
531  * @returns #TRUE on success
532  */
533 dbus_bool_t
534 _dbus_marshal_uint32 (DBusString    *str,
535                       int            byte_order,
536                       dbus_uint32_t  value)
537 {
538   return marshal_4_octets (str, byte_order, value);
539 }
540
541
542 #ifdef DBUS_HAVE_INT64
543 /**
544  * Marshals a 64 bit signed integer value.
545  *
546  * @param str the string to append the marshalled value to
547  * @param byte_order the byte order to use
548  * @param value the value
549  * @returns #TRUE on success
550  */
551 dbus_bool_t
552 _dbus_marshal_int64  (DBusString   *str,
553                       int           byte_order,
554                       dbus_int64_t  value)
555 {
556   DBusOctets8 r;
557   r.s = value;
558   return marshal_8_octets (str, byte_order, r);
559 }
560
561 /**
562  * Marshals a 64 bit unsigned integer value.
563  *
564  * @param str the string to append the marshalled value to
565  * @param byte_order the byte order to use
566  * @param value the value
567  * @returns #TRUE on success
568  */
569 dbus_bool_t
570 _dbus_marshal_uint64 (DBusString    *str,
571                       int            byte_order,
572                       dbus_uint64_t  value)
573 {
574   DBusOctets8 r;
575   r.u = value;
576   return marshal_8_octets (str, byte_order, r);
577 }
578
579 #endif /* DBUS_HAVE_INT64 */
580
581 /**
582  * Marshals a UTF-8 string
583  *
584  * @todo: If the string append fails we need to restore
585  * the old length. (also for other marshallers)
586  * 
587  * @param str the string to append the marshalled value to
588  * @param byte_order the byte order to use
589  * @param value the string
590  * @returns #TRUE on success
591  */
592 dbus_bool_t
593 _dbus_marshal_string (DBusString    *str,
594                       int            byte_order,
595                       const char    *value)
596 {
597   int len, old_string_len;
598
599   old_string_len = _dbus_string_get_length (str);
600   
601   len = strlen (value);
602
603   if (!_dbus_marshal_uint32 (str, byte_order, len))
604     {
605       /* Restore the previous length */
606       _dbus_string_set_length (str, old_string_len);
607
608       return FALSE;
609     }
610
611   return _dbus_string_append_len (str, value, len + 1);
612 }
613
614 /**
615  * Marshals a UTF-8 string
616  *
617  * @todo: If the string append fails we need to restore
618  * the old length. (also for other marshallers)
619  * 
620  * @param str the string to append the marshalled value to
621  * @param byte_order the byte order to use
622  * @param value the string
623  * @param len length of string to marshal in bytes
624  * @returns #TRUE on success
625  */
626 dbus_bool_t
627 _dbus_marshal_string_len (DBusString    *str,
628                           int            byte_order,
629                           const char    *value,
630                           int            len)
631 {
632   int old_string_len;
633
634   old_string_len = _dbus_string_get_length (str);
635
636   if (!_dbus_marshal_uint32 (str, byte_order, len))
637     {
638       /* Restore the previous length */
639       _dbus_string_set_length (str, old_string_len);
640
641       return FALSE;
642     }
643
644   if (!_dbus_string_append_len (str, value, len))
645     return FALSE;
646
647   /* add a nul byte */
648   if (!_dbus_string_lengthen (str, 1))
649     return FALSE;
650
651   return TRUE;
652 }
653
654 /**
655  * Marshals a byte array
656  *
657  * @param str the string to append the marshalled value to
658  * @param byte_order the byte order to use
659  * @param value the array
660  * @param len number of elements in the array
661  * @returns #TRUE on success
662  */
663 dbus_bool_t
664 _dbus_marshal_byte_array (DBusString          *str,
665                           int                  byte_order,
666                           const unsigned char *value,
667                           int                  len)
668 {
669   int old_string_len;
670
671   old_string_len = _dbus_string_get_length (str);
672   
673   if (!_dbus_marshal_uint32 (str, byte_order, len))
674     {
675       /* Restore the previous length */
676       _dbus_string_set_length (str, old_string_len);
677
678       return FALSE;
679     }
680
681   if (len == 0)
682     return TRUE;
683   else
684     return _dbus_string_append_len (str, value, len);
685 }
686
687 static dbus_bool_t
688 marshal_4_octets_array (DBusString          *str,
689                         int                  byte_order,
690                         const dbus_uint32_t *value,
691                         int                  len)
692 {
693   int old_string_len;
694   int array_start;
695
696   old_string_len = _dbus_string_get_length (str);
697
698   if (!_dbus_marshal_uint32 (str, byte_order, len * 4))
699     goto error;
700
701   array_start = _dbus_string_get_length (str);
702   
703   if (!_dbus_string_append_len (str, (const unsigned char*) value,
704                                 len * 4))
705     goto error;
706   
707   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
708     {
709       const unsigned char *d;
710       const unsigned char *end;
711       
712       d = _dbus_string_get_data (str) + array_start;
713       end = d + len * 4;
714       while (d != end)
715         {
716           *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
717           d += 4;
718         }
719     }
720
721   return TRUE;
722   
723  error:
724   /* Restore previous length */
725   _dbus_string_set_length (str, old_string_len);
726   
727   return FALSE;  
728 }
729
730 static dbus_bool_t
731 marshal_8_octets_array (DBusString          *str,
732                         int                  byte_order,
733                         const DBusOctets8   *value,
734                         int                  len)
735 {
736   int old_string_len;
737   int array_start;
738
739   old_string_len = _dbus_string_get_length (str);
740
741   if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
742     goto error;
743
744   array_start = _dbus_string_get_length (str);
745   
746   if (!_dbus_string_append_len (str, (const unsigned char*) value,
747                                 len * 8))
748     goto error;
749   
750   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
751     {
752       const unsigned char *d;
753       const unsigned char *end;
754       
755       d = _dbus_string_get_data (str) + array_start;
756       end = d + len * 8;
757       while (d != end)
758         {
759 #ifdef DBUS_HAVE_INT64
760           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
761 #else
762           swap_bytes ((unsigned char*) d, 8);
763 #endif
764           d += 8;
765         }
766     }
767
768   return TRUE;
769   
770  error:
771   /* Restore previous length */
772   _dbus_string_set_length (str, old_string_len);
773   
774   return FALSE;  
775 }
776
777 /**
778  * Marshals a 32 bit signed integer array
779  *
780  * @param str the string to append the marshalled value to
781  * @param byte_order the byte order to use
782  * @param value the array
783  * @param len the length of the array
784  * @returns #TRUE on success
785  */
786 dbus_bool_t
787 _dbus_marshal_int32_array (DBusString         *str,
788                            int                 byte_order,
789                            const dbus_int32_t *value,
790                            int                 len)
791 {
792   return marshal_4_octets_array (str, byte_order,
793                                  (const dbus_uint32_t*) value,
794                                  len);
795 }
796
797 /**
798  * Marshals a 32 bit unsigned integer array
799  *
800  * @param str the string to append the marshalled value to
801  * @param byte_order the byte order to use
802  * @param value the array
803  * @param len the length of the array
804  * @returns #TRUE on success
805  */
806 dbus_bool_t
807 _dbus_marshal_uint32_array (DBusString          *str,
808                             int                  byte_order,
809                             const dbus_uint32_t  *value,
810                             int                  len)
811 {
812   return marshal_4_octets_array (str, byte_order,
813                                  value,
814                                  len);
815 }
816
817 #ifdef DBUS_HAVE_INT64
818
819 /**
820  * Marshals a 64 bit signed integer array
821  *
822  * @param str the string to append the marshalled value to
823  * @param byte_order the byte order to use
824  * @param value the array
825  * @param len the length of the array
826  * @returns #TRUE on success
827  */
828 dbus_bool_t
829 _dbus_marshal_int64_array (DBusString         *str,
830                            int                 byte_order,
831                            const dbus_int64_t *value,
832                            int                 len)
833 {
834   return marshal_8_octets_array (str, byte_order,
835                                  (const DBusOctets8*) value,
836                                  len);
837 }
838
839 /**
840  * Marshals a 64 bit unsigned integer array
841  *
842  * @param str the string to append the marshalled value to
843  * @param byte_order the byte order to use
844  * @param value the array
845  * @param len the length of the array
846  * @returns #TRUE on success
847  */
848 dbus_bool_t
849 _dbus_marshal_uint64_array (DBusString          *str,
850                             int                  byte_order,
851                             const dbus_uint64_t  *value,
852                             int                  len)
853 {
854   return marshal_8_octets_array (str, byte_order,
855                                  (const DBusOctets8*) value,
856                                  len);
857 }
858
859 #endif /* DBUS_HAVE_INT64 */
860
861 /**
862  * Marshals a double array
863  *
864  * @param str the string to append the marshalled value to
865  * @param byte_order the byte order to use
866  * @param value the array
867  * @param len the length of the array
868  * @returns #TRUE on success
869  */
870 dbus_bool_t
871 _dbus_marshal_double_array (DBusString          *str,
872                             int                  byte_order,
873                             const double        *value,
874                             int                  len)
875 {
876   return marshal_8_octets_array (str, byte_order,
877                                  (const DBusOctets8*) value,
878                                  len);
879 }
880
881 /**
882  * Marshals a string array
883  *
884  * @param str the string to append the marshalled value to
885  * @param byte_order the byte order to use
886  * @param value the array
887  * @param len the length of the array
888  * @returns #TRUE on success
889  */
890 dbus_bool_t
891 _dbus_marshal_string_array (DBusString  *str,
892                             int          byte_order,
893                             const char **value,
894                             int          len)
895 {
896   int i, old_string_len, array_start;
897
898   old_string_len = _dbus_string_get_length (str);
899
900   /* Set the length to 0 temporarily */
901   if (!_dbus_marshal_uint32 (str, byte_order, 0))
902     goto error;
903
904   array_start = _dbus_string_get_length (str);
905   
906   for (i = 0; i < len; i++)
907     if (!_dbus_marshal_string (str, byte_order, value[i]))
908       goto error;
909
910   /* Write the length now that we know it */
911   _dbus_marshal_set_uint32 (str, byte_order,
912                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
913                             _dbus_string_get_length (str) - array_start);
914   
915   return TRUE;
916   
917  error:
918   /* Restore previous length */
919   _dbus_string_set_length (str, old_string_len);
920   
921   return FALSE;      
922 }
923
924 /**
925  * Marshals an object path value.
926  * 
927  * @param str the string to append the marshalled value to
928  * @param byte_order the byte order to use
929  * @param path the path
930  * @param path_len length of the path
931  * @returns #TRUE on success
932  */
933 dbus_bool_t
934 _dbus_marshal_object_path (DBusString            *str,
935                            int                    byte_order,
936                            const char           **path,
937                            int                    path_len)
938 {
939   int array_start, old_string_len;
940   int i;
941   
942   old_string_len = _dbus_string_get_length (str);
943   
944   /* Set the length to 0 temporarily */
945   if (!_dbus_marshal_uint32 (str, byte_order, 0))
946     goto nomem;
947
948   array_start = _dbus_string_get_length (str);
949   
950   i = 0;
951   while (i < path_len)
952     {
953       if (!_dbus_string_append_byte (str, '/'))
954         goto nomem;
955       
956       if (!_dbus_string_append (str, path[0]))
957         goto nomem;
958
959       ++i;
960     }
961
962   /* Write the length now that we know it */
963   _dbus_marshal_set_uint32 (str, byte_order,
964                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
965                             _dbus_string_get_length (str) - array_start);  
966
967   return TRUE;
968
969  nomem:
970   /* Restore the previous length */
971   _dbus_string_set_length (str, old_string_len);
972   
973   return FALSE;
974 }
975
976 static dbus_uint32_t
977 demarshal_4_octets (const DBusString *str,
978                     int               byte_order,
979                     int               pos,
980                     int              *new_pos)
981 {
982   const DBusRealString *real = (const DBusRealString*) str;
983   
984   pos = _DBUS_ALIGN_VALUE (pos, 4);
985   
986   if (new_pos)
987     *new_pos = pos + 4;
988
989   return unpack_4_octets (byte_order, real->str + pos);
990 }
991
992 static DBusOctets8
993 demarshal_8_octets (const DBusString *str,
994                     int               byte_order,
995                     int               pos,
996                     int              *new_pos)
997 {
998   const DBusRealString *real = (const DBusRealString*) str;
999   
1000   pos = _DBUS_ALIGN_VALUE (pos, 8);
1001   
1002   if (new_pos)
1003     *new_pos = pos + 8;
1004
1005   return unpack_8_octets (byte_order, real->str + pos);
1006 }
1007
1008 /**
1009  * Demarshals a double.
1010  *
1011  * @param str the string containing the data
1012  * @param byte_order the byte order
1013  * @param pos the position in the string
1014  * @param new_pos the new position of the string
1015  * @returns the demarshaled double.
1016  */
1017 double
1018 _dbus_demarshal_double (const DBusString  *str,
1019                         int                byte_order,
1020                         int                pos,
1021                         int               *new_pos)
1022 {
1023   DBusOctets8 r;
1024
1025   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1026
1027   return r.d;
1028 }
1029
1030 /**
1031  * Demarshals a 32 bit signed integer.
1032  *
1033  * @param str the string containing the data
1034  * @param byte_order the byte order
1035  * @param pos the position in the string
1036  * @param new_pos the new position of the string
1037  * @returns the demarshaled integer.
1038  */
1039 dbus_int32_t
1040 _dbus_demarshal_int32  (const DBusString *str,
1041                         int               byte_order,
1042                         int               pos,
1043                         int              *new_pos)
1044 {
1045   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
1046 }
1047
1048 /**
1049  * Demarshals a 32 bit unsigned integer.
1050  *
1051  * @param str the string containing the data
1052  * @param byte_order the byte order
1053  * @param pos the position in the string
1054  * @param new_pos the new position of the string
1055  * @returns the demarshaled integer.
1056  */
1057 dbus_uint32_t
1058 _dbus_demarshal_uint32  (const DBusString *str,
1059                          int         byte_order,
1060                          int         pos,
1061                          int        *new_pos)
1062 {
1063   return demarshal_4_octets (str, byte_order, pos, new_pos);
1064 }
1065
1066 #ifdef DBUS_HAVE_INT64
1067
1068 /**
1069  * Demarshals a 64 bit signed integer.
1070  *
1071  * @param str the string containing the data
1072  * @param byte_order the byte order
1073  * @param pos the position in the string
1074  * @param new_pos the new position of the string
1075  * @returns the demarshaled integer.
1076  */
1077 dbus_int64_t
1078 _dbus_demarshal_int64  (const DBusString *str,
1079                         int               byte_order,
1080                         int               pos,
1081                         int              *new_pos)
1082 {
1083   DBusOctets8 r;
1084
1085   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1086
1087   return r.s;
1088 }
1089
1090 /**
1091  * Demarshals a 64 bit unsigned integer.
1092  *
1093  * @param str the string containing the data
1094  * @param byte_order the byte order
1095  * @param pos the position in the string
1096  * @param new_pos the new position of the string
1097  * @returns the demarshaled integer.
1098  */
1099 dbus_uint64_t
1100 _dbus_demarshal_uint64  (const DBusString *str,
1101                          int         byte_order,
1102                          int         pos,
1103                          int        *new_pos)
1104 {
1105   DBusOctets8 r;
1106
1107   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1108
1109   return r.u;
1110 }
1111
1112 #endif /* DBUS_HAVE_INT64 */
1113
1114 /**
1115  * Demarshals a basic type
1116  *
1117  * @param str the string containing the data
1118  * @param type type of value to demarshal
1119  * @param value pointer to return value data
1120  * @param byte_order the byte order
1121  * @param pos pointer to position in the string,
1122  *            updated on return to new position
1123  **/
1124 void
1125 _dbus_demarshal_basic_type (const DBusString      *str,
1126                             int                    type,
1127                             void                  *value,
1128                             int                    byte_order,
1129                             int                   *pos)
1130 {
1131   const char *str_data = _dbus_string_get_const_data (str);
1132
1133   switch (type)
1134     {
1135     case DBUS_TYPE_BYTE:
1136     case DBUS_TYPE_BOOLEAN:
1137       *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
1138       (*pos)++;
1139       break;
1140     case DBUS_TYPE_INT32:
1141     case DBUS_TYPE_UINT32:
1142       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1143       *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
1144       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1145         *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
1146       *pos += 4;
1147       break;
1148 #ifdef DBUS_HAVE_INT64
1149     case DBUS_TYPE_INT64:
1150     case DBUS_TYPE_UINT64: 
1151 #endif /* DBUS_HAVE_INT64 */
1152     case DBUS_TYPE_DOUBLE:
1153       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1154       memcpy (value, str_data + *pos, 8);
1155       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1156 #ifdef DBUS_HAVE_INT64
1157         *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
1158 #else   
1159         swap_bytes (value, 8);
1160 #endif
1161       *pos += 8;
1162       break;
1163     default:
1164       _dbus_assert_not_reached ("not a basic type");
1165       break;
1166     }
1167 }
1168
1169 /**
1170  * Demarshals an UTF-8 string.
1171  *
1172  * @todo Should we check the string to make sure
1173  * that it's  valid UTF-8, and maybe "fix" the string
1174  * if it's broken?
1175  *
1176  * @todo Should probably demarshal to a DBusString,
1177  * having memcpy() in here is Evil(tm).
1178  *
1179  * @param str the string containing the data
1180  * @param byte_order the byte order
1181  * @param pos the position in the string
1182  * @param new_pos the new position of the string
1183  * @returns the demarshaled string.
1184  */
1185 char *
1186 _dbus_demarshal_string (const DBusString *str,
1187                         int               byte_order,
1188                         int               pos,
1189                         int              *new_pos)
1190 {
1191   int len;
1192   char *retval;
1193   const char *data;
1194   
1195   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1196
1197   retval = dbus_malloc (len + 1);
1198
1199   if (!retval)
1200     return NULL;
1201
1202   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1203
1204   if (!data)
1205     return NULL;
1206
1207   memcpy (retval, data, len + 1);
1208
1209   if (new_pos)
1210     *new_pos = pos + len + 1;
1211   
1212   return retval;
1213 }
1214
1215 /**
1216  * Demarshals a byte array.
1217  *
1218  * @todo Should probably demarshal to a DBusString,
1219  * having memcpy() in here is Evil(tm).
1220  *
1221  * @param str the string containing the data
1222  * @param byte_order the byte order
1223  * @param pos the position in the string
1224  * @param new_pos the new position of the string
1225  * @param array the array
1226  * @param array_len length of the demarshaled data
1227  
1228  * @returns #TRUE on success
1229  */
1230 dbus_bool_t
1231 _dbus_demarshal_byte_array (const DBusString  *str,
1232                             int                byte_order,
1233                             int                pos,
1234                             int               *new_pos,
1235                             unsigned char    **array,
1236                             int               *array_len)
1237 {
1238   int len;
1239   unsigned char *retval;
1240   const char *data;
1241
1242   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1243
1244   if (len == 0)
1245     {
1246       *array_len = len;
1247       *array = NULL;
1248
1249       if (new_pos)
1250         *new_pos = pos;
1251       
1252       return TRUE;
1253     }
1254   
1255   retval = dbus_malloc (len);
1256
1257   if (!retval)
1258     return FALSE;
1259
1260   data = _dbus_string_get_const_data_len (str, pos, len);
1261
1262   if (!data)
1263     {
1264       dbus_free (retval);
1265       return FALSE;
1266     }
1267
1268   memcpy (retval, data, len);
1269
1270   if (new_pos)
1271     *new_pos = pos + len;
1272
1273   *array = retval;
1274   *array_len = len;
1275   
1276   return TRUE;
1277 }
1278
1279 static dbus_bool_t
1280 demarshal_4_octets_array (const DBusString  *str,
1281                           int                byte_order,
1282                           int                pos,
1283                           int               *new_pos,
1284                           dbus_uint32_t    **array,
1285                           int               *array_len)
1286 {
1287   int len, i;
1288   dbus_uint32_t *retval;
1289   int byte_len;
1290   
1291   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1292   len = byte_len / 4;
1293
1294   if (len == 0)
1295     {
1296       *array_len = 0;
1297       *array = NULL;
1298
1299       if (new_pos)
1300         *new_pos = pos;
1301       
1302       return TRUE;
1303     }
1304
1305   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1306                                    pos, byte_len))
1307     return FALSE;
1308   
1309   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1310     {
1311       for (i = 0; i < len; i++)
1312         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1313     }
1314
1315   if (new_pos)
1316     *new_pos = pos + byte_len;
1317
1318   *array_len = len;
1319   *array = retval;
1320   
1321   return TRUE;  
1322 }
1323
1324 static dbus_bool_t
1325 demarshal_8_octets_array (const DBusString  *str,
1326                           int                byte_order,
1327                           int                pos,
1328                           int               *new_pos,
1329                           DBusOctets8      **array,
1330                           int               *array_len)
1331 {
1332   int len, i;
1333   DBusOctets8 *retval;
1334   int byte_len;
1335   
1336   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1337   len = byte_len / 8;
1338
1339   if (len == 0)
1340     {
1341       *array_len = 0;
1342       *array = NULL;
1343
1344       if (new_pos)
1345         *new_pos = pos;
1346       
1347       return TRUE;
1348     }
1349
1350   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1351                                    pos, byte_len))
1352     return FALSE;
1353   
1354   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1355     {
1356       for (i = 0; i < len; i++)
1357         {
1358 #ifdef DBUS_HAVE_INT64
1359           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1360 #else
1361           swap_bytes ((unsigned char *) &retval[i], 8);
1362 #endif
1363         }
1364     }
1365
1366   if (new_pos)
1367     *new_pos = pos + byte_len;
1368
1369   *array_len = len;
1370   *array = retval;
1371   
1372   return TRUE;  
1373 }
1374
1375 /**
1376  * Demarshals a 32 bit signed integer array.
1377  *
1378  * @param str the string containing the data
1379  * @param byte_order the byte order
1380  * @param pos the position in the string
1381  * @param new_pos the new position of the string
1382  * @param array the array
1383  * @param array_len length of the demarshaled data
1384  * @returns #TRUE on success
1385  */
1386 dbus_bool_t
1387 _dbus_demarshal_int32_array (const DBusString  *str,
1388                              int                byte_order,
1389                              int                pos,
1390                              int               *new_pos,
1391                              dbus_int32_t     **array,
1392                              int               *array_len)
1393 {
1394   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1395                                    (dbus_uint32_t**) array, array_len);
1396 }
1397
1398 /**
1399  * Demarshals a 32 bit unsigned integer array.
1400  *
1401  * @param str the string containing the data
1402  * @param byte_order the byte order
1403  * @param pos the position in the string
1404  * @param new_pos the new position of the string
1405  * @param array the array
1406  * @param array_len length of the demarshaled data
1407  * @returns #TRUE on success
1408  */
1409 dbus_bool_t
1410 _dbus_demarshal_uint32_array (const DBusString  *str,
1411                               int                byte_order,
1412                               int                pos,
1413                               int               *new_pos,
1414                               dbus_uint32_t    **array,
1415                               int               *array_len)
1416 {
1417   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1418                                    array, array_len);
1419 }
1420
1421 #ifdef DBUS_HAVE_INT64
1422
1423 /**
1424  * Demarshals a 64 bit signed integer array.
1425  *
1426  * @param str the string containing the data
1427  * @param byte_order the byte order
1428  * @param pos the position in the string
1429  * @param new_pos the new position of the string
1430  * @param array the array
1431  * @param array_len length of the demarshaled data
1432  * @returns #TRUE on success
1433  */
1434 dbus_bool_t
1435 _dbus_demarshal_int64_array (const DBusString  *str,
1436                              int                byte_order,
1437                              int                pos,
1438                              int               *new_pos,
1439                              dbus_int64_t     **array,
1440                              int               *array_len)
1441 {
1442   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1443                                    (DBusOctets8**) array, array_len);
1444 }
1445
1446 /**
1447  * Demarshals a 64 bit unsigned integer array.
1448  *
1449  * @param str the string containing the data
1450  * @param byte_order the byte order
1451  * @param pos the position in the string
1452  * @param new_pos the new position of the string
1453  * @param array the array
1454  * @param array_len length of the demarshaled data
1455  * @returns #TRUE on success
1456  */
1457 dbus_bool_t
1458 _dbus_demarshal_uint64_array (const DBusString  *str,
1459                               int                byte_order,
1460                               int                pos,
1461                               int               *new_pos,
1462                               dbus_uint64_t    **array,
1463                               int               *array_len)
1464 {
1465   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1466                                    (DBusOctets8**) array, array_len);
1467 }
1468
1469 #endif /* DBUS_HAVE_INT64 */
1470
1471 /**
1472  * Demarshals a double array.
1473  *
1474  * @param str the string containing the data
1475  * @param byte_order the byte order
1476  * @param pos the position in the string
1477  * @param new_pos the new position of the string
1478  * @param array the array
1479  * @param array_len length of the demarshaled data
1480  * @returns #TRUE on success
1481  */
1482 dbus_bool_t
1483 _dbus_demarshal_double_array (const DBusString  *str,
1484                               int                byte_order,
1485                               int                pos,
1486                               int               *new_pos,
1487                               double           **array,
1488                               int               *array_len)
1489 {
1490   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1491                                    (DBusOctets8**) array, array_len);
1492 }
1493
1494
1495 /**
1496  * Demarshals an array of basic types
1497  *
1498  * @param str the string containing the data
1499  * @param element_type type of array elements to demarshal
1500  * @param array pointer to pointer to array data
1501  * @param array_len pointer to array length
1502  * @param byte_order the byte order
1503  * @param pos pointer to position in the string,
1504  *            updated on return to new position
1505  **/
1506 dbus_bool_t
1507 _dbus_demarshal_basic_type_array (const DBusString      *str,
1508                                   int                    element_type,
1509                                   void                 **array,
1510                                   int                   *array_len,
1511                                   int                    byte_order,
1512                                   int                   *pos)
1513 {
1514   switch (element_type)
1515     {
1516     case DBUS_TYPE_BOOLEAN:
1517       /* FIXME: do we want to post-normalize these ? */
1518     case DBUS_TYPE_BYTE:
1519       return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
1520                                          (unsigned char **)array, array_len);
1521       break;
1522     case DBUS_TYPE_INT32:
1523     case DBUS_TYPE_UINT32:
1524       return demarshal_4_octets_array (str, byte_order, *pos, pos,
1525                                        (dbus_uint32_t **)array, array_len);
1526       break;
1527 #ifdef DBUS_HAVE_INT64
1528     case DBUS_TYPE_INT64:
1529     case DBUS_TYPE_UINT64: 
1530 #endif /* DBUS_HAVE_INT64 */
1531     case DBUS_TYPE_DOUBLE:
1532       return demarshal_8_octets_array (str, byte_order, *pos, pos,
1533                                        (DBusOctets8**) array, array_len);
1534     default:
1535       _dbus_assert_not_reached ("not a basic type");
1536       break;
1537     }
1538   return FALSE;
1539 }
1540
1541 /**
1542  * Demarshals a string array.
1543  *
1544  * @param str the string containing the data
1545  * @param byte_order the byte order
1546  * @param pos the position in the string
1547  * @param new_pos the new position of the string
1548  * @param array the array
1549  * @param array_len location for length of the demarshaled data or NULL
1550  * @returns #TRUE on success
1551  */
1552 dbus_bool_t
1553 _dbus_demarshal_string_array (const DBusString   *str,
1554                               int                 byte_order,
1555                               int                 pos,
1556                               int                *new_pos,
1557                               char             ***array,
1558                               int                *array_len)
1559 {
1560   int bytes_len, i;
1561   int len, allocated;
1562   int end_pos;
1563   char **retval;
1564   
1565   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1566   
1567   if (bytes_len == 0)
1568     {
1569       *array_len = 0;
1570       *array = NULL;
1571
1572       if (new_pos)
1573         *new_pos = pos;
1574       
1575       return TRUE;
1576     }
1577
1578   len = 0;
1579   allocated = 4;
1580   end_pos = pos + bytes_len;
1581   
1582   retval = dbus_new (char *, allocated);
1583
1584   if (!retval)
1585     return FALSE;
1586
1587   while (pos < end_pos)
1588     {
1589       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1590       
1591       if (retval[len] == NULL)
1592         goto error;
1593       
1594       len += 1;
1595
1596       if (len >= allocated - 1) /* -1 for NULL termination */
1597         {
1598           char **newp;
1599           newp = dbus_realloc (retval,
1600                                sizeof (char*) * allocated * 2);
1601           if (newp == NULL)
1602             goto error;
1603
1604           allocated *= 2;
1605           retval = newp;
1606         }
1607     }
1608       
1609   retval[len] = NULL;
1610
1611   if (new_pos)
1612     *new_pos = pos;
1613   
1614   *array = retval;
1615   *array_len = len;
1616   
1617   return TRUE;
1618
1619  error:
1620   for (i = 0; i < len; i++)
1621     dbus_free (retval[i]);
1622   dbus_free (retval);
1623
1624   return FALSE;
1625 }
1626
1627 /** Set to 1 to get a bunch of spew about disassembling the path string */
1628 #define VERBOSE_DECOMPOSE 0
1629
1630 /**
1631  * Decompose an object path.  A path of just "/" is
1632  * represented as an empty vector of strings.
1633  * 
1634  * @param data the path data
1635  * @param len  the length of the path string
1636  * @param path address to store new object path
1637  * @param path_len length of stored path
1638  */
1639 dbus_bool_t
1640 _dbus_decompose_path (const char*     data,
1641                       int             len,
1642                       char         ***path,
1643                       int            *path_len)
1644 {
1645   char **retval;
1646   int n_components;
1647   int i, j, comp;
1648
1649   _dbus_assert (data != NULL);
1650
1651 #if VERBOSE_DECOMPOSE
1652   _dbus_verbose ("Decomposing path \"%s\"\n",
1653                  data);
1654 #endif
1655   
1656   n_components = 0;
1657   i = 0;
1658   while (i < len)
1659     {
1660       if (data[i] == '/')
1661         n_components += 1;
1662       ++i;
1663     }
1664   
1665   retval = dbus_new0 (char*, n_components + 1);
1666
1667   if (retval == NULL)
1668     return FALSE;
1669
1670   comp = 0;
1671   i = 0;
1672   while (i < len)
1673     {
1674       if (data[i] == '/')
1675         ++i;
1676       j = i;
1677
1678       while (j < len && data[j] != '/')
1679         ++j;
1680
1681       /* Now [i, j) is the path component */
1682       _dbus_assert (i < j);
1683       _dbus_assert (data[i] != '/');
1684       _dbus_assert (j == len || data[j] == '/');
1685
1686 #if VERBOSE_DECOMPOSE
1687       _dbus_verbose ("  (component in [%d,%d))\n",
1688                      i, j);
1689 #endif
1690       
1691       retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1692       if (retval[comp] == NULL)
1693         {
1694           dbus_free_string_array (retval);
1695           return FALSE;
1696         }
1697       retval[comp][j-i] = '\0';
1698 #if VERBOSE_DECOMPOSE
1699       _dbus_verbose ("  (component %d = \"%s\")\n",
1700                      comp, retval[comp]);
1701 #endif
1702
1703       ++comp;
1704       i = j;
1705     }
1706   _dbus_assert (i == len);
1707   
1708   *path = retval;
1709   if (path_len)
1710     *path_len = n_components;
1711   
1712   return TRUE;
1713 }
1714
1715 /**
1716  * Demarshals an object path.  A path of just "/" is
1717  * represented as an empty vector of strings.
1718  * 
1719  * @param str the string containing the data
1720  * @param byte_order the byte order
1721  * @param pos the position in the string
1722  * @param new_pos the new position of the string
1723  * @param path address to store new object path
1724  * @param path_len length of stored path
1725  */
1726 dbus_bool_t
1727 _dbus_demarshal_object_path (const DBusString *str,
1728                              int               byte_order,
1729                              int               pos,
1730                              int              *new_pos,
1731                              char           ***path,
1732                              int              *path_len)
1733 {
1734   int len;
1735   const char *data;
1736   
1737   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1738   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1739
1740   if (!_dbus_decompose_path (data, len, path, path_len))
1741     return FALSE;
1742
1743   if (new_pos)
1744     *new_pos = pos + len + 1;
1745
1746   return TRUE;
1747 }
1748
1749 /** 
1750  * Returns the position right after the end of an argument.  PERFORMS
1751  * NO VALIDATION WHATSOEVER. The message must have been previously
1752  * validated.
1753  *
1754  * @param str a string
1755  * @param byte_order the byte order to use
1756  * @param type the type of the argument
1757  * @param pos the pos where the arg starts
1758  * @param end_pos pointer where the position right
1759  * after the end position will follow
1760  * @returns TRUE if more data exists after the arg
1761  */
1762 dbus_bool_t
1763 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1764                                int               byte_order,
1765                                int               type,
1766                                int               pos,
1767                                int              *end_pos)
1768 {
1769   if (pos >= _dbus_string_get_length (str))
1770     return FALSE;
1771
1772   switch (type)
1773     {
1774     case DBUS_TYPE_INVALID:
1775       return FALSE;
1776       break;
1777
1778     case DBUS_TYPE_NIL:
1779       *end_pos = pos;
1780       break;
1781
1782     case DBUS_TYPE_BYTE:
1783       *end_pos = pos + 1;
1784       break;
1785       
1786     case DBUS_TYPE_BOOLEAN:
1787       *end_pos = pos + 1;
1788       break;
1789
1790     case DBUS_TYPE_INT32:
1791     case DBUS_TYPE_UINT32:
1792       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1793       break;
1794
1795     case DBUS_TYPE_INT64:
1796     case DBUS_TYPE_UINT64:
1797     case DBUS_TYPE_DOUBLE:
1798       
1799       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1800       break;
1801
1802     case DBUS_TYPE_OBJECT_PATH:
1803     case DBUS_TYPE_STRING:
1804       {
1805         int len;
1806         
1807         /* Demarshal the length */
1808         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1809
1810         *end_pos = pos + len + 1;
1811       }
1812       break;
1813
1814     case DBUS_TYPE_CUSTOM:
1815       {
1816         int len;
1817         
1818         /* Demarshal the string length */
1819         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1820
1821         pos += len + 1;
1822         
1823         /* Demarshal the data length */
1824         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1825
1826         *end_pos = pos + len;
1827       }
1828       break;
1829       
1830     case DBUS_TYPE_ARRAY:
1831       {
1832         int len;
1833
1834         /* Demarshal the length  */
1835         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1836         
1837         *end_pos = pos + len;
1838       }
1839       break;
1840
1841     case DBUS_TYPE_DICT:
1842       {
1843         int len;
1844
1845         /* Demarshal the length */
1846         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1847         
1848         *end_pos = pos + len;
1849       }
1850       break;
1851       
1852     default:
1853       _dbus_warn ("Unknown message arg type %d\n", type);
1854       _dbus_assert_not_reached ("Unknown message argument type\n");
1855       return FALSE;
1856     }
1857
1858   if (*end_pos > _dbus_string_get_length (str))
1859     return FALSE;
1860   
1861   return TRUE;
1862 }
1863
1864 /**
1865  * Demarshals and validates a length; returns < 0 if the validation
1866  * fails. The length is required to be small enough that
1867  * len*sizeof(double) will not overflow, and small enough to fit in a
1868  * signed integer. DOES NOT check whether the length points
1869  * beyond the end of the string, because it doesn't know the
1870  * size of array elements.
1871  *
1872  * @param str the string
1873  * @param byte_order the byte order
1874  * @param pos the unaligned string position (snap to next aligned)
1875  * @param new_pos return location for new position.
1876  */
1877 static int
1878 demarshal_and_validate_len (const DBusString *str,
1879                             int               byte_order,
1880                             int               pos,
1881                             int              *new_pos)
1882 {
1883   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1884   unsigned int len;
1885
1886   _dbus_assert (new_pos != NULL);
1887   
1888   if ((align_4 + 4) > _dbus_string_get_length (str))
1889     {
1890       _dbus_verbose ("not enough room in message for array length\n");
1891       return -1;
1892     }
1893   
1894   if (!_dbus_string_validate_nul (str, pos,
1895                                   align_4 - pos))
1896     {
1897       _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
1898       return -1;
1899     }
1900
1901   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1902
1903   /* note that the len is the number of bytes, so we need it to be
1904    * at least SIZE_T_MAX, but make it smaller just to keep things
1905    * sane.  We end up using ints for most sizes to avoid unsigned mess
1906    * so limit to maximum 32-bit signed int divided by at least 8, more
1907    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1908    */  
1909 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1910   if (len > MAX_ARRAY_LENGTH)
1911     {
1912       _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
1913                      len, MAX_ARRAY_LENGTH, pos);
1914       return -1;
1915     }
1916   else
1917     return (int) len;
1918 }
1919
1920 static dbus_bool_t
1921 validate_string (const DBusString *str,
1922                  int               pos,
1923                  int               len_without_nul,
1924                  int              *end_pos)
1925 {
1926   *end_pos = pos + len_without_nul + 1;
1927   
1928   if (*end_pos > _dbus_string_get_length (str))
1929     {
1930       _dbus_verbose ("string length outside length of the message\n");
1931       return FALSE;
1932     }
1933   
1934   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1935     {
1936       _dbus_verbose ("string arg not nul-terminated\n");
1937       return FALSE;
1938     }
1939   
1940   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1941     {
1942       _dbus_verbose ("string is not valid UTF-8\n");
1943       return FALSE;
1944     }
1945
1946   return TRUE;
1947 }   
1948
1949 /**
1950  * Validates and returns a typecode at a specific position
1951  * in the message
1952  *
1953  * @param str a string
1954  * @param type the type of the argument
1955  * @param pos the pos where the typecode starts
1956  * @param end_pos pointer where the position right
1957  * after the end position will follow
1958  * @returns #TRUE if the type is valid.
1959  */
1960 dbus_bool_t
1961 _dbus_marshal_validate_type   (const DBusString *str,
1962                                int               pos,
1963                                int              *type,
1964                                int              *end_pos)
1965 {
1966   const char *data;
1967   
1968   if (pos >= _dbus_string_get_length (str))
1969     return FALSE;
1970
1971   data = _dbus_string_get_const_data_len (str, pos, 1);
1972
1973   if (_dbus_type_is_valid (*data))
1974     {
1975       *type = *data;
1976       if (end_pos != NULL)
1977         *end_pos = pos + 1;
1978       return TRUE;
1979     }
1980
1981   _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
1982   
1983   return FALSE;
1984 }
1985
1986 /* Faster validator for array data that doesn't call
1987  * validate_arg for each value
1988  */
1989 static dbus_bool_t
1990 validate_array_data (const DBusString *str,
1991                      int               byte_order,
1992                      int               depth,
1993                      int               type,
1994                      int               array_type_pos,
1995                      int               pos,
1996                      int              *new_pos,
1997                      int               end)
1998 {
1999   switch (type)
2000     {
2001     case DBUS_TYPE_INVALID:
2002       return FALSE;
2003       break;
2004
2005     case DBUS_TYPE_NIL:
2006       break;
2007
2008     case DBUS_TYPE_OBJECT_PATH:
2009     case DBUS_TYPE_STRING:
2010     case DBUS_TYPE_CUSTOM:
2011     case DBUS_TYPE_ARRAY:
2012     case DBUS_TYPE_DICT:
2013       /* This clean recursion to validate_arg is what we
2014        * are doing logically for all types, but we don't
2015        * really want to call validate_arg for every byte
2016        * in a byte array, so the primitive types are
2017        * special-cased.
2018        */
2019       while (pos < end)
2020         {
2021           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2022                                            type, array_type_pos, pos, &pos))
2023             return FALSE;
2024         }
2025       break;
2026       
2027     case DBUS_TYPE_BYTE:
2028       pos = end;
2029       break;
2030       
2031     case DBUS_TYPE_BOOLEAN:
2032       while (pos < end)
2033         {
2034           unsigned char c;
2035           
2036           c = _dbus_string_get_byte (str, pos);
2037           
2038           if (!(c == 0 || c == 1))
2039             {
2040               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2041               return FALSE;
2042             }
2043           
2044           ++pos;
2045         }
2046       break;
2047       
2048     case DBUS_TYPE_INT32:
2049     case DBUS_TYPE_UINT32:
2050       /* Call validate arg one time to check alignment padding
2051        * at start of array
2052        */
2053       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2054                                        type, array_type_pos, pos, &pos))
2055         return FALSE;
2056       pos = _DBUS_ALIGN_VALUE (end, 4);
2057       break;
2058
2059     case DBUS_TYPE_INT64:
2060     case DBUS_TYPE_UINT64:
2061     case DBUS_TYPE_DOUBLE:
2062       /* Call validate arg one time to check alignment padding
2063        * at start of array
2064        */
2065       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2066                                        type, array_type_pos, pos, &pos))
2067         return FALSE;
2068       pos = _DBUS_ALIGN_VALUE (end, 8);
2069       break;
2070       
2071     default:
2072       _dbus_verbose ("Unknown message arg type %d\n", type);
2073       return FALSE;
2074     }
2075
2076   *new_pos = pos;
2077
2078   return TRUE;
2079 }
2080
2081 /** 
2082  * Validates an argument of a specific type, checking that it
2083  * is well-formed, for example no ludicrous length fields, strings
2084  * are nul-terminated, etc.
2085  * Returns the end position of the argument in end_pos, and
2086  * returns #TRUE if a valid arg begins at "pos"
2087  *
2088  * @todo security: need to audit this function.
2089  * 
2090  * @param str a string
2091  * @param byte_order the byte order to use
2092  * @param depth current recursion depth, to prevent excessive recursion
2093  * @param type the type of the argument
2094  * @param array_type_pos the position of the current array type, or
2095  *        -1 if not in an array
2096  * @param pos the pos where the arg starts
2097  * @param end_pos pointer where the position right
2098  * after the end position will follow
2099  * @returns #TRUE if the arg is valid.
2100  */
2101 dbus_bool_t
2102 _dbus_marshal_validate_arg (const DBusString *str,
2103                             int               byte_order,
2104                             int               depth,
2105                             int               type,
2106                             int               array_type_pos,
2107                             int               pos,
2108                             int              *end_pos)
2109 {
2110   if (pos > _dbus_string_get_length (str))
2111     {
2112       _dbus_verbose ("Validation went off the end of the message\n");
2113       return FALSE;
2114     }
2115
2116 #define MAX_VALIDATION_DEPTH 32
2117   
2118   if (depth > MAX_VALIDATION_DEPTH)
2119     {
2120       _dbus_verbose ("Maximum recursion depth reached validating message\n");
2121       return FALSE;
2122     }
2123   
2124   switch (type)
2125     {
2126     case DBUS_TYPE_INVALID:
2127       return FALSE;
2128       break;
2129
2130     case DBUS_TYPE_NIL:
2131       *end_pos = pos;
2132       break;
2133
2134     case DBUS_TYPE_BYTE:
2135       if (1 > _dbus_string_get_length (str) - pos)
2136         {
2137           _dbus_verbose ("no room for byte value\n");
2138           return FALSE;
2139         }
2140         
2141       *end_pos = pos + 1;
2142       break;
2143       
2144     case DBUS_TYPE_BOOLEAN:
2145       {
2146         unsigned char c;
2147
2148         if (1 > _dbus_string_get_length (str) - pos)
2149           {
2150             _dbus_verbose ("no room for boolean value\n");
2151             return FALSE;
2152           }
2153         
2154         c = _dbus_string_get_byte (str, pos);
2155
2156         if (!(c == 0 || c == 1))
2157           {
2158             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2159             return FALSE;
2160           }
2161         
2162         *end_pos = pos + 1;
2163       }
2164       break;
2165       
2166     case DBUS_TYPE_INT32:
2167     case DBUS_TYPE_UINT32:
2168       {
2169         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
2170         
2171         if (!_dbus_string_validate_nul (str, pos,
2172                                         align_4 - pos))
2173           {
2174             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2175             return FALSE;
2176           }
2177
2178         *end_pos = align_4 + 4;
2179       }
2180       break;
2181
2182     case DBUS_TYPE_INT64:
2183     case DBUS_TYPE_UINT64:      
2184     case DBUS_TYPE_DOUBLE:
2185       {
2186         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2187
2188         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2189         
2190         if (!_dbus_string_validate_nul (str, pos,
2191                                         align_8 - pos))
2192           {
2193             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
2194             return FALSE;
2195           }
2196
2197         *end_pos = align_8 + 8;
2198       }
2199       break;
2200
2201     case DBUS_TYPE_OBJECT_PATH:
2202     case DBUS_TYPE_STRING:
2203       {
2204         int len;
2205
2206         /* Demarshal the length, which does NOT include
2207          * nul termination
2208          */
2209         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2210         if (len < 0)
2211           return FALSE;
2212
2213         if (!validate_string (str, pos, len, end_pos))
2214           return FALSE;
2215
2216         if (type == DBUS_TYPE_OBJECT_PATH)
2217           {
2218             if (!_dbus_string_validate_path (str, pos, len))
2219               return FALSE;
2220           }
2221       }
2222       break;
2223
2224     case DBUS_TYPE_CUSTOM:
2225       {
2226         int len;
2227
2228         /* Demarshal the string length, which does NOT include
2229          * nul termination
2230          */
2231         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2232         if (len < 0)
2233           return FALSE;
2234
2235         if (!validate_string (str, pos, len, &pos))
2236           return FALSE;
2237
2238         /* Validate data */
2239         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2240         if (len < 0)
2241           return FALSE;
2242
2243         *end_pos = pos + len;
2244       }
2245       break;
2246       
2247     case DBUS_TYPE_ARRAY:
2248       {
2249         int len;
2250         int end;
2251         int array_type;
2252
2253         if (array_type_pos == -1)
2254           {
2255             array_type_pos = pos;
2256
2257             do
2258               {
2259                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2260                   {
2261                     _dbus_verbose ("invalid array type\n");
2262                     return FALSE;
2263                   }
2264                 
2265                 /* NIL values take up no space, so you couldn't iterate over an array of them.
2266                  * array of nil seems useless anyway; the useful thing might be array of
2267                  * (nil OR string) but we have no framework for that.
2268                  */
2269                 if (array_type == DBUS_TYPE_NIL)
2270                   {
2271                     _dbus_verbose ("array of NIL is not allowed\n");
2272                     return FALSE;
2273                   }
2274               }
2275             while (array_type == DBUS_TYPE_ARRAY);
2276           }
2277         else
2278           array_type_pos++;
2279
2280         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2281           {
2282             _dbus_verbose ("invalid array type\n");
2283             return FALSE;
2284           }
2285         
2286         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2287         if (len < 0)
2288           {
2289             _dbus_verbose ("invalid array length (<0)\n");
2290             return FALSE;
2291           }
2292
2293         if (len > _dbus_string_get_length (str) - pos)
2294           {
2295             _dbus_verbose ("array length outside length of the message\n");
2296             return FALSE;
2297           }
2298         
2299         end = pos + len;
2300
2301         if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
2302                                              array_type, array_type_pos,
2303                                              pos, &pos, end))
2304           {
2305             _dbus_verbose ("invalid array data\n");
2306             return FALSE;
2307           }
2308
2309         if (pos < end)
2310           {
2311             /* This should not be able to happen, as long as validate_arg moves forward;
2312              * but the check is here just to be paranoid.
2313              */
2314             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2315                            len, end - pos);
2316             return FALSE;
2317           }
2318         
2319         if (pos > end)
2320           {
2321             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2322             return FALSE;
2323           }
2324
2325         *end_pos = pos;
2326       }
2327       break;
2328
2329     case DBUS_TYPE_DICT:
2330       {
2331         int dict_type;
2332         int len;
2333         int end;
2334         
2335         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2336         if (len < 0)
2337           return FALSE;
2338
2339         if (len > _dbus_string_get_length (str) - pos)
2340           {
2341             _dbus_verbose ("dict length outside length of the message\n");
2342             return FALSE;
2343           }
2344         
2345         end = pos + len;
2346         
2347         while (pos < end)
2348           {
2349             /* Validate name */
2350             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2351                                              DBUS_TYPE_STRING, -1, pos, &pos))
2352               return FALSE;
2353             
2354             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2355               {
2356                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2357                 return FALSE;
2358               }
2359             
2360             /* Validate element */
2361             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2362                                              dict_type, -1, pos, &pos))
2363               {
2364                 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
2365                 return FALSE;
2366               }
2367           }
2368         
2369         if (pos > end)
2370           {
2371             _dbus_verbose ("dict contents exceed stated dict length\n");
2372             return FALSE;
2373           }
2374         
2375         *end_pos = pos;
2376       }
2377       break;
2378       
2379     default:
2380       _dbus_verbose ("Unknown message arg type %d\n", type);
2381       return FALSE;
2382     }
2383
2384   if (*end_pos > _dbus_string_get_length (str))
2385     return FALSE;
2386   
2387   return TRUE;
2388 }
2389
2390 /**
2391  * Return #TRUE if the typecode is a valid typecode
2392  *
2393  * @returns #TRUE if valid
2394  */
2395 dbus_bool_t
2396 _dbus_type_is_valid (int typecode)
2397 {
2398   switch (typecode)
2399     {
2400     case DBUS_TYPE_NIL:
2401     case DBUS_TYPE_BYTE:
2402     case DBUS_TYPE_BOOLEAN:
2403     case DBUS_TYPE_INT32:
2404     case DBUS_TYPE_UINT32:
2405     case DBUS_TYPE_INT64:
2406     case DBUS_TYPE_UINT64:
2407     case DBUS_TYPE_DOUBLE:
2408     case DBUS_TYPE_STRING:
2409     case DBUS_TYPE_CUSTOM:
2410     case DBUS_TYPE_ARRAY:
2411     case DBUS_TYPE_DICT:
2412     case DBUS_TYPE_OBJECT_PATH:
2413       return TRUE;
2414       
2415     default:
2416       return FALSE;
2417     }
2418 }
2419
2420 /**
2421  * If in verbose mode, print a block of binary data.
2422  *
2423  * @todo right now it prints even if not in verbose mode
2424  * 
2425  * @param data the data
2426  * @param len the length of the data
2427  */
2428 void
2429 _dbus_verbose_bytes (const unsigned char *data,
2430                      int                  len)
2431 {
2432   int i;
2433   const unsigned char *aligned;
2434
2435   _dbus_assert (len >= 0);
2436   
2437   /* Print blanks on first row if appropriate */
2438   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2439   if (aligned > data)
2440     aligned -= 4;
2441   _dbus_assert (aligned <= data);
2442
2443   if (aligned != data)
2444     {
2445       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2446       while (aligned != data)
2447         {
2448           _dbus_verbose ("    ");
2449           ++aligned;
2450         }
2451     }
2452
2453   /* now print the bytes */
2454   i = 0;
2455   while (i < len)
2456     {
2457       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2458         {
2459           _dbus_verbose ("%4d\t%p: ",
2460                    i, &data[i]);
2461         }
2462       
2463       if (data[i] >= 32 &&
2464           data[i] <= 126)
2465         _dbus_verbose (" '%c' ", data[i]);
2466       else
2467         _dbus_verbose ("0x%s%x ",
2468                  data[i] <= 0xf ? "0" : "", data[i]);
2469
2470       ++i;
2471
2472       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2473         {
2474           if (i > 3)
2475             _dbus_verbose ("BE: %d LE: %d",
2476                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2477                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2478
2479           if (i > 7 && 
2480               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2481             {
2482               _dbus_verbose (" dbl: %g",
2483                              *(double*)&data[i-8]);
2484             }
2485           
2486           _dbus_verbose ("\n");
2487         }
2488     }
2489
2490   _dbus_verbose ("\n");
2491 }
2492
2493 /**
2494  * Dump the given part of the string to verbose log.
2495  *
2496  * @param str the string
2497  * @param start the start of range to dump
2498  * @param len length of range
2499  */
2500 void
2501 _dbus_verbose_bytes_of_string (const DBusString    *str,
2502                                int                  start,
2503                                int                  len)
2504 {
2505   const char *d;
2506   int real_len;
2507
2508   real_len = _dbus_string_get_length (str);
2509
2510   _dbus_assert (start >= 0);
2511   
2512   if (start > real_len)
2513     {
2514       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2515                      start, len, real_len);
2516       return;
2517     }
2518
2519   if ((start + len) > real_len)
2520     {
2521       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2522                      start, len, real_len);
2523       len = real_len - start;
2524     }
2525   
2526   d = _dbus_string_get_const_data_len (str, start, len);
2527
2528   _dbus_verbose_bytes (d, len);
2529 }
2530
2531 /**
2532  * Marshals a basic type
2533  *
2534  * @param str string to marshal to
2535  * @param type type of value
2536  * @param value pointer to value
2537  * @param byte_order byte order
2538  * @returns #TRUE on success
2539  **/
2540 dbus_bool_t
2541 _dbus_marshal_basic_type (DBusString *str,
2542                           char        type,
2543                           void       *value,
2544                           int         byte_order)
2545 {
2546   dbus_bool_t retval;
2547
2548   switch (type)
2549     {
2550     case DBUS_TYPE_BYTE:
2551     case DBUS_TYPE_BOOLEAN:
2552       retval = _dbus_string_append_byte (str, *(unsigned char *)value);
2553       break;
2554     case DBUS_TYPE_INT32:
2555     case DBUS_TYPE_UINT32:
2556       return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
2557       break;
2558 #ifdef DBUS_HAVE_INT64
2559     case DBUS_TYPE_INT64:
2560     case DBUS_TYPE_UINT64: 
2561       retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
2562       break;
2563 #endif /* DBUS_HAVE_INT64 */
2564     case DBUS_TYPE_DOUBLE:
2565       retval = _dbus_marshal_double (str, byte_order, *(double *)value);
2566       break;
2567     default:
2568       _dbus_assert_not_reached ("not a basic type");
2569       retval = FALSE;
2570       break;
2571     }
2572   return retval;
2573 }
2574
2575 /**
2576  * Marshals a basic type array
2577  *
2578  * @param str string to marshal to
2579  * @param element_type type of array elements
2580  * @param value pointer to value
2581  * @param len length of value data in elements
2582  * @param byte_order byte order
2583  * @returns #TRUE on success
2584  **/
2585 dbus_bool_t
2586 _dbus_marshal_basic_type_array (DBusString *str,
2587                                 char        element_type,
2588                                 const void *value,
2589                                 int         len,
2590                                 int         byte_order)
2591 {
2592   switch (element_type)
2593     {
2594     case DBUS_TYPE_BOOLEAN:
2595       /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
2596        * should we here too ? */
2597     case DBUS_TYPE_BYTE:
2598       return _dbus_marshal_byte_array (str, byte_order, value, len);
2599       break;
2600     case DBUS_TYPE_INT32:
2601     case DBUS_TYPE_UINT32:
2602       return marshal_4_octets_array (str, byte_order, value, len);
2603       break;
2604 #ifdef DBUS_HAVE_INT64
2605     case DBUS_TYPE_INT64:
2606     case DBUS_TYPE_UINT64: 
2607 #endif /* DBUS_HAVE_INT64 */
2608     case DBUS_TYPE_DOUBLE:
2609       return marshal_8_octets_array (str, byte_order, value, len);
2610       break;
2611     default:
2612       _dbus_assert_not_reached ("non basic type in array");
2613       break;
2614     }
2615   return FALSE;
2616 }
2617
2618 /** @} */
2619
2620 #ifdef DBUS_BUILD_TESTS
2621 #include "dbus-test.h"
2622 #include <stdio.h>
2623
2624 dbus_bool_t
2625 _dbus_marshal_test (void)
2626 {
2627   DBusString str;
2628   char *tmp1, *tmp2;
2629   int pos = 0, len;
2630   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2631 #ifdef DBUS_HAVE_INT64
2632   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
2633                              DBUS_INT64_CONSTANT (0x456ffffffff), 
2634                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
2635 #endif
2636   char *s;
2637   DBusString t;
2638   
2639   if (!_dbus_string_init (&str))
2640     _dbus_assert_not_reached ("failed to init string");
2641
2642   /* Marshal doubles */
2643   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2644     _dbus_assert_not_reached ("could not marshal double value");
2645   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2646     _dbus_assert_not_reached ("demarshal failed");
2647
2648   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2649     _dbus_assert_not_reached ("could not marshal double value");
2650   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2651     _dbus_assert_not_reached ("demarshal failed");
2652   
2653   /* Marshal signed integers */
2654   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2655     _dbus_assert_not_reached ("could not marshal signed integer value");
2656   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2657     _dbus_assert_not_reached ("demarshal failed");
2658
2659   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2660     _dbus_assert_not_reached ("could not marshal signed integer value");
2661   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2662     _dbus_assert_not_reached ("demarshal failed");
2663   
2664   /* Marshal unsigned integers */
2665   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2666     _dbus_assert_not_reached ("could not marshal signed integer value");
2667   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2668     _dbus_assert_not_reached ("demarshal failed");
2669   
2670   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2671     _dbus_assert_not_reached ("could not marshal signed integer value");
2672   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2673     _dbus_assert_not_reached ("demarshal failed");
2674
2675 #ifdef DBUS_HAVE_INT64
2676   /* Marshal signed integers */
2677   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2678     _dbus_assert_not_reached ("could not marshal signed integer value");
2679   if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2680     _dbus_assert_not_reached ("demarshal failed");
2681
2682   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2683     _dbus_assert_not_reached ("could not marshal signed integer value");
2684   if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2685     _dbus_assert_not_reached ("demarshal failed");
2686   
2687   /* Marshal unsigned integers */
2688   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2689     _dbus_assert_not_reached ("could not marshal signed integer value");
2690   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2691     _dbus_assert_not_reached ("demarshal failed");
2692   
2693   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2694     _dbus_assert_not_reached ("could not marshal signed integer value");
2695   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2696     _dbus_assert_not_reached ("demarshal failed");
2697 #endif /* DBUS_HAVE_INT64 */
2698   
2699   /* Marshal strings */
2700   tmp1 = "This is the dbus test string";
2701   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2702     _dbus_assert_not_reached ("could not marshal string");
2703   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2704   if (!strcmp (tmp1, tmp2) == 0)
2705     _dbus_assert_not_reached ("demarshal failed");
2706   dbus_free (tmp2);
2707
2708   tmp1 = "This is the dbus test string";
2709   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2710     _dbus_assert_not_reached ("could not marshal string");
2711   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2712   if (!strcmp (tmp1, tmp2) == 0)
2713     _dbus_assert_not_reached ("demarshal failed");
2714   dbus_free (tmp2);
2715
2716   /* Marshal signed integer arrays */
2717   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2718     _dbus_assert_not_reached ("could not marshal integer array");
2719   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2720     _dbus_assert_not_reached ("could not demarshal integer array");
2721
2722   if (len != 3)
2723     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2724   dbus_free (array2);
2725
2726 #ifdef DBUS_HAVE_INT64
2727   /* Marshal 64-bit signed integer arrays */
2728   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2729     _dbus_assert_not_reached ("could not marshal integer array");
2730   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2731     _dbus_assert_not_reached ("could not demarshal integer array");
2732
2733   if (len != 3)
2734     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2735   dbus_free (array4);
2736
2737   /* set/pack 64-bit integers */
2738   _dbus_string_set_length (&str, 8);
2739
2740   /* signed little */
2741   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2742                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2743   
2744   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2745                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2746                                     _dbus_string_get_const_data (&str)));
2747
2748   /* signed big */
2749   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2750                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2751
2752   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2753                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2754                                     _dbus_string_get_const_data (&str)));
2755
2756   /* signed little pack */
2757   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2758                     DBUS_LITTLE_ENDIAN,
2759                     _dbus_string_get_data (&str));
2760   
2761   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2762                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2763                                     _dbus_string_get_const_data (&str)));
2764
2765   /* signed big pack */
2766   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2767                     DBUS_BIG_ENDIAN,
2768                     _dbus_string_get_data (&str));
2769
2770   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2771                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2772                                     _dbus_string_get_const_data (&str)));
2773
2774   /* unsigned little */
2775   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2776                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2777   
2778   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2779                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2780                                      _dbus_string_get_const_data (&str)));
2781
2782   /* unsigned big */
2783   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2784                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2785
2786   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2787                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2788                                      _dbus_string_get_const_data (&str)));
2789
2790   /* unsigned little pack */
2791   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2792                      DBUS_LITTLE_ENDIAN,
2793                      _dbus_string_get_data (&str));
2794   
2795   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2796                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2797                                      _dbus_string_get_const_data (&str)));
2798
2799   /* unsigned big pack */
2800   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2801                      DBUS_BIG_ENDIAN,
2802                      _dbus_string_get_data (&str));
2803
2804   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2805                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2806                                      _dbus_string_get_const_data (&str)));
2807   
2808 #endif
2809
2810   /* set/pack 32-bit integers */
2811   _dbus_string_set_length (&str, 4);
2812
2813   /* signed little */
2814   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2815                            0, -0x123456);
2816   
2817   _dbus_assert (-0x123456 ==
2818                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2819                                     _dbus_string_get_const_data (&str)));
2820
2821   /* signed big */
2822   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2823                            0, -0x123456);
2824
2825   _dbus_assert (-0x123456 ==
2826                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2827                                     _dbus_string_get_const_data (&str)));
2828
2829   /* signed little pack */
2830   _dbus_pack_int32 (-0x123456,
2831                     DBUS_LITTLE_ENDIAN,
2832                     _dbus_string_get_data (&str));
2833   
2834   _dbus_assert (-0x123456 ==
2835                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2836                                     _dbus_string_get_const_data (&str)));
2837
2838   /* signed big pack */
2839   _dbus_pack_int32 (-0x123456,
2840                     DBUS_BIG_ENDIAN,
2841                     _dbus_string_get_data (&str));
2842
2843   _dbus_assert (-0x123456 ==
2844                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2845                                     _dbus_string_get_const_data (&str)));
2846
2847   /* unsigned little */
2848   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2849                             0, 0x123456);
2850   
2851   _dbus_assert (0x123456 ==
2852                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2853                                      _dbus_string_get_const_data (&str)));
2854
2855   /* unsigned big */
2856   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2857                             0, 0x123456);
2858
2859   _dbus_assert (0x123456 ==
2860                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2861                                      _dbus_string_get_const_data (&str)));
2862
2863   /* unsigned little pack */
2864   _dbus_pack_uint32 (0x123456,
2865                      DBUS_LITTLE_ENDIAN,
2866                      _dbus_string_get_data (&str));
2867   
2868   _dbus_assert (0x123456 ==
2869                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2870                                      _dbus_string_get_const_data (&str)));
2871
2872   /* unsigned big pack */
2873   _dbus_pack_uint32 (0x123456,
2874                      DBUS_BIG_ENDIAN,
2875                      _dbus_string_get_data (&str));
2876
2877   _dbus_assert (0x123456 ==
2878                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2879                                      _dbus_string_get_const_data (&str)));
2880
2881
2882   /* Strings */
2883   
2884   _dbus_string_set_length (&str, 0);
2885
2886   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2887                         "Hello world");
2888   
2889   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2890   _dbus_assert (strcmp (s, "Hello world") == 0);
2891   dbus_free (s);
2892
2893   _dbus_string_init_const (&t, "Hello world foo");
2894   
2895   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2896                             &t, _dbus_string_get_length (&t));
2897   
2898   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2899   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2900   dbus_free (s);
2901
2902   _dbus_string_init_const (&t, "Hello");
2903   
2904   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2905                             &t, _dbus_string_get_length (&t));
2906   
2907   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2908   _dbus_assert (strcmp (s, "Hello") == 0);
2909   dbus_free (s);
2910
2911   /* Strings (big endian) */
2912   
2913   _dbus_string_set_length (&str, 0);
2914
2915   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2916                         "Hello world");
2917   
2918   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2919   _dbus_assert (strcmp (s, "Hello world") == 0);
2920   dbus_free (s);
2921
2922   _dbus_string_init_const (&t, "Hello world foo");
2923   
2924   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2925                             &t, _dbus_string_get_length (&t));
2926   
2927   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2928   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2929   dbus_free (s);
2930
2931   _dbus_string_init_const (&t, "Hello");
2932   
2933   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2934                             &t, _dbus_string_get_length (&t));
2935   
2936   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2937   _dbus_assert (strcmp (s, "Hello") == 0);
2938   dbus_free (s);
2939   
2940   _dbus_string_free (&str);
2941       
2942   return TRUE;
2943 }
2944
2945 #endif /* DBUS_BUILD_TESTS */