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