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