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