sync busted marshaling work in progress
[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   /*  The array length is the length in bytes of the array,
750    * *excluding* alignment padding.
751    */
752   if (!_dbus_marshal_uint32 (str, byte_order, len * 8))
753     goto error;
754
755   array_start = _dbus_string_get_length (str);
756
757   /* Note that we do alignment padding unconditionally
758    * even if the array is empty; this means that
759    * padding + len is always equal to the number of bytes
760    * in the array.
761    */
762   
763   if (!_dbus_string_align_length (str, 8))
764     goto error;
765   
766   if (!_dbus_string_append_len (str, (const unsigned char*) value,
767                                 len * 8))
768     goto error;
769   
770   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
771     {
772       const unsigned char *d;
773       const unsigned char *end;
774       
775       d = _dbus_string_get_data (str) + array_start;
776       end = d + len * 8;
777       while (d != end)
778         {
779 #ifdef DBUS_HAVE_INT64
780           *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
781 #else
782           swap_bytes ((unsigned char*) d, 8);
783 #endif
784           d += 8;
785         }
786     }
787
788   return TRUE;
789   
790  error:
791   /* Restore previous length */
792   _dbus_string_set_length (str, old_string_len);
793   
794   return FALSE;  
795 }
796
797 /**
798  * Marshals a 32 bit signed integer array
799  *
800  * @param str the string to append the marshalled value to
801  * @param byte_order the byte order to use
802  * @param value the array
803  * @param len the length of the array
804  * @returns #TRUE on success
805  */
806 dbus_bool_t
807 _dbus_marshal_int32_array (DBusString         *str,
808                            int                 byte_order,
809                            const dbus_int32_t *value,
810                            int                 len)
811 {
812   return marshal_4_octets_array (str, byte_order,
813                                  (const dbus_uint32_t*) value,
814                                  len);
815 }
816
817 /**
818  * Marshals a 32 bit unsigned integer array
819  *
820  * @param str the string to append the marshalled value to
821  * @param byte_order the byte order to use
822  * @param value the array
823  * @param len the length of the array
824  * @returns #TRUE on success
825  */
826 dbus_bool_t
827 _dbus_marshal_uint32_array (DBusString          *str,
828                             int                  byte_order,
829                             const dbus_uint32_t  *value,
830                             int                  len)
831 {
832   return marshal_4_octets_array (str, byte_order,
833                                  value,
834                                  len);
835 }
836
837 #ifdef DBUS_HAVE_INT64
838
839 /**
840  * Marshals a 64 bit signed integer array
841  *
842  * @param str the string to append the marshalled value to
843  * @param byte_order the byte order to use
844  * @param value the array
845  * @param len the length of the array
846  * @returns #TRUE on success
847  */
848 dbus_bool_t
849 _dbus_marshal_int64_array (DBusString         *str,
850                            int                 byte_order,
851                            const dbus_int64_t *value,
852                            int                 len)
853 {
854   return marshal_8_octets_array (str, byte_order,
855                                  (const DBusOctets8*) value,
856                                  len);
857 }
858
859 /**
860  * Marshals a 64 bit unsigned integer array
861  *
862  * @param str the string to append the marshalled value to
863  * @param byte_order the byte order to use
864  * @param value the array
865  * @param len the length of the array
866  * @returns #TRUE on success
867  */
868 dbus_bool_t
869 _dbus_marshal_uint64_array (DBusString          *str,
870                             int                  byte_order,
871                             const dbus_uint64_t  *value,
872                             int                  len)
873 {
874   return marshal_8_octets_array (str, byte_order,
875                                  (const DBusOctets8*) value,
876                                  len);
877 }
878
879 #endif /* DBUS_HAVE_INT64 */
880
881 /**
882  * Marshals a double array
883  *
884  * @param str the string to append the marshalled value to
885  * @param byte_order the byte order to use
886  * @param value the array
887  * @param len the length of the array
888  * @returns #TRUE on success
889  */
890 dbus_bool_t
891 _dbus_marshal_double_array (DBusString          *str,
892                             int                  byte_order,
893                             const double        *value,
894                             int                  len)
895 {
896   return marshal_8_octets_array (str, byte_order,
897                                  (const DBusOctets8*) value,
898                                  len);
899 }
900
901 /**
902  * Marshals a string array
903  *
904  * @param str the string to append the marshalled value to
905  * @param byte_order the byte order to use
906  * @param value the array
907  * @param len the length of the array
908  * @returns #TRUE on success
909  */
910 dbus_bool_t
911 _dbus_marshal_string_array (DBusString  *str,
912                             int          byte_order,
913                             const char **value,
914                             int          len)
915 {
916   int i, old_string_len, array_start;
917
918   old_string_len = _dbus_string_get_length (str);
919
920   /* Set the length to 0 temporarily */
921   if (!_dbus_marshal_uint32 (str, byte_order, 0))
922     goto error;
923
924   array_start = _dbus_string_get_length (str);
925   
926   for (i = 0; i < len; i++)
927     if (!_dbus_marshal_string (str, byte_order, value[i]))
928       goto error;
929
930   /* Write the length now that we know it */
931   _dbus_marshal_set_uint32 (str, byte_order,
932                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
933                             _dbus_string_get_length (str) - array_start);
934   
935   return TRUE;
936   
937  error:
938   /* Restore previous length */
939   _dbus_string_set_length (str, old_string_len);
940   
941   return FALSE;      
942 }
943
944 /**
945  * Marshals an object path value.
946  * 
947  * @param str the string to append the marshalled value to
948  * @param byte_order the byte order to use
949  * @param path the path
950  * @param path_len length of the path
951  * @returns #TRUE on success
952  */
953 static dbus_bool_t
954 _dbus_marshal_object_path (DBusString            *str,
955                            int                    byte_order,
956                            const char           **path,
957                            int                    path_len)
958 {
959   int array_start, old_string_len;
960   int i;
961   
962   old_string_len = _dbus_string_get_length (str);
963   
964   /* Set the length to 0 temporarily */
965   if (!_dbus_marshal_uint32 (str, byte_order, 0))
966     goto nomem;
967
968   array_start = _dbus_string_get_length (str);
969   
970   i = 0;
971   while (i < path_len)
972     {
973       if (!_dbus_string_append_byte (str, '/'))
974         goto nomem;
975       
976       if (!_dbus_string_append (str, path[0]))
977         goto nomem;
978
979       ++i;
980     }
981
982   /* Write the length now that we know it */
983   _dbus_marshal_set_uint32 (str, byte_order,
984                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
985                             _dbus_string_get_length (str) - array_start);  
986
987   return TRUE;
988
989  nomem:
990   /* Restore the previous length */
991   _dbus_string_set_length (str, old_string_len);
992   
993   return FALSE;
994 }
995
996 static dbus_uint32_t
997 demarshal_4_octets (const DBusString *str,
998                     int               byte_order,
999                     int               pos,
1000                     int              *new_pos)
1001 {
1002   const DBusRealString *real = (const DBusRealString*) str;
1003   
1004   pos = _DBUS_ALIGN_VALUE (pos, 4);
1005   
1006   if (new_pos)
1007     *new_pos = pos + 4;
1008
1009   return unpack_4_octets (byte_order, real->str + pos);
1010 }
1011
1012 static DBusOctets8
1013 demarshal_8_octets (const DBusString *str,
1014                     int               byte_order,
1015                     int               pos,
1016                     int              *new_pos)
1017 {
1018   const DBusRealString *real = (const DBusRealString*) str;
1019   
1020   pos = _DBUS_ALIGN_VALUE (pos, 8);
1021   
1022   if (new_pos)
1023     *new_pos = pos + 8;
1024
1025   return unpack_8_octets (byte_order, real->str + pos);
1026 }
1027
1028 /**
1029  * Demarshals a double.
1030  *
1031  * @param str the string containing the data
1032  * @param byte_order the byte order
1033  * @param pos the position in the string
1034  * @param new_pos the new position of the string
1035  * @returns the demarshaled double.
1036  */
1037 double
1038 _dbus_demarshal_double (const DBusString  *str,
1039                         int                byte_order,
1040                         int                pos,
1041                         int               *new_pos)
1042 {
1043   DBusOctets8 r;
1044
1045   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1046
1047   return r.d;
1048 }
1049
1050 /**
1051  * Demarshals a 32 bit signed integer.
1052  *
1053  * @param str the string containing the data
1054  * @param byte_order the byte order
1055  * @param pos the position in the string
1056  * @param new_pos the new position of the string
1057  * @returns the demarshaled integer.
1058  */
1059 dbus_int32_t
1060 _dbus_demarshal_int32  (const DBusString *str,
1061                         int               byte_order,
1062                         int               pos,
1063                         int              *new_pos)
1064 {
1065   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
1066 }
1067
1068 /**
1069  * Demarshals a 32 bit unsigned integer.
1070  *
1071  * @param str the string containing the data
1072  * @param byte_order the byte order
1073  * @param pos the position in the string
1074  * @param new_pos the new position of the string
1075  * @returns the demarshaled integer.
1076  */
1077 dbus_uint32_t
1078 _dbus_demarshal_uint32  (const DBusString *str,
1079                          int         byte_order,
1080                          int         pos,
1081                          int        *new_pos)
1082 {
1083   return demarshal_4_octets (str, byte_order, pos, new_pos);
1084 }
1085
1086 #ifdef DBUS_HAVE_INT64
1087
1088 /**
1089  * Demarshals a 64 bit signed integer.
1090  *
1091  * @param str the string containing the data
1092  * @param byte_order the byte order
1093  * @param pos the position in the string
1094  * @param new_pos the new position of the string
1095  * @returns the demarshaled integer.
1096  */
1097 dbus_int64_t
1098 _dbus_demarshal_int64  (const DBusString *str,
1099                         int               byte_order,
1100                         int               pos,
1101                         int              *new_pos)
1102 {
1103   DBusOctets8 r;
1104
1105   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1106
1107   return r.s;
1108 }
1109
1110 /**
1111  * Demarshals a 64 bit unsigned integer.
1112  *
1113  * @param str the string containing the data
1114  * @param byte_order the byte order
1115  * @param pos the position in the string
1116  * @param new_pos the new position of the string
1117  * @returns the demarshaled integer.
1118  */
1119 dbus_uint64_t
1120 _dbus_demarshal_uint64  (const DBusString *str,
1121                          int         byte_order,
1122                          int         pos,
1123                          int        *new_pos)
1124 {
1125   DBusOctets8 r;
1126
1127   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1128
1129   return r.u;
1130 }
1131
1132 #endif /* DBUS_HAVE_INT64 */
1133
1134 /**
1135  * Demarshals a basic type
1136  *
1137  * @param str the string containing the data
1138  * @param type type of value to demarshal
1139  * @param value pointer to return value data
1140  * @param byte_order the byte order
1141  * @param pos pointer to position in the string,
1142  *            updated on return to new position
1143  **/
1144 void
1145 _dbus_demarshal_basic_type (const DBusString      *str,
1146                             int                    type,
1147                             void                  *value,
1148                             int                    byte_order,
1149                             int                   *pos)
1150 {
1151   const char *str_data = _dbus_string_get_const_data (str);
1152
1153   switch (type)
1154     {
1155     case DBUS_TYPE_BYTE:
1156     case DBUS_TYPE_BOOLEAN:
1157       *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
1158       (*pos)++;
1159       break;
1160     case DBUS_TYPE_INT32:
1161     case DBUS_TYPE_UINT32:
1162       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1163       *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
1164       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1165         *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
1166       *pos += 4;
1167       break;
1168 #ifdef DBUS_HAVE_INT64
1169     case DBUS_TYPE_INT64:
1170     case DBUS_TYPE_UINT64: 
1171 #endif /* DBUS_HAVE_INT64 */
1172     case DBUS_TYPE_DOUBLE:
1173       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1174       memcpy (value, str_data + *pos, 8);
1175       if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1176 #ifdef DBUS_HAVE_INT64
1177         *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
1178 #else   
1179         swap_bytes (value, 8);
1180 #endif
1181       *pos += 8;
1182       break;
1183     case DBUS_TYPE_STRING:
1184       _dbus_assert_not_reached ("FIXME string is a basic type");
1185       break;
1186     case DBUS_TYPE_OBJECT_PATH:
1187       _dbus_assert_not_reached ("FIXME object path is a basic type");
1188       break;
1189     default:
1190       _dbus_verbose ("type %s not a basic type\n",
1191                      _dbus_type_to_string (type));
1192       _dbus_assert_not_reached ("not a basic type");
1193       break;
1194     }
1195 }
1196
1197 /**
1198  * Demarshals an UTF-8 string.
1199  *
1200  * @todo Should we check the string to make sure
1201  * that it's  valid UTF-8, and maybe "fix" the string
1202  * if it's broken?
1203  *
1204  * @todo Should probably demarshal to a DBusString,
1205  * having memcpy() in here is Evil(tm).
1206  *
1207  * @param str the string containing the data
1208  * @param byte_order the byte order
1209  * @param pos the position in the string
1210  * @param new_pos the new position of the string
1211  * @returns the demarshaled string.
1212  */
1213 char *
1214 _dbus_demarshal_string (const DBusString *str,
1215                         int               byte_order,
1216                         int               pos,
1217                         int              *new_pos)
1218 {
1219   int len;
1220   char *retval;
1221   const char *data;
1222   
1223   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1224
1225   retval = dbus_malloc (len + 1);
1226
1227   if (!retval)
1228     return NULL;
1229
1230   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1231
1232   if (!data)
1233     return NULL;
1234
1235   memcpy (retval, data, len + 1);
1236
1237   if (new_pos)
1238     *new_pos = pos + len + 1;
1239   
1240   return retval;
1241 }
1242
1243 /**
1244  * Demarshals a byte array.
1245  *
1246  * @todo Should probably demarshal to a DBusString,
1247  * having memcpy() in here is Evil(tm).
1248  *
1249  * @param str the string containing the data
1250  * @param byte_order the byte order
1251  * @param pos the position in the string
1252  * @param new_pos the new position of the string
1253  * @param array the array
1254  * @param array_len length of the demarshaled data
1255  
1256  * @returns #TRUE on success
1257  */
1258 dbus_bool_t
1259 _dbus_demarshal_byte_array (const DBusString  *str,
1260                             int                byte_order,
1261                             int                pos,
1262                             int               *new_pos,
1263                             unsigned char    **array,
1264                             int               *array_len)
1265 {
1266   int len;
1267   unsigned char *retval;
1268   const char *data;
1269
1270   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1271
1272   if (len == 0)
1273     {
1274       *array_len = len;
1275       *array = NULL;
1276
1277       if (new_pos)
1278         *new_pos = pos;
1279       
1280       return TRUE;
1281     }
1282   
1283   retval = dbus_malloc (len);
1284
1285   if (!retval)
1286     return FALSE;
1287
1288   data = _dbus_string_get_const_data_len (str, pos, len);
1289
1290   if (!data)
1291     {
1292       dbus_free (retval);
1293       return FALSE;
1294     }
1295
1296   memcpy (retval, data, len);
1297
1298   if (new_pos)
1299     *new_pos = pos + len;
1300
1301   *array = retval;
1302   *array_len = len;
1303   
1304   return TRUE;
1305 }
1306
1307 static dbus_bool_t
1308 demarshal_4_octets_array (const DBusString  *str,
1309                           int                byte_order,
1310                           int                pos,
1311                           int               *new_pos,
1312                           dbus_uint32_t    **array,
1313                           int               *array_len)
1314 {
1315   int len, i;
1316   dbus_uint32_t *retval;
1317   int byte_len;
1318   
1319   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1320   len = byte_len / 4;
1321
1322   if (len == 0)
1323     {
1324       *array_len = 0;
1325       *array = NULL;
1326
1327       if (new_pos)
1328         *new_pos = pos;
1329       
1330       return TRUE;
1331     }
1332
1333   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1334                                    pos, byte_len))
1335     return FALSE;
1336   
1337   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1338     {
1339       for (i = 0; i < len; i++)
1340         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1341     }
1342
1343   if (new_pos)
1344     *new_pos = pos + byte_len;
1345
1346   *array_len = len;
1347   *array = retval;
1348   
1349   return TRUE;  
1350 }
1351
1352 static dbus_bool_t
1353 demarshal_8_octets_array (const DBusString  *str,
1354                           int                byte_order,
1355                           int                pos,
1356                           int               *new_pos,
1357                           DBusOctets8      **array,
1358                           int               *array_len)
1359 {
1360   int len, i;
1361   DBusOctets8 *retval;
1362   int byte_len;
1363   
1364   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1365
1366   pos = _DBUS_ALIGN_VALUE (pos, 8);
1367   
1368   len = byte_len / 8;
1369
1370   if (len == 0)
1371     {
1372       *array_len = 0;
1373       *array = NULL;
1374
1375       if (new_pos)
1376         *new_pos = pos;
1377       
1378       return TRUE;
1379     }
1380
1381   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1382                                    pos, byte_len))
1383     return FALSE;
1384   
1385   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1386     {
1387       for (i = 0; i < len; i++)
1388         {
1389 #ifdef DBUS_HAVE_INT64
1390           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1391 #else
1392           swap_bytes ((unsigned char *) &retval[i], 8);
1393 #endif
1394         }
1395     }
1396
1397   if (new_pos)
1398     *new_pos = pos + byte_len;
1399
1400   *array_len = len;
1401   *array = retval;
1402   
1403   return TRUE;  
1404 }
1405
1406 /**
1407  * Demarshals a 32 bit signed integer array.
1408  *
1409  * @param str the string containing the data
1410  * @param byte_order the byte order
1411  * @param pos the position in the string
1412  * @param new_pos the new position of the string
1413  * @param array the array
1414  * @param array_len length of the demarshaled data
1415  * @returns #TRUE on success
1416  */
1417 dbus_bool_t
1418 _dbus_demarshal_int32_array (const DBusString  *str,
1419                              int                byte_order,
1420                              int                pos,
1421                              int               *new_pos,
1422                              dbus_int32_t     **array,
1423                              int               *array_len)
1424 {
1425   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1426                                    (dbus_uint32_t**) array, array_len);
1427 }
1428
1429 /**
1430  * Demarshals a 32 bit unsigned integer array.
1431  *
1432  * @param str the string containing the data
1433  * @param byte_order the byte order
1434  * @param pos the position in the string
1435  * @param new_pos the new position of the string
1436  * @param array the array
1437  * @param array_len length of the demarshaled data
1438  * @returns #TRUE on success
1439  */
1440 dbus_bool_t
1441 _dbus_demarshal_uint32_array (const DBusString  *str,
1442                               int                byte_order,
1443                               int                pos,
1444                               int               *new_pos,
1445                               dbus_uint32_t    **array,
1446                               int               *array_len)
1447 {
1448   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1449                                    array, array_len);
1450 }
1451
1452 #ifdef DBUS_HAVE_INT64
1453
1454 /**
1455  * Demarshals a 64 bit signed integer array.
1456  *
1457  * @param str the string containing the data
1458  * @param byte_order the byte order
1459  * @param pos the position in the string
1460  * @param new_pos the new position of the string
1461  * @param array the array
1462  * @param array_len length of the demarshaled data
1463  * @returns #TRUE on success
1464  */
1465 dbus_bool_t
1466 _dbus_demarshal_int64_array (const DBusString  *str,
1467                              int                byte_order,
1468                              int                pos,
1469                              int               *new_pos,
1470                              dbus_int64_t     **array,
1471                              int               *array_len)
1472 {
1473   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1474                                    (DBusOctets8**) array, array_len);
1475 }
1476
1477 /**
1478  * Demarshals a 64 bit unsigned integer array.
1479  *
1480  * @param str the string containing the data
1481  * @param byte_order the byte order
1482  * @param pos the position in the string
1483  * @param new_pos the new position of the string
1484  * @param array the array
1485  * @param array_len length of the demarshaled data
1486  * @returns #TRUE on success
1487  */
1488 dbus_bool_t
1489 _dbus_demarshal_uint64_array (const DBusString  *str,
1490                               int                byte_order,
1491                               int                pos,
1492                               int               *new_pos,
1493                               dbus_uint64_t    **array,
1494                               int               *array_len)
1495 {
1496   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1497                                    (DBusOctets8**) array, array_len);
1498 }
1499
1500 #endif /* DBUS_HAVE_INT64 */
1501
1502 /**
1503  * Demarshals a double array.
1504  *
1505  * @param str the string containing the data
1506  * @param byte_order the byte order
1507  * @param pos the position in the string
1508  * @param new_pos the new position of the string
1509  * @param array the array
1510  * @param array_len length of the demarshaled data
1511  * @returns #TRUE on success
1512  */
1513 dbus_bool_t
1514 _dbus_demarshal_double_array (const DBusString  *str,
1515                               int                byte_order,
1516                               int                pos,
1517                               int               *new_pos,
1518                               double           **array,
1519                               int               *array_len)
1520 {
1521   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1522                                    (DBusOctets8**) array, array_len);
1523 }
1524
1525
1526 /**
1527  * Demarshals an array of basic types
1528  *
1529  * @param str the string containing the data
1530  * @param element_type type of array elements to demarshal
1531  * @param array pointer to pointer to array data
1532  * @param array_len pointer to array length
1533  * @param byte_order the byte order
1534  * @param pos pointer to position in the string,
1535  *            updated on return to new position
1536  **/
1537 dbus_bool_t
1538 _dbus_demarshal_basic_type_array (const DBusString      *str,
1539                                   int                    element_type,
1540                                   void                 **array,
1541                                   int                   *array_len,
1542                                   int                    byte_order,
1543                                   int                   *pos)
1544 {
1545   switch (element_type)
1546     {
1547     case DBUS_TYPE_BOOLEAN:
1548       /* FIXME: do we want to post-normalize these ? */
1549     case DBUS_TYPE_BYTE:
1550       return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
1551                                          (unsigned char **)array, array_len);
1552       break;
1553     case DBUS_TYPE_INT32:
1554     case DBUS_TYPE_UINT32:
1555       return demarshal_4_octets_array (str, byte_order, *pos, pos,
1556                                        (dbus_uint32_t **)array, array_len);
1557       break;
1558 #ifdef DBUS_HAVE_INT64
1559     case DBUS_TYPE_INT64:
1560     case DBUS_TYPE_UINT64: 
1561 #endif /* DBUS_HAVE_INT64 */
1562     case DBUS_TYPE_DOUBLE:
1563       return demarshal_8_octets_array (str, byte_order, *pos, pos,
1564                                        (DBusOctets8**) array, array_len);
1565     default:
1566       _dbus_assert_not_reached ("not a basic type");
1567       break;
1568     }
1569   return FALSE;
1570 }
1571
1572 /**
1573  * Demarshals a string array.
1574  *
1575  * @param str the string containing the data
1576  * @param byte_order the byte order
1577  * @param pos the position in the string
1578  * @param new_pos the new position of the string
1579  * @param array the array
1580  * @param array_len location for length of the demarshaled data or NULL
1581  * @returns #TRUE on success
1582  */
1583 dbus_bool_t
1584 _dbus_demarshal_string_array (const DBusString   *str,
1585                               int                 byte_order,
1586                               int                 pos,
1587                               int                *new_pos,
1588                               char             ***array,
1589                               int                *array_len)
1590 {
1591   int bytes_len, i;
1592   int len, allocated;
1593   int end_pos;
1594   char **retval;
1595   
1596   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1597   
1598   if (bytes_len == 0)
1599     {
1600       *array_len = 0;
1601       *array = NULL;
1602
1603       if (new_pos)
1604         *new_pos = pos;
1605       
1606       return TRUE;
1607     }
1608
1609   len = 0;
1610   allocated = 4;
1611   end_pos = pos + bytes_len;
1612   
1613   retval = dbus_new (char *, allocated);
1614
1615   if (!retval)
1616     return FALSE;
1617
1618   while (pos < end_pos)
1619     {
1620       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1621       
1622       if (retval[len] == NULL)
1623         goto error;
1624       
1625       len += 1;
1626
1627       if (len >= allocated - 1) /* -1 for NULL termination */
1628         {
1629           char **newp;
1630           newp = dbus_realloc (retval,
1631                                sizeof (char*) * allocated * 2);
1632           if (newp == NULL)
1633             goto error;
1634
1635           allocated *= 2;
1636           retval = newp;
1637         }
1638     }
1639       
1640   retval[len] = NULL;
1641
1642   if (new_pos)
1643     *new_pos = pos;
1644   
1645   *array = retval;
1646   *array_len = len;
1647   
1648   return TRUE;
1649
1650  error:
1651   for (i = 0; i < len; i++)
1652     dbus_free (retval[i]);
1653   dbus_free (retval);
1654
1655   return FALSE;
1656 }
1657
1658 /** Set to 1 to get a bunch of spew about disassembling the path string */
1659 #define VERBOSE_DECOMPOSE 0
1660
1661 /**
1662  * Decompose an object path.  A path of just "/" is
1663  * represented as an empty vector of strings.
1664  * 
1665  * @param data the path data
1666  * @param len  the length of the path string
1667  * @param path address to store new object path
1668  * @param path_len length of stored path
1669  */
1670 dbus_bool_t
1671 _dbus_decompose_path (const char*     data,
1672                       int             len,
1673                       char         ***path,
1674                       int            *path_len)
1675 {
1676   char **retval;
1677   int n_components;
1678   int i, j, comp;
1679
1680   _dbus_assert (data != NULL);
1681
1682 #if VERBOSE_DECOMPOSE
1683   _dbus_verbose ("Decomposing path \"%s\"\n",
1684                  data);
1685 #endif
1686   
1687   n_components = 0;
1688   i = 0;
1689   while (i < len)
1690     {
1691       if (data[i] == '/')
1692         n_components += 1;
1693       ++i;
1694     }
1695   
1696   retval = dbus_new0 (char*, n_components + 1);
1697
1698   if (retval == NULL)
1699     return FALSE;
1700
1701   comp = 0;
1702   i = 0;
1703   while (i < len)
1704     {
1705       if (data[i] == '/')
1706         ++i;
1707       j = i;
1708
1709       while (j < len && data[j] != '/')
1710         ++j;
1711
1712       /* Now [i, j) is the path component */
1713       _dbus_assert (i < j);
1714       _dbus_assert (data[i] != '/');
1715       _dbus_assert (j == len || data[j] == '/');
1716
1717 #if VERBOSE_DECOMPOSE
1718       _dbus_verbose ("  (component in [%d,%d))\n",
1719                      i, j);
1720 #endif
1721       
1722       retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1723       if (retval[comp] == NULL)
1724         {
1725           dbus_free_string_array (retval);
1726           return FALSE;
1727         }
1728       retval[comp][j-i] = '\0';
1729 #if VERBOSE_DECOMPOSE
1730       _dbus_verbose ("  (component %d = \"%s\")\n",
1731                      comp, retval[comp]);
1732 #endif
1733
1734       ++comp;
1735       i = j;
1736     }
1737   _dbus_assert (i == len);
1738   
1739   *path = retval;
1740   if (path_len)
1741     *path_len = n_components;
1742   
1743   return TRUE;
1744 }
1745
1746 /**
1747  * Demarshals an object path.  A path of just "/" is
1748  * represented as an empty vector of strings.
1749  * 
1750  * @param str the string containing the data
1751  * @param byte_order the byte order
1752  * @param pos the position in the string
1753  * @param new_pos the new position of the string
1754  * @param path address to store new object path
1755  * @param path_len length of stored path
1756  */
1757 dbus_bool_t
1758 _dbus_demarshal_object_path (const DBusString *str,
1759                              int               byte_order,
1760                              int               pos,
1761                              int              *new_pos,
1762                              char           ***path,
1763                              int              *path_len)
1764 {
1765   int len;
1766   const char *data;
1767   
1768   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1769   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1770
1771   if (!_dbus_decompose_path (data, len, path, path_len))
1772     return FALSE;
1773
1774   if (new_pos)
1775     *new_pos = pos + len + 1;
1776
1777   return TRUE;
1778 }
1779
1780 /**
1781  * Skips over a basic type, reporting the following position.
1782  *
1783  * @param str the string containing the data
1784  * @param type type of value to demarshal
1785  * @param byte_order the byte order
1786  * @param pos pointer to position in the string,
1787  *            updated on return to new position
1788  **/
1789 void
1790 _dbus_marshal_skip_basic_type (const DBusString      *str,
1791                                int                    type,
1792                                int                    byte_order,
1793                                int                   *pos)
1794 {
1795   switch (type)
1796     {
1797     case DBUS_TYPE_BYTE:
1798     case DBUS_TYPE_BOOLEAN:
1799       (*pos)++;
1800       break;
1801     case DBUS_TYPE_INT32:
1802     case DBUS_TYPE_UINT32:
1803       *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1804       *pos += 4;
1805       break;
1806 #ifdef DBUS_HAVE_INT64
1807     case DBUS_TYPE_INT64:
1808     case DBUS_TYPE_UINT64: 
1809 #endif /* DBUS_HAVE_INT64 */
1810     case DBUS_TYPE_DOUBLE:
1811       *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1812       *pos += 8;
1813       break;
1814     case DBUS_TYPE_STRING:
1815       _dbus_assert_not_reached ("FIXME string is a basic type");
1816       break;
1817     case DBUS_TYPE_OBJECT_PATH:
1818       _dbus_assert_not_reached ("FIXME object path is a basic type");
1819       break;
1820     default:
1821       _dbus_verbose ("type %s not a basic type\n",
1822                      _dbus_type_to_string (type));
1823       _dbus_assert_not_reached ("not a basic type");
1824       break;
1825     }
1826 }
1827
1828 /**
1829  * Skips an array, returning the next position.
1830  *
1831  * @param str the string containing the data
1832  * @param byte_order the byte order
1833  * @param pos pointer to position in the string,
1834  *            updated on return to new position
1835  */
1836 void
1837 _dbus_marshal_skip_array (const DBusString  *str,
1838                           int                byte_order,
1839                           int               *pos)
1840 {
1841   int len;
1842
1843   len = _dbus_demarshal_uint32 (str, byte_order, *pos, pos);
1844
1845   /* FIXME we need to insert alignment padding according to array type */
1846   
1847   *pos += len;
1848 }
1849
1850 /** 
1851  * Returns the position right after the end of an argument.  PERFORMS
1852  * NO VALIDATION WHATSOEVER. The message must have been previously
1853  * validated.
1854  *
1855  * @param str a string
1856  * @param byte_order the byte order to use
1857  * @param type the type of the argument
1858  * @param pos the pos where the arg starts
1859  * @param end_pos pointer where the position right
1860  * after the end position will follow
1861  * @returns TRUE if more data exists after the arg
1862  */
1863 dbus_bool_t
1864 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1865                                int               byte_order,
1866                                int               type,
1867                                int               pos,
1868                                int              *end_pos)
1869 {
1870   if (pos >= _dbus_string_get_length (str))
1871     return FALSE;
1872
1873   switch (type)
1874     {
1875     case DBUS_TYPE_INVALID:
1876       return FALSE;
1877       break;
1878
1879     case DBUS_TYPE_BYTE:
1880       *end_pos = pos + 1;
1881       break;
1882       
1883     case DBUS_TYPE_BOOLEAN:
1884       *end_pos = pos + 1;
1885       break;
1886
1887     case DBUS_TYPE_INT32:
1888     case DBUS_TYPE_UINT32:
1889       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1890       break;
1891
1892     case DBUS_TYPE_INT64:
1893     case DBUS_TYPE_UINT64:
1894     case DBUS_TYPE_DOUBLE:
1895       
1896       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1897       break;
1898
1899     case DBUS_TYPE_OBJECT_PATH:
1900     case DBUS_TYPE_STRING:
1901       {
1902         int len;
1903         
1904         /* Demarshal the length */
1905         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1906
1907         *end_pos = pos + len + 1;
1908       }
1909       break;
1910       
1911     case DBUS_TYPE_ARRAY:
1912       {
1913         int len;
1914
1915         /* Demarshal the length  */
1916         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1917
1918         /* FIXME needs to align to the right boundary for the array type */
1919         *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + len;
1920       }
1921       break;
1922
1923     case DBUS_TYPE_DICT:
1924       {
1925         int len;
1926
1927         /* Demarshal the length */
1928         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1929         
1930         *end_pos = pos + len;
1931       }
1932       break;
1933       
1934     default:
1935       _dbus_warn ("Unknown message arg type %d\n", type);
1936       _dbus_assert_not_reached ("Unknown message argument type\n");
1937       return FALSE;
1938     }
1939
1940   if (*end_pos > _dbus_string_get_length (str))
1941     return FALSE;
1942   
1943   return TRUE;
1944 }
1945
1946 /**
1947  * Demarshals and validates a length; returns < 0 if the validation
1948  * fails. The length is required to be small enough that
1949  * len*sizeof(double) will not overflow, and small enough to fit in a
1950  * signed integer. DOES NOT check whether the length points
1951  * beyond the end of the string, because it doesn't know the
1952  * size of array elements.
1953  *
1954  * @param str the string
1955  * @param byte_order the byte order
1956  * @param pos the unaligned string position (snap to next aligned)
1957  * @param new_pos return location for new position.
1958  */
1959 static int
1960 demarshal_and_validate_len (const DBusString *str,
1961                             int               byte_order,
1962                             int               pos,
1963                             int              *new_pos)
1964 {
1965   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1966   unsigned int len;
1967
1968   _dbus_assert (new_pos != NULL);
1969   
1970   if ((align_4 + 4) > _dbus_string_get_length (str))
1971     {
1972       _dbus_verbose ("not enough room in message for array length\n");
1973       return -1;
1974     }
1975   
1976   if (!_dbus_string_validate_nul (str, pos,
1977                                   align_4 - pos))
1978     {
1979       _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
1980       return -1;
1981     }
1982
1983   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1984
1985   /* note that the len is the number of bytes, so we need it to be
1986    * at least SIZE_T_MAX, but make it smaller just to keep things
1987    * sane.  We end up using ints for most sizes to avoid unsigned mess
1988    * so limit to maximum 32-bit signed int divided by at least 8, more
1989    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1990    */  
1991 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1992   if (len > MAX_ARRAY_LENGTH)
1993     {
1994       _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
1995                      len, MAX_ARRAY_LENGTH, pos);
1996       return -1;
1997     }
1998   else
1999     return (int) len;
2000 }
2001
2002 static dbus_bool_t
2003 validate_string (const DBusString *str,
2004                  int               pos,
2005                  int               len_without_nul,
2006                  int              *end_pos)
2007 {
2008   *end_pos = pos + len_without_nul + 1;
2009   
2010   if (*end_pos > _dbus_string_get_length (str))
2011     {
2012       _dbus_verbose ("string length outside length of the message\n");
2013       return FALSE;
2014     }
2015   
2016   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
2017     {
2018       _dbus_verbose ("string arg not nul-terminated\n");
2019       return FALSE;
2020     }
2021   
2022   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
2023     {
2024       _dbus_verbose ("string is not valid UTF-8\n");
2025       return FALSE;
2026     }
2027
2028   return TRUE;
2029 }   
2030
2031 /**
2032  * Validates and returns a typecode at a specific position
2033  * in the message
2034  *
2035  * @param str a string
2036  * @param type the type of the argument
2037  * @param pos the pos where the typecode starts
2038  * @param end_pos pointer where the position right
2039  * after the end position will follow
2040  * @returns #TRUE if the type is valid.
2041  */
2042 dbus_bool_t
2043 _dbus_marshal_validate_type   (const DBusString *str,
2044                                int               pos,
2045                                int              *type,
2046                                int              *end_pos)
2047 {
2048   const char *data;
2049   
2050   if (pos >= _dbus_string_get_length (str))
2051     return FALSE;
2052
2053   data = _dbus_string_get_const_data_len (str, pos, 1);
2054
2055   if (_dbus_type_is_valid (*data))
2056     {
2057       *type = *data;
2058       if (end_pos != NULL)
2059         *end_pos = pos + 1;
2060       return TRUE;
2061     }
2062
2063   _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
2064   
2065   return FALSE;
2066 }
2067
2068 /* Faster validator for array data that doesn't call
2069  * validate_arg for each value
2070  */
2071 static dbus_bool_t
2072 validate_array_data (const DBusString *str,
2073                      int               byte_order,
2074                      int               depth,
2075                      int               type,
2076                      int               array_type_pos,
2077                      int               pos,
2078                      int              *new_pos,
2079                      int               end)
2080 {
2081   switch (type)
2082     {
2083     case DBUS_TYPE_INVALID:
2084       return FALSE;
2085       break;
2086
2087     case DBUS_TYPE_OBJECT_PATH:
2088     case DBUS_TYPE_STRING:
2089     case DBUS_TYPE_ARRAY:
2090     case DBUS_TYPE_DICT:
2091       /* This clean recursion to validate_arg is what we
2092        * are doing logically for all types, but we don't
2093        * really want to call validate_arg for every byte
2094        * in a byte array, so the primitive types are
2095        * special-cased.
2096        */
2097       while (pos < end)
2098         {
2099           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2100                                            type, array_type_pos, pos, &pos))
2101             return FALSE;
2102         }
2103       break;
2104       
2105     case DBUS_TYPE_BYTE:
2106       pos = end;
2107       break;
2108       
2109     case DBUS_TYPE_BOOLEAN:
2110       while (pos < end)
2111         {
2112           unsigned char c;
2113           
2114           c = _dbus_string_get_byte (str, pos);
2115           
2116           if (!(c == 0 || c == 1))
2117             {
2118               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2119               return FALSE;
2120             }
2121           
2122           ++pos;
2123         }
2124       break;
2125       
2126     case DBUS_TYPE_INT32:
2127     case DBUS_TYPE_UINT32:
2128       /* Call validate arg one time to check alignment padding
2129        * at start of array
2130        */
2131       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2132                                        type, array_type_pos, pos, &pos))
2133         return FALSE;
2134       pos = _DBUS_ALIGN_VALUE (end, 4);
2135       break;
2136
2137     case DBUS_TYPE_INT64:
2138     case DBUS_TYPE_UINT64:
2139     case DBUS_TYPE_DOUBLE:
2140       /* Call validate arg one time to check alignment padding
2141        * at start of array
2142        */
2143       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2144                                        type, array_type_pos, pos, &pos))
2145         return FALSE;
2146       pos = _DBUS_ALIGN_VALUE (end, 8);
2147       break;
2148       
2149     default:
2150       _dbus_verbose ("Unknown message arg type %d\n", type);
2151       return FALSE;
2152     }
2153
2154   *new_pos = pos;
2155
2156   return TRUE;
2157 }
2158
2159 /** 
2160  * Validates an argument of a specific type, checking that it
2161  * is well-formed, for example no ludicrous length fields, strings
2162  * are nul-terminated, etc.
2163  * Returns the end position of the argument in end_pos, and
2164  * returns #TRUE if a valid arg begins at "pos"
2165  *
2166  * @todo security: need to audit this function.
2167  * 
2168  * @param str a string
2169  * @param byte_order the byte order to use
2170  * @param depth current recursion depth, to prevent excessive recursion
2171  * @param type the type of the argument
2172  * @param array_type_pos the position of the current array type, or
2173  *        -1 if not in an array
2174  * @param pos the pos where the arg starts
2175  * @param end_pos pointer where the position right
2176  * after the end position will follow
2177  * @returns #TRUE if the arg is valid.
2178  */
2179 dbus_bool_t
2180 _dbus_marshal_validate_arg (const DBusString *str,
2181                             int               byte_order,
2182                             int               depth,
2183                             int               type,
2184                             int               array_type_pos,
2185                             int               pos,
2186                             int              *end_pos)
2187 {
2188   if (pos > _dbus_string_get_length (str))
2189     {
2190       _dbus_verbose ("Validation went off the end of the message\n");
2191       return FALSE;
2192     }
2193
2194 #define MAX_VALIDATION_DEPTH 32
2195   
2196   if (depth > MAX_VALIDATION_DEPTH)
2197     {
2198       _dbus_verbose ("Maximum recursion depth reached validating message\n");
2199       return FALSE;
2200     }
2201   
2202   switch (type)
2203     {
2204     case DBUS_TYPE_INVALID:
2205       return FALSE;
2206       break;
2207
2208     case DBUS_TYPE_BYTE:
2209       if (1 > _dbus_string_get_length (str) - pos)
2210         {
2211           _dbus_verbose ("no room for byte value\n");
2212           return FALSE;
2213         }
2214         
2215       *end_pos = pos + 1;
2216       break;
2217       
2218     case DBUS_TYPE_BOOLEAN:
2219       {
2220         unsigned char c;
2221
2222         if (1 > _dbus_string_get_length (str) - pos)
2223           {
2224             _dbus_verbose ("no room for boolean value\n");
2225             return FALSE;
2226           }
2227         
2228         c = _dbus_string_get_byte (str, pos);
2229
2230         if (!(c == 0 || c == 1))
2231           {
2232             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2233             return FALSE;
2234           }
2235         
2236         *end_pos = pos + 1;
2237       }
2238       break;
2239       
2240     case DBUS_TYPE_INT32:
2241     case DBUS_TYPE_UINT32:
2242       {
2243         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
2244         
2245         if (!_dbus_string_validate_nul (str, pos,
2246                                         align_4 - pos))
2247           {
2248             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2249             return FALSE;
2250           }
2251
2252         *end_pos = align_4 + 4;
2253       }
2254       break;
2255
2256     case DBUS_TYPE_INT64:
2257     case DBUS_TYPE_UINT64:      
2258     case DBUS_TYPE_DOUBLE:
2259       {
2260         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2261
2262         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2263         
2264         if (!_dbus_string_validate_nul (str, pos,
2265                                         align_8 - pos))
2266           {
2267             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
2268             return FALSE;
2269           }
2270
2271         *end_pos = align_8 + 8;
2272       }
2273       break;
2274
2275     case DBUS_TYPE_OBJECT_PATH:
2276     case DBUS_TYPE_STRING:
2277       {
2278         int len;
2279
2280         /* Demarshal the length, which does NOT include
2281          * nul termination
2282          */
2283         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2284         if (len < 0)
2285           return FALSE;
2286
2287         if (!validate_string (str, pos, len, end_pos))
2288           return FALSE;
2289
2290         if (type == DBUS_TYPE_OBJECT_PATH)
2291           {
2292             if (!_dbus_string_validate_path (str, pos, len))
2293               return FALSE;
2294           }
2295       }
2296       break;
2297       
2298     case DBUS_TYPE_ARRAY:
2299       {
2300         int len;
2301         int end;
2302         int array_type;
2303
2304         if (array_type_pos == -1)
2305           {
2306             array_type_pos = pos;
2307
2308             do
2309               {
2310                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2311                   {
2312                     _dbus_verbose ("invalid array type\n");
2313                     return FALSE;
2314                   }
2315               }
2316             while (array_type == DBUS_TYPE_ARRAY);
2317           }
2318         else
2319           array_type_pos++;
2320
2321         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2322           {
2323             _dbus_verbose ("invalid array type\n");
2324             return FALSE;
2325           }
2326         
2327         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2328         if (len < 0)
2329           {
2330             _dbus_verbose ("invalid array length (<0)\n");
2331             return FALSE;
2332           }
2333
2334         if (len > _dbus_string_get_length (str) - pos)
2335           {
2336             _dbus_verbose ("array length outside length of the message\n");
2337             return FALSE;
2338           }
2339         
2340         end = pos + len;
2341
2342         if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
2343                                              array_type, array_type_pos,
2344                                              pos, &pos, end))
2345           {
2346             _dbus_verbose ("invalid array data\n");
2347             return FALSE;
2348           }
2349
2350         if (pos < end)
2351           {
2352             /* This should not be able to happen, as long as validate_arg moves forward;
2353              * but the check is here just to be paranoid.
2354              */
2355             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2356                            len, end - pos);
2357             return FALSE;
2358           }
2359         
2360         if (pos > end)
2361           {
2362             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2363             return FALSE;
2364           }
2365
2366         *end_pos = pos;
2367       }
2368       break;
2369
2370     case DBUS_TYPE_DICT:
2371       {
2372         int dict_type;
2373         int len;
2374         int end;
2375         
2376         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2377         if (len < 0)
2378           return FALSE;
2379
2380         if (len > _dbus_string_get_length (str) - pos)
2381           {
2382             _dbus_verbose ("dict length outside length of the message\n");
2383             return FALSE;
2384           }
2385         
2386         end = pos + len;
2387         
2388         while (pos < end)
2389           {
2390             /* Validate name */
2391             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2392                                              DBUS_TYPE_STRING, -1, pos, &pos))
2393               return FALSE;
2394             
2395             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2396               {
2397                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2398                 return FALSE;
2399               }
2400             
2401             /* Validate element */
2402             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2403                                              dict_type, -1, pos, &pos))
2404               {
2405                 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
2406                 return FALSE;
2407               }
2408           }
2409         
2410         if (pos > end)
2411           {
2412             _dbus_verbose ("dict contents exceed stated dict length\n");
2413             return FALSE;
2414           }
2415         
2416         *end_pos = pos;
2417       }
2418       break;
2419       
2420     default:
2421       _dbus_verbose ("Unknown message arg type %d\n", type);
2422       return FALSE;
2423     }
2424
2425   if (*end_pos > _dbus_string_get_length (str))
2426     return FALSE;
2427   
2428   return TRUE;
2429 }
2430
2431 /**
2432  * Return #TRUE if the typecode is a valid typecode
2433  *
2434  * @returns #TRUE if valid
2435  */
2436 dbus_bool_t
2437 _dbus_type_is_valid (int typecode)
2438 {
2439   switch (typecode)
2440     {
2441     case DBUS_TYPE_BYTE:
2442     case DBUS_TYPE_BOOLEAN:
2443     case DBUS_TYPE_INT32:
2444     case DBUS_TYPE_UINT32:
2445     case DBUS_TYPE_INT64:
2446     case DBUS_TYPE_UINT64:
2447     case DBUS_TYPE_DOUBLE:
2448     case DBUS_TYPE_STRING:
2449     case DBUS_TYPE_OBJECT_PATH:
2450     case DBUS_TYPE_ARRAY:
2451     case DBUS_TYPE_DICT:
2452     case DBUS_TYPE_STRUCT:
2453     case DBUS_TYPE_VARIANT:
2454       return TRUE;
2455       
2456     default:
2457       return FALSE;
2458     }
2459 }
2460
2461 /**
2462  * Gets the alignment requirement for the given type;
2463  * will be 1, 4, or 8.
2464  *
2465  * @param typecode the type
2466  * @returns alignment of 1, 4, or 8
2467  */
2468 int
2469 _dbus_type_get_alignment (int typecode)
2470 {
2471   switch (typecode)
2472     {
2473     case DBUS_TYPE_BYTE:
2474     case DBUS_TYPE_BOOLEAN:
2475       return 1;
2476     case DBUS_TYPE_INT32:
2477     case DBUS_TYPE_UINT32:
2478       /* this stuff is 4 since it starts with a length */
2479     case DBUS_TYPE_STRING:
2480     case DBUS_TYPE_OBJECT_PATH:
2481     case DBUS_TYPE_ARRAY:
2482     case DBUS_TYPE_DICT:
2483     case DBUS_TYPE_VARIANT:
2484       return 4;
2485     case DBUS_TYPE_INT64:
2486     case DBUS_TYPE_UINT64:
2487     case DBUS_TYPE_DOUBLE:
2488       /* struct is 8 since it could contain an 8-aligned item
2489        * and it's simpler to just always align structs to 8;
2490        * we want the amount of padding in a struct of a given
2491        * type to be predictable, not location-dependent.
2492        */
2493     case DBUS_TYPE_STRUCT:
2494       return 8;
2495       
2496     default:
2497       _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
2498       return 0;
2499     }
2500 }
2501
2502 /**
2503  * If in verbose mode, print a block of binary data.
2504  *
2505  * @todo right now it prints even if not in verbose mode
2506  * 
2507  * @param data the data
2508  * @param len the length of the data
2509  * @param offset where to start counting for byte indexes
2510  */
2511 void
2512 _dbus_verbose_bytes (const unsigned char *data,
2513                      int                  len,
2514                      int                  offset)
2515 {
2516   int i;
2517   const unsigned char *aligned;
2518
2519   _dbus_assert (len >= 0);
2520   
2521   /* Print blanks on first row if appropriate */
2522   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2523   if (aligned > data)
2524     aligned -= 4;
2525   _dbus_assert (aligned <= data);
2526
2527   if (aligned != data)
2528     {
2529       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2530       while (aligned != data)
2531         {
2532           _dbus_verbose ("    ");
2533           ++aligned;
2534         }
2535     }
2536
2537   /* now print the bytes */
2538   i = 0;
2539   while (i < len)
2540     {
2541       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2542         {
2543           _dbus_verbose ("%4d\t%p: ",
2544                          offset + i, &data[i]);
2545         }
2546       
2547       if (data[i] >= 32 &&
2548           data[i] <= 126)
2549         _dbus_verbose (" '%c' ", data[i]);
2550       else
2551         _dbus_verbose ("0x%s%x ",
2552                        data[i] <= 0xf ? "0" : "", data[i]);
2553
2554       ++i;
2555
2556       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2557         {
2558           if (i > 3)
2559             _dbus_verbose ("BE: %d LE: %d",
2560                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2561                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2562
2563           if (i > 7 && 
2564               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2565             {
2566               _dbus_verbose (" dbl: %g",
2567                              *(double*)&data[i-8]);
2568             }
2569           
2570           _dbus_verbose ("\n");
2571         }
2572     }
2573
2574   _dbus_verbose ("\n");
2575 }
2576
2577 /**
2578  * Dump the given part of the string to verbose log.
2579  *
2580  * @param str the string
2581  * @param start the start of range to dump
2582  * @param len length of range
2583  */
2584 void
2585 _dbus_verbose_bytes_of_string (const DBusString    *str,
2586                                int                  start,
2587                                int                  len)
2588 {
2589   const char *d;
2590   int real_len;
2591
2592   real_len = _dbus_string_get_length (str);
2593
2594   _dbus_assert (start >= 0);
2595   
2596   if (start > real_len)
2597     {
2598       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2599                      start, len, real_len);
2600       return;
2601     }
2602
2603   if ((start + len) > real_len)
2604     {
2605       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2606                      start, len, real_len);
2607       len = real_len - start;
2608     }
2609   
2610   d = _dbus_string_get_const_data_len (str, start, len);
2611
2612   _dbus_verbose_bytes (d, len, start);
2613 }
2614
2615 /**
2616  * Marshals a basic type
2617  *
2618  * @param str string to marshal to
2619  * @param insert_at where to insert the value
2620  * @param type type of value
2621  * @param value pointer to value
2622  * @param byte_order byte order
2623  * @returns #TRUE on success
2624  **/
2625 dbus_bool_t
2626 _dbus_marshal_basic_type (DBusString *str,
2627                           int         insert_at,
2628                           char        type,
2629                           const void *value,
2630                           int         byte_order)
2631 {
2632   dbus_bool_t retval;
2633
2634   switch (type)
2635     {
2636     case DBUS_TYPE_BYTE:
2637     case DBUS_TYPE_BOOLEAN:
2638       retval = _dbus_string_insert_byte (str, insert_at, *(const unsigned char *)value);
2639       break;
2640     case DBUS_TYPE_INT32:
2641     case DBUS_TYPE_UINT32:
2642       return marshal_4_octets (str, insert_at, byte_order, *(const dbus_uint32_t *)value);
2643       break;
2644 #ifdef DBUS_HAVE_INT64
2645     case DBUS_TYPE_INT64:
2646     case DBUS_TYPE_UINT64:
2647       {
2648         DBusOctets8 r;
2649         r.u = *(const dbus_uint64_t *)value;
2650         retval = marshal_8_octets (str, insert_at, byte_order, r);
2651       }
2652       break;
2653 #endif /* DBUS_HAVE_INT64 */
2654     case DBUS_TYPE_DOUBLE:
2655       {
2656         DBusOctets8 r;
2657         r.d = *(const double *)value;
2658         retval = marshal_8_octets (str, insert_at, byte_order, r);
2659       }
2660       break;
2661     default:
2662       _dbus_assert_not_reached ("not a basic type");
2663       retval = FALSE;
2664       break;
2665     }
2666   return retval;
2667 }
2668
2669 /**
2670  * Marshals a basic type array
2671  *
2672  * @param str string to marshal to
2673  * @param insert_at where to insert the value
2674  * @param element_type type of array elements
2675  * @param value pointer to value
2676  * @param len length of value data in elements
2677  * @param byte_order byte order
2678  * @returns #TRUE on success
2679  **/
2680 dbus_bool_t
2681 _dbus_marshal_basic_type_array (DBusString *str,
2682                                 int         insert_at,
2683                                 char        element_type,
2684                                 const void *value,
2685                                 int         len,
2686                                 int         byte_order)
2687 {
2688   /* FIXME use the insert_at arg */
2689   
2690   switch (element_type)
2691     {
2692     case DBUS_TYPE_BOOLEAN:
2693       /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
2694        * should we here too ? */
2695     case DBUS_TYPE_BYTE:
2696       return _dbus_marshal_byte_array (str, byte_order, value, len);
2697       break;
2698     case DBUS_TYPE_INT32:
2699     case DBUS_TYPE_UINT32:
2700       return marshal_4_octets_array (str, byte_order, value, len);
2701       break;
2702 #ifdef DBUS_HAVE_INT64
2703     case DBUS_TYPE_INT64:
2704     case DBUS_TYPE_UINT64: 
2705 #endif /* DBUS_HAVE_INT64 */
2706     case DBUS_TYPE_DOUBLE:
2707       return marshal_8_octets_array (str, byte_order, value, len);
2708       break;
2709     default:
2710       _dbus_assert_not_reached ("non basic type in array");
2711       break;
2712     }
2713   return FALSE;
2714 }
2715
2716 /** @} */
2717
2718 #ifdef DBUS_BUILD_TESTS
2719 #include "dbus-test.h"
2720 #include <stdio.h>
2721
2722 dbus_bool_t
2723 _dbus_marshal_test (void)
2724 {
2725   DBusString str;
2726   char *tmp1, *tmp2;
2727   int pos = 0, len;
2728   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2729 #ifdef DBUS_HAVE_INT64
2730   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
2731                              DBUS_INT64_CONSTANT (0x456ffffffff), 
2732                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
2733 #endif
2734   char *s;
2735   DBusString t;
2736   
2737   if (!_dbus_string_init (&str))
2738     _dbus_assert_not_reached ("failed to init string");
2739
2740   /* Marshal doubles */
2741   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2742     _dbus_assert_not_reached ("could not marshal double value");
2743   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2744     _dbus_assert_not_reached ("demarshal failed");
2745
2746   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2747     _dbus_assert_not_reached ("could not marshal double value");
2748   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2749     _dbus_assert_not_reached ("demarshal failed");
2750   
2751   /* Marshal signed integers */
2752   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2753     _dbus_assert_not_reached ("could not marshal signed integer value");
2754   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2755     _dbus_assert_not_reached ("demarshal failed");
2756
2757   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2758     _dbus_assert_not_reached ("could not marshal signed integer value");
2759   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2760     _dbus_assert_not_reached ("demarshal failed");
2761   
2762   /* Marshal unsigned integers */
2763   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2764     _dbus_assert_not_reached ("could not marshal signed integer value");
2765   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2766     _dbus_assert_not_reached ("demarshal failed");
2767   
2768   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2769     _dbus_assert_not_reached ("could not marshal signed integer value");
2770   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2771     _dbus_assert_not_reached ("demarshal failed");
2772
2773 #ifdef DBUS_HAVE_INT64
2774   /* Marshal signed integers */
2775   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2776     _dbus_assert_not_reached ("could not marshal signed integer value");
2777   if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2778     _dbus_assert_not_reached ("demarshal failed");
2779
2780   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2781     _dbus_assert_not_reached ("could not marshal signed integer value");
2782   if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2783     _dbus_assert_not_reached ("demarshal failed");
2784   
2785   /* Marshal unsigned integers */
2786   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2787     _dbus_assert_not_reached ("could not marshal signed integer value");
2788   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2789     _dbus_assert_not_reached ("demarshal failed");
2790   
2791   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2792     _dbus_assert_not_reached ("could not marshal signed integer value");
2793   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2794     _dbus_assert_not_reached ("demarshal failed");
2795 #endif /* DBUS_HAVE_INT64 */
2796   
2797   /* Marshal strings */
2798   tmp1 = "This is the dbus test string";
2799   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2800     _dbus_assert_not_reached ("could not marshal string");
2801   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2802   if (!strcmp (tmp1, tmp2) == 0)
2803     _dbus_assert_not_reached ("demarshal failed");
2804   dbus_free (tmp2);
2805
2806   tmp1 = "This is the dbus test string";
2807   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2808     _dbus_assert_not_reached ("could not marshal string");
2809   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2810   if (!strcmp (tmp1, tmp2) == 0)
2811     _dbus_assert_not_reached ("demarshal failed");
2812   dbus_free (tmp2);
2813
2814   /* Marshal signed integer arrays */
2815   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2816     _dbus_assert_not_reached ("could not marshal integer array");
2817   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2818     _dbus_assert_not_reached ("could not demarshal integer array");
2819
2820   if (len != 3)
2821     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2822   dbus_free (array2);
2823
2824 #ifdef DBUS_HAVE_INT64
2825   /* Marshal 64-bit signed integer arrays */
2826   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2827     _dbus_assert_not_reached ("could not marshal integer array");
2828   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2829     _dbus_assert_not_reached ("could not demarshal integer array");
2830
2831   if (len != 3)
2832     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2833   dbus_free (array4);
2834
2835   /* set/pack 64-bit integers */
2836   _dbus_string_set_length (&str, 8);
2837
2838   /* signed little */
2839   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2840                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2841   
2842   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2843                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2844                                     _dbus_string_get_const_data (&str)));
2845
2846   /* signed big */
2847   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2848                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2849
2850   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2851                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2852                                     _dbus_string_get_const_data (&str)));
2853
2854   /* signed little pack */
2855   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2856                     DBUS_LITTLE_ENDIAN,
2857                     _dbus_string_get_data (&str));
2858   
2859   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2860                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2861                                     _dbus_string_get_const_data (&str)));
2862
2863   /* signed big pack */
2864   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2865                     DBUS_BIG_ENDIAN,
2866                     _dbus_string_get_data (&str));
2867
2868   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2869                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2870                                     _dbus_string_get_const_data (&str)));
2871
2872   /* unsigned little */
2873   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2874                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2875   
2876   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2877                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2878                                      _dbus_string_get_const_data (&str)));
2879
2880   /* unsigned big */
2881   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2882                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2883
2884   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2885                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2886                                      _dbus_string_get_const_data (&str)));
2887
2888   /* unsigned little pack */
2889   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2890                      DBUS_LITTLE_ENDIAN,
2891                      _dbus_string_get_data (&str));
2892   
2893   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2894                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2895                                      _dbus_string_get_const_data (&str)));
2896
2897   /* unsigned big pack */
2898   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2899                      DBUS_BIG_ENDIAN,
2900                      _dbus_string_get_data (&str));
2901
2902   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2903                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2904                                      _dbus_string_get_const_data (&str)));
2905   
2906 #endif
2907
2908   /* set/pack 32-bit integers */
2909   _dbus_string_set_length (&str, 4);
2910
2911   /* signed little */
2912   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2913                            0, -0x123456);
2914   
2915   _dbus_assert (-0x123456 ==
2916                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2917                                     _dbus_string_get_const_data (&str)));
2918
2919   /* signed big */
2920   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2921                            0, -0x123456);
2922
2923   _dbus_assert (-0x123456 ==
2924                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2925                                     _dbus_string_get_const_data (&str)));
2926
2927   /* signed little pack */
2928   _dbus_pack_int32 (-0x123456,
2929                     DBUS_LITTLE_ENDIAN,
2930                     _dbus_string_get_data (&str));
2931   
2932   _dbus_assert (-0x123456 ==
2933                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2934                                     _dbus_string_get_const_data (&str)));
2935
2936   /* signed big pack */
2937   _dbus_pack_int32 (-0x123456,
2938                     DBUS_BIG_ENDIAN,
2939                     _dbus_string_get_data (&str));
2940
2941   _dbus_assert (-0x123456 ==
2942                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2943                                     _dbus_string_get_const_data (&str)));
2944
2945   /* unsigned little */
2946   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2947                             0, 0x123456);
2948   
2949   _dbus_assert (0x123456 ==
2950                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2951                                      _dbus_string_get_const_data (&str)));
2952
2953   /* unsigned big */
2954   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2955                             0, 0x123456);
2956
2957   _dbus_assert (0x123456 ==
2958                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2959                                      _dbus_string_get_const_data (&str)));
2960
2961   /* unsigned little pack */
2962   _dbus_pack_uint32 (0x123456,
2963                      DBUS_LITTLE_ENDIAN,
2964                      _dbus_string_get_data (&str));
2965   
2966   _dbus_assert (0x123456 ==
2967                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2968                                      _dbus_string_get_const_data (&str)));
2969
2970   /* unsigned big pack */
2971   _dbus_pack_uint32 (0x123456,
2972                      DBUS_BIG_ENDIAN,
2973                      _dbus_string_get_data (&str));
2974
2975   _dbus_assert (0x123456 ==
2976                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2977                                      _dbus_string_get_const_data (&str)));
2978
2979
2980   /* Strings */
2981   
2982   _dbus_string_set_length (&str, 0);
2983
2984   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2985                         "Hello world");
2986   
2987   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2988   _dbus_assert (strcmp (s, "Hello world") == 0);
2989   dbus_free (s);
2990
2991   _dbus_string_init_const (&t, "Hello world foo");
2992   
2993   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2994                             &t, _dbus_string_get_length (&t));
2995   
2996   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2997   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2998   dbus_free (s);
2999
3000   _dbus_string_init_const (&t, "Hello");
3001   
3002   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
3003                             &t, _dbus_string_get_length (&t));
3004   
3005   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
3006   _dbus_assert (strcmp (s, "Hello") == 0);
3007   dbus_free (s);
3008
3009   /* Strings (big endian) */
3010   
3011   _dbus_string_set_length (&str, 0);
3012
3013   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
3014                         "Hello world");
3015   
3016   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3017   _dbus_assert (strcmp (s, "Hello world") == 0);
3018   dbus_free (s);
3019
3020   _dbus_string_init_const (&t, "Hello world foo");
3021   
3022   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
3023                             &t, _dbus_string_get_length (&t));
3024   
3025   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3026   _dbus_assert (strcmp (s, "Hello world foo") == 0);
3027   dbus_free (s);
3028
3029   _dbus_string_init_const (&t, "Hello");
3030   
3031   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
3032                             &t, _dbus_string_get_length (&t));
3033   
3034   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
3035   _dbus_assert (strcmp (s, "Hello") == 0);
3036   dbus_free (s);
3037   
3038   _dbus_string_free (&str);
3039       
3040   return TRUE;
3041 }
3042
3043 #endif /* DBUS_BUILD_TESTS */