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