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