2004-06-05 Olivier Andrieu <oliv__a@users.sourceforge.net>
[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  * Decompose an object path.  A path of just "/" is
1588  * represented as an empty vector of strings.
1589  * 
1590  * @param data the path data
1591  * @param len  the length of the path string
1592  * @param path address to store new object path
1593  * @param path_len length of stored path
1594  */
1595 dbus_bool_t
1596 _dbus_decompose_path (const char*     data,
1597                       int             len,
1598                       char         ***path,
1599                       int            *path_len)
1600 {
1601   char **retval;
1602   int n_components;
1603   int i, j, comp;
1604
1605   _dbus_assert (data != NULL);
1606
1607 #if VERBOSE_DECOMPOSE
1608   _dbus_verbose ("Decomposing path \"%s\"\n",
1609                  data);
1610 #endif
1611   
1612   n_components = 0;
1613   i = 0;
1614   while (i < len)
1615     {
1616       if (data[i] == '/')
1617         n_components += 1;
1618       ++i;
1619     }
1620   
1621   retval = dbus_new0 (char*, n_components + 1);
1622
1623   if (retval == NULL)
1624     return FALSE;
1625
1626   comp = 0;
1627   i = 0;
1628   while (i < len)
1629     {
1630       if (data[i] == '/')
1631         ++i;
1632       j = i;
1633
1634       while (j < len && data[j] != '/')
1635         ++j;
1636
1637       /* Now [i, j) is the path component */
1638       _dbus_assert (i < j);
1639       _dbus_assert (data[i] != '/');
1640       _dbus_assert (j == len || data[j] == '/');
1641
1642 #if VERBOSE_DECOMPOSE
1643       _dbus_verbose ("  (component in [%d,%d))\n",
1644                      i, j);
1645 #endif
1646       
1647       retval[comp] = _dbus_memdup (&data[i], j - i + 1);
1648       if (retval[comp] == NULL)
1649         {
1650           dbus_free_string_array (retval);
1651           return FALSE;
1652         }
1653       retval[comp][j-i] = '\0';
1654 #if VERBOSE_DECOMPOSE
1655       _dbus_verbose ("  (component %d = \"%s\")\n",
1656                      comp, retval[comp]);
1657 #endif
1658
1659       ++comp;
1660       i = j;
1661     }
1662   _dbus_assert (i == len);
1663   
1664   *path = retval;
1665   if (path_len)
1666     *path_len = n_components;
1667   
1668   return TRUE;
1669 }
1670
1671 /**
1672  * Demarshals an object path.  A path of just "/" is
1673  * represented as an empty vector of strings.
1674  * 
1675  * @param str the string containing the data
1676  * @param byte_order the byte order
1677  * @param pos the position in the string
1678  * @param new_pos the new position of the string
1679  * @param path address to store new object path
1680  * @param path_len length of stored path
1681  */
1682 dbus_bool_t
1683 _dbus_demarshal_object_path (const DBusString *str,
1684                              int               byte_order,
1685                              int               pos,
1686                              int              *new_pos,
1687                              char           ***path,
1688                              int              *path_len)
1689 {
1690   int len;
1691   const char *data;
1692   
1693   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1694   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1695
1696   if (!_dbus_decompose_path (data, len, path, path_len))
1697     return FALSE;
1698
1699   if (new_pos)
1700     *new_pos = pos + len + 1;
1701
1702   return TRUE;
1703 }
1704
1705 /** 
1706  * Returns the position right after the end of an argument.  PERFORMS
1707  * NO VALIDATION WHATSOEVER. The message must have been previously
1708  * validated.
1709  *
1710  * @param str a string
1711  * @param byte_order the byte order to use
1712  * @param type the type of the argument
1713  * @param pos the pos where the arg starts
1714  * @param end_pos pointer where the position right
1715  * after the end position will follow
1716  * @returns TRUE if more data exists after the arg
1717  */
1718 dbus_bool_t
1719 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1720                                int               byte_order,
1721                                int               type,
1722                                int               pos,
1723                                int              *end_pos)
1724 {
1725   if (pos >= _dbus_string_get_length (str))
1726     return FALSE;
1727
1728   switch (type)
1729     {
1730     case DBUS_TYPE_INVALID:
1731       return FALSE;
1732       break;
1733
1734     case DBUS_TYPE_NIL:
1735       *end_pos = pos;
1736       break;
1737
1738     case DBUS_TYPE_BYTE:
1739       *end_pos = pos + 1;
1740       break;
1741       
1742     case DBUS_TYPE_BOOLEAN:
1743       *end_pos = pos + 1;
1744       break;
1745
1746     case DBUS_TYPE_INT32:
1747     case DBUS_TYPE_UINT32:
1748       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1749       break;
1750
1751     case DBUS_TYPE_INT64:
1752     case DBUS_TYPE_UINT64:
1753     case DBUS_TYPE_DOUBLE:
1754       
1755       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1756       break;
1757
1758     case DBUS_TYPE_OBJECT_PATH:
1759     case DBUS_TYPE_STRING:
1760       {
1761         int len;
1762         
1763         /* Demarshal the length */
1764         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1765
1766         *end_pos = pos + len + 1;
1767       }
1768       break;
1769
1770     case DBUS_TYPE_CUSTOM:
1771       {
1772         int len;
1773         
1774         /* Demarshal the string length */
1775         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1776
1777         pos += len + 1;
1778         
1779         /* Demarshal the data length */
1780         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1781
1782         *end_pos = pos + len;
1783       }
1784       break;
1785       
1786     case DBUS_TYPE_ARRAY:
1787       {
1788         int len;
1789
1790         /* Demarshal the length  */
1791         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1792         
1793         *end_pos = pos + len;
1794       }
1795       break;
1796
1797     case DBUS_TYPE_DICT:
1798       {
1799         int len;
1800
1801         /* Demarshal the length */
1802         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1803         
1804         *end_pos = pos + len;
1805       }
1806       break;
1807       
1808     default:
1809       _dbus_warn ("Unknown message arg type %d\n", type);
1810       _dbus_assert_not_reached ("Unknown message argument type\n");
1811       return FALSE;
1812     }
1813
1814   if (*end_pos > _dbus_string_get_length (str))
1815     return FALSE;
1816   
1817   return TRUE;
1818 }
1819
1820 /**
1821  * Demarshals and validates a length; returns < 0 if the validation
1822  * fails. The length is required to be small enough that
1823  * len*sizeof(double) will not overflow, and small enough to fit in a
1824  * signed integer. DOES NOT check whether the length points
1825  * beyond the end of the string, because it doesn't know the
1826  * size of array elements.
1827  *
1828  * @param str the string
1829  * @param byte_order the byte order
1830  * @param pos the unaligned string position (snap to next aligned)
1831  * @param new_pos return location for new position.
1832  */
1833 static int
1834 demarshal_and_validate_len (const DBusString *str,
1835                             int               byte_order,
1836                             int               pos,
1837                             int              *new_pos)
1838 {
1839   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1840   unsigned int len;
1841
1842   _dbus_assert (new_pos != NULL);
1843   
1844   if ((align_4 + 4) > _dbus_string_get_length (str))
1845     {
1846       _dbus_verbose ("not enough room in message for array length\n");
1847       return -1;
1848     }
1849   
1850   if (!_dbus_string_validate_nul (str, pos,
1851                                   align_4 - pos))
1852     {
1853       _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
1854       return -1;
1855     }
1856
1857   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1858
1859   /* note that the len is the number of bytes, so we need it to be
1860    * at least SIZE_T_MAX, but make it smaller just to keep things
1861    * sane.  We end up using ints for most sizes to avoid unsigned mess
1862    * so limit to maximum 32-bit signed int divided by at least 8, more
1863    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1864    */  
1865 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1866   if (len > MAX_ARRAY_LENGTH)
1867     {
1868       _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
1869                      len, MAX_ARRAY_LENGTH, pos);
1870       return -1;
1871     }
1872   else
1873     return (int) len;
1874 }
1875
1876 static dbus_bool_t
1877 validate_string (const DBusString *str,
1878                  int               pos,
1879                  int               len_without_nul,
1880                  int              *end_pos)
1881 {
1882   *end_pos = pos + len_without_nul + 1;
1883   
1884   if (*end_pos > _dbus_string_get_length (str))
1885     {
1886       _dbus_verbose ("string length outside length of the message\n");
1887       return FALSE;
1888     }
1889   
1890   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1891     {
1892       _dbus_verbose ("string arg not nul-terminated\n");
1893       return FALSE;
1894     }
1895   
1896   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1897     {
1898       _dbus_verbose ("string is not valid UTF-8\n");
1899       return FALSE;
1900     }
1901
1902   return TRUE;
1903 }   
1904
1905 /**
1906  * Validates and returns a typecode at a specific position
1907  * in the message
1908  *
1909  * @param str a string
1910  * @param type the type of the argument
1911  * @param pos the pos where the typecode starts
1912  * @param end_pos pointer where the position right
1913  * after the end position will follow
1914  * @returns #TRUE if the type is valid.
1915  */
1916 dbus_bool_t
1917 _dbus_marshal_validate_type   (const DBusString *str,
1918                                int               pos,
1919                                int              *type,
1920                                int              *end_pos)
1921 {
1922   const char *data;
1923   
1924   if (pos >= _dbus_string_get_length (str))
1925     return FALSE;
1926
1927   data = _dbus_string_get_const_data_len (str, pos, 1);
1928
1929   if (_dbus_type_is_valid (*data))
1930     {
1931       *type = *data;
1932       if (end_pos != NULL)
1933         *end_pos = pos + 1;
1934       return TRUE;
1935     }
1936
1937   _dbus_verbose ("'%c' %d invalid type code\n", (int) *data, (int) *data);
1938   
1939   return FALSE;
1940 }
1941
1942 /* Faster validator for array data that doesn't call
1943  * validate_arg for each value
1944  */
1945 static dbus_bool_t
1946 validate_array_data (const DBusString *str,
1947                      int               byte_order,
1948                      int               depth,
1949                      int               type,
1950                      int               array_type_pos,
1951                      int               pos,
1952                      int              *new_pos,
1953                      int               end)
1954 {
1955   switch (type)
1956     {
1957     case DBUS_TYPE_INVALID:
1958       return FALSE;
1959       break;
1960
1961     case DBUS_TYPE_NIL:
1962       break;
1963
1964     case DBUS_TYPE_OBJECT_PATH:
1965     case DBUS_TYPE_STRING:
1966     case DBUS_TYPE_CUSTOM:
1967     case DBUS_TYPE_ARRAY:
1968     case DBUS_TYPE_DICT:
1969       /* This clean recursion to validate_arg is what we
1970        * are doing logically for all types, but we don't
1971        * really want to call validate_arg for every byte
1972        * in a byte array, so the primitive types are
1973        * special-cased.
1974        */
1975       while (pos < end)
1976         {
1977           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1978                                            type, array_type_pos, pos, &pos))
1979             return FALSE;
1980         }
1981       break;
1982       
1983     case DBUS_TYPE_BYTE:
1984       pos = end;
1985       break;
1986       
1987     case DBUS_TYPE_BOOLEAN:
1988       while (pos < end)
1989         {
1990           unsigned char c;
1991           
1992           c = _dbus_string_get_byte (str, pos);
1993           
1994           if (!(c == 0 || c == 1))
1995             {
1996               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1997               return FALSE;
1998             }
1999           
2000           ++pos;
2001         }
2002       break;
2003       
2004     case DBUS_TYPE_INT32:
2005     case DBUS_TYPE_UINT32:
2006       /* Call validate arg one time to check alignment padding
2007        * at start of array
2008        */
2009       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2010                                        type, array_type_pos, pos, &pos))
2011         return FALSE;
2012       pos = _DBUS_ALIGN_VALUE (end, 4);
2013       break;
2014
2015     case DBUS_TYPE_INT64:
2016     case DBUS_TYPE_UINT64:
2017     case DBUS_TYPE_DOUBLE:
2018       /* Call validate arg one time to check alignment padding
2019        * at start of array
2020        */
2021       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
2022                                        type, array_type_pos, pos, &pos))
2023         return FALSE;
2024       pos = _DBUS_ALIGN_VALUE (end, 8);
2025       break;
2026       
2027     default:
2028       _dbus_verbose ("Unknown message arg type %d\n", type);
2029       return FALSE;
2030     }
2031
2032   *new_pos = pos;
2033
2034   return TRUE;
2035 }
2036
2037 /** 
2038  * Validates an argument of a specific type, checking that it
2039  * is well-formed, for example no ludicrous length fields, strings
2040  * are nul-terminated, etc.
2041  * Returns the end position of the argument in end_pos, and
2042  * returns #TRUE if a valid arg begins at "pos"
2043  *
2044  * @todo security: need to audit this function.
2045  * 
2046  * @param str a string
2047  * @param byte_order the byte order to use
2048  * @param depth current recursion depth, to prevent excessive recursion
2049  * @param type the type of the argument
2050  * @param array_type_pos the position of the current array type, or
2051  *        -1 if not in an array
2052  * @param pos the pos where the arg starts
2053  * @param end_pos pointer where the position right
2054  * after the end position will follow
2055  * @returns #TRUE if the arg is valid.
2056  */
2057 dbus_bool_t
2058 _dbus_marshal_validate_arg (const DBusString *str,
2059                             int               byte_order,
2060                             int               depth,
2061                             int               type,
2062                             int               array_type_pos,
2063                             int               pos,
2064                             int              *end_pos)
2065 {
2066   if (pos > _dbus_string_get_length (str))
2067     {
2068       _dbus_verbose ("Validation went off the end of the message\n");
2069       return FALSE;
2070     }
2071
2072 #define MAX_VALIDATION_DEPTH 32
2073   
2074   if (depth > MAX_VALIDATION_DEPTH)
2075     {
2076       _dbus_verbose ("Maximum recursion depth reached validating message\n");
2077       return FALSE;
2078     }
2079   
2080   switch (type)
2081     {
2082     case DBUS_TYPE_INVALID:
2083       return FALSE;
2084       break;
2085
2086     case DBUS_TYPE_NIL:
2087       *end_pos = pos;
2088       break;
2089
2090     case DBUS_TYPE_BYTE:
2091       if (1 > _dbus_string_get_length (str) - pos)
2092         {
2093           _dbus_verbose ("no room for byte value\n");
2094           return FALSE;
2095         }
2096         
2097       *end_pos = pos + 1;
2098       break;
2099       
2100     case DBUS_TYPE_BOOLEAN:
2101       {
2102         unsigned char c;
2103
2104         if (1 > _dbus_string_get_length (str) - pos)
2105           {
2106             _dbus_verbose ("no room for boolean value\n");
2107             return FALSE;
2108           }
2109         
2110         c = _dbus_string_get_byte (str, pos);
2111
2112         if (!(c == 0 || c == 1))
2113           {
2114             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
2115             return FALSE;
2116           }
2117         
2118         *end_pos = pos + 1;
2119       }
2120       break;
2121       
2122     case DBUS_TYPE_INT32:
2123     case DBUS_TYPE_UINT32:
2124       {
2125         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
2126         
2127         if (!_dbus_string_validate_nul (str, pos,
2128                                         align_4 - pos))
2129           {
2130             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2131             return FALSE;
2132           }
2133
2134         *end_pos = align_4 + 4;
2135       }
2136       break;
2137
2138     case DBUS_TYPE_INT64:
2139     case DBUS_TYPE_UINT64:      
2140     case DBUS_TYPE_DOUBLE:
2141       {
2142         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2143
2144         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2145         
2146         if (!_dbus_string_validate_nul (str, pos,
2147                                         align_8 - pos))
2148           {
2149             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
2150             return FALSE;
2151           }
2152
2153         *end_pos = align_8 + 8;
2154       }
2155       break;
2156
2157     case DBUS_TYPE_OBJECT_PATH:
2158     case DBUS_TYPE_STRING:
2159       {
2160         int len;
2161
2162         /* Demarshal the length, which does NOT include
2163          * nul termination
2164          */
2165         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2166         if (len < 0)
2167           return FALSE;
2168
2169         if (!validate_string (str, pos, len, end_pos))
2170           return FALSE;
2171
2172         if (type == DBUS_TYPE_OBJECT_PATH)
2173           {
2174             if (!_dbus_string_validate_path (str, pos, len))
2175               return FALSE;
2176           }
2177       }
2178       break;
2179
2180     case DBUS_TYPE_CUSTOM:
2181       {
2182         int len;
2183
2184         /* Demarshal the string length, which does NOT include
2185          * nul termination
2186          */
2187         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2188         if (len < 0)
2189           return FALSE;
2190
2191         if (!validate_string (str, pos, len, &pos))
2192           return FALSE;
2193
2194         /* Validate data */
2195         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2196         if (len < 0)
2197           return FALSE;
2198
2199         *end_pos = pos + len;
2200       }
2201       break;
2202       
2203     case DBUS_TYPE_ARRAY:
2204       {
2205         int len;
2206         int end;
2207         int array_type;
2208
2209         if (array_type_pos == -1)
2210           {
2211             array_type_pos = pos;
2212
2213             do
2214               {
2215                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2216                   {
2217                     _dbus_verbose ("invalid array type\n");
2218                     return FALSE;
2219                   }
2220                 
2221                 /* NIL values take up no space, so you couldn't iterate over an array of them.
2222                  * array of nil seems useless anyway; the useful thing might be array of
2223                  * (nil OR string) but we have no framework for that.
2224                  */
2225                 if (array_type == DBUS_TYPE_NIL)
2226                   {
2227                     _dbus_verbose ("array of NIL is not allowed\n");
2228                     return FALSE;
2229                   }
2230               }
2231             while (array_type == DBUS_TYPE_ARRAY);
2232           }
2233         else
2234           array_type_pos++;
2235
2236         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2237           {
2238             _dbus_verbose ("invalid array type\n");
2239             return FALSE;
2240           }
2241         
2242         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2243         if (len < 0)
2244           {
2245             _dbus_verbose ("invalid array length (<0)\n");
2246             return FALSE;
2247           }
2248
2249         if (len > _dbus_string_get_length (str) - pos)
2250           {
2251             _dbus_verbose ("array length outside length of the message\n");
2252             return FALSE;
2253           }
2254         
2255         end = pos + len;
2256
2257         if (len > 0 && !validate_array_data (str, byte_order, depth + 1,
2258                                              array_type, array_type_pos,
2259                                              pos, &pos, end))
2260           {
2261             _dbus_verbose ("invalid array data\n");
2262             return FALSE;
2263           }
2264
2265         if (pos < end)
2266           {
2267             /* This should not be able to happen, as long as validate_arg moves forward;
2268              * but the check is here just to be paranoid.
2269              */
2270             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2271                            len, end - pos);
2272             return FALSE;
2273           }
2274         
2275         if (pos > end)
2276           {
2277             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2278             return FALSE;
2279           }
2280
2281         *end_pos = pos;
2282       }
2283       break;
2284
2285     case DBUS_TYPE_DICT:
2286       {
2287         int dict_type;
2288         int len;
2289         int end;
2290         
2291         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2292         if (len < 0)
2293           return FALSE;
2294
2295         if (len > _dbus_string_get_length (str) - pos)
2296           {
2297             _dbus_verbose ("dict length outside length of the message\n");
2298             return FALSE;
2299           }
2300         
2301         end = pos + len;
2302         
2303         while (pos < end)
2304           {
2305             /* Validate name */
2306             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2307                                              DBUS_TYPE_STRING, -1, pos, &pos))
2308               return FALSE;
2309             
2310             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2311               {
2312                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2313                 return FALSE;
2314               }
2315             
2316             /* Validate element */
2317             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2318                                              dict_type, -1, pos, &pos))
2319               {
2320                 _dbus_verbose ("dict arg invalid at offset %d\n", pos);
2321                 return FALSE;
2322               }
2323           }
2324         
2325         if (pos > end)
2326           {
2327             _dbus_verbose ("dict contents exceed stated dict length\n");
2328             return FALSE;
2329           }
2330         
2331         *end_pos = pos;
2332       }
2333       break;
2334       
2335     default:
2336       _dbus_verbose ("Unknown message arg type %d\n", type);
2337       return FALSE;
2338     }
2339
2340   if (*end_pos > _dbus_string_get_length (str))
2341     return FALSE;
2342   
2343   return TRUE;
2344 }
2345
2346 /**
2347  * Return #TRUE if the typecode is a valid typecode
2348  *
2349  * @returns #TRUE if valid
2350  */
2351 dbus_bool_t
2352 _dbus_type_is_valid (int typecode)
2353 {
2354   switch (typecode)
2355     {
2356     case DBUS_TYPE_NIL:
2357     case DBUS_TYPE_BYTE:
2358     case DBUS_TYPE_BOOLEAN:
2359     case DBUS_TYPE_INT32:
2360     case DBUS_TYPE_UINT32:
2361     case DBUS_TYPE_INT64:
2362     case DBUS_TYPE_UINT64:
2363     case DBUS_TYPE_DOUBLE:
2364     case DBUS_TYPE_STRING:
2365     case DBUS_TYPE_CUSTOM:
2366     case DBUS_TYPE_ARRAY:
2367     case DBUS_TYPE_DICT:
2368     case DBUS_TYPE_OBJECT_PATH:
2369       return TRUE;
2370       
2371     default:
2372       return FALSE;
2373     }
2374 }
2375
2376 /**
2377  * If in verbose mode, print a block of binary data.
2378  *
2379  * @todo right now it prints even if not in verbose mode
2380  * 
2381  * @param data the data
2382  * @param len the length of the data
2383  */
2384 void
2385 _dbus_verbose_bytes (const unsigned char *data,
2386                      int                  len)
2387 {
2388   int i;
2389   const unsigned char *aligned;
2390
2391   _dbus_assert (len >= 0);
2392   
2393   /* Print blanks on first row if appropriate */
2394   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2395   if (aligned > data)
2396     aligned -= 4;
2397   _dbus_assert (aligned <= data);
2398
2399   if (aligned != data)
2400     {
2401       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2402       while (aligned != data)
2403         {
2404           _dbus_verbose ("    ");
2405           ++aligned;
2406         }
2407     }
2408
2409   /* now print the bytes */
2410   i = 0;
2411   while (i < len)
2412     {
2413       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2414         {
2415           _dbus_verbose ("%4d\t%p: ",
2416                    i, &data[i]);
2417         }
2418       
2419       if (data[i] >= 32 &&
2420           data[i] <= 126)
2421         _dbus_verbose (" '%c' ", data[i]);
2422       else
2423         _dbus_verbose ("0x%s%x ",
2424                  data[i] <= 0xf ? "0" : "", data[i]);
2425
2426       ++i;
2427
2428       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2429         {
2430           if (i > 3)
2431             _dbus_verbose ("BE: %d LE: %d",
2432                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2433                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2434
2435           if (i > 7 && 
2436               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2437             {
2438               _dbus_verbose (" dbl: %g",
2439                              *(double*)&data[i-8]);
2440             }
2441           
2442           _dbus_verbose ("\n");
2443         }
2444     }
2445
2446   _dbus_verbose ("\n");
2447 }
2448
2449 /**
2450  * Dump the given part of the string to verbose log.
2451  *
2452  * @param str the string
2453  * @param start the start of range to dump
2454  * @param len length of range
2455  */
2456 void
2457 _dbus_verbose_bytes_of_string (const DBusString    *str,
2458                                int                  start,
2459                                int                  len)
2460 {
2461   const char *d;
2462   int real_len;
2463
2464   real_len = _dbus_string_get_length (str);
2465
2466   _dbus_assert (start >= 0);
2467   
2468   if (start > real_len)
2469     {
2470       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2471                      start, len, real_len);
2472       return;
2473     }
2474
2475   if ((start + len) > real_len)
2476     {
2477       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2478                      start, len, real_len);
2479       len = real_len - start;
2480     }
2481   
2482   d = _dbus_string_get_const_data_len (str, start, len);
2483
2484   _dbus_verbose_bytes (d, len);
2485 }
2486
2487 /**
2488  * Marshals a basic type
2489  *
2490  * @param str string to marshal to
2491  * @param type type of value
2492  * @param value pointer to value
2493  * @param byte_order byte order
2494  * @returns #TRUE on success
2495  **/
2496 dbus_bool_t
2497 _dbus_marshal_basic_type (DBusString *str,
2498                           char        type,
2499                           void       *value,
2500                           int         byte_order)
2501 {
2502   dbus_bool_t retval;
2503
2504   switch (type)
2505     {
2506     case DBUS_TYPE_BYTE:
2507     case DBUS_TYPE_BOOLEAN:
2508       retval = _dbus_string_append_byte (str, *(unsigned char *)value);
2509       break;
2510     case DBUS_TYPE_INT32:
2511     case DBUS_TYPE_UINT32:
2512       return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
2513       break;
2514 #ifdef DBUS_HAVE_INT64
2515     case DBUS_TYPE_INT64:
2516     case DBUS_TYPE_UINT64: 
2517       retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
2518       break;
2519 #endif /* DBUS_HAVE_INT64 */
2520     case DBUS_TYPE_DOUBLE:
2521       retval = _dbus_marshal_double (str, byte_order, *(double *)value);
2522       break;
2523     default:
2524       _dbus_assert_not_reached ("not a basic type");
2525       retval = FALSE;
2526       break;
2527     }
2528   return retval;
2529 }
2530
2531 /**
2532  * Marshals a basic type array
2533  *
2534  * @param str string to marshal to
2535  * @param element_type type of array elements
2536  * @param value pointer to value
2537  * @param len length of value data in elements
2538  * @param byte_order byte order
2539  * @returns #TRUE on success
2540  **/
2541 dbus_bool_t
2542 _dbus_marshal_basic_type_array (DBusString *str,
2543                                 char        element_type,
2544                                 const void *value,
2545                                 int         len,
2546                                 int         byte_order)
2547 {
2548   switch (element_type)
2549     {
2550     case DBUS_TYPE_BOOLEAN:
2551       /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
2552        * should we here too ? */
2553     case DBUS_TYPE_BYTE:
2554       return _dbus_marshal_byte_array (str, byte_order, value, len);
2555       break;
2556     case DBUS_TYPE_INT32:
2557     case DBUS_TYPE_UINT32:
2558       return marshal_4_octets_array (str, byte_order, value, len);
2559       break;
2560 #ifdef DBUS_HAVE_INT64
2561     case DBUS_TYPE_INT64:
2562     case DBUS_TYPE_UINT64: 
2563 #endif /* DBUS_HAVE_INT64 */
2564     case DBUS_TYPE_DOUBLE:
2565       return marshal_8_octets_array (str, byte_order, value, len);
2566       break;
2567     default:
2568       _dbus_assert_not_reached ("non basic type in array");
2569       break;
2570     }
2571   return FALSE;
2572 }
2573
2574 /** @} */
2575
2576 #ifdef DBUS_BUILD_TESTS
2577 #include "dbus-test.h"
2578 #include <stdio.h>
2579
2580 dbus_bool_t
2581 _dbus_marshal_test (void)
2582 {
2583   DBusString str;
2584   char *tmp1, *tmp2;
2585   int pos = 0, len;
2586   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2587 #ifdef DBUS_HAVE_INT64
2588   dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff), 
2589                              DBUS_INT64_CONSTANT (0x456ffffffff), 
2590                              DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
2591 #endif
2592   char *s;
2593   DBusString t;
2594   
2595   if (!_dbus_string_init (&str))
2596     _dbus_assert_not_reached ("failed to init string");
2597
2598   /* Marshal doubles */
2599   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2600     _dbus_assert_not_reached ("could not marshal double value");
2601   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2602     _dbus_assert_not_reached ("demarshal failed");
2603
2604   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2605     _dbus_assert_not_reached ("could not marshal double value");
2606   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2607     _dbus_assert_not_reached ("demarshal failed");
2608   
2609   /* Marshal signed integers */
2610   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2611     _dbus_assert_not_reached ("could not marshal signed integer value");
2612   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2613     _dbus_assert_not_reached ("demarshal failed");
2614
2615   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2616     _dbus_assert_not_reached ("could not marshal signed integer value");
2617   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2618     _dbus_assert_not_reached ("demarshal failed");
2619   
2620   /* Marshal unsigned integers */
2621   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2622     _dbus_assert_not_reached ("could not marshal signed integer value");
2623   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2624     _dbus_assert_not_reached ("demarshal failed");
2625   
2626   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2627     _dbus_assert_not_reached ("could not marshal signed integer value");
2628   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2629     _dbus_assert_not_reached ("demarshal failed");
2630
2631 #ifdef DBUS_HAVE_INT64
2632   /* Marshal signed integers */
2633   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2634     _dbus_assert_not_reached ("could not marshal signed integer value");
2635   if (_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2636     _dbus_assert_not_reached ("demarshal failed");
2637
2638   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2639     _dbus_assert_not_reached ("could not marshal signed integer value");
2640   if (_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) != DBUS_INT64_CONSTANT (-0x123456789abc7))
2641     _dbus_assert_not_reached ("demarshal failed");
2642   
2643   /* Marshal unsigned integers */
2644   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2645     _dbus_assert_not_reached ("could not marshal signed integer value");
2646   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2647     _dbus_assert_not_reached ("demarshal failed");
2648   
2649   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2650     _dbus_assert_not_reached ("could not marshal signed integer value");
2651   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2652     _dbus_assert_not_reached ("demarshal failed");
2653 #endif /* DBUS_HAVE_INT64 */
2654   
2655   /* Marshal strings */
2656   tmp1 = "This is the dbus test string";
2657   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2658     _dbus_assert_not_reached ("could not marshal string");
2659   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2660   if (!strcmp (tmp1, tmp2) == 0)
2661     _dbus_assert_not_reached ("demarshal failed");
2662   dbus_free (tmp2);
2663
2664   tmp1 = "This is the dbus test string";
2665   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2666     _dbus_assert_not_reached ("could not marshal string");
2667   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2668   if (!strcmp (tmp1, tmp2) == 0)
2669     _dbus_assert_not_reached ("demarshal failed");
2670   dbus_free (tmp2);
2671
2672   /* Marshal signed integer arrays */
2673   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2674     _dbus_assert_not_reached ("could not marshal integer array");
2675   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2676     _dbus_assert_not_reached ("could not demarshal integer array");
2677
2678   if (len != 3)
2679     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2680   dbus_free (array2);
2681
2682 #ifdef DBUS_HAVE_INT64
2683   /* Marshal 64-bit signed integer arrays */
2684   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2685     _dbus_assert_not_reached ("could not marshal integer array");
2686   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2687     _dbus_assert_not_reached ("could not demarshal integer array");
2688
2689   if (len != 3)
2690     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2691   dbus_free (array4);
2692
2693   /* set/pack 64-bit integers */
2694   _dbus_string_set_length (&str, 8);
2695
2696   /* signed little */
2697   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2698                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2699   
2700   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2701                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2702                                     _dbus_string_get_const_data (&str)));
2703
2704   /* signed big */
2705   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2706                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2707
2708   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2709                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2710                                     _dbus_string_get_const_data (&str)));
2711
2712   /* signed little pack */
2713   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2714                     DBUS_LITTLE_ENDIAN,
2715                     _dbus_string_get_data (&str));
2716   
2717   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2718                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2719                                     _dbus_string_get_const_data (&str)));
2720
2721   /* signed big pack */
2722   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2723                     DBUS_BIG_ENDIAN,
2724                     _dbus_string_get_data (&str));
2725
2726   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2727                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2728                                     _dbus_string_get_const_data (&str)));
2729
2730   /* unsigned little */
2731   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2732                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2733   
2734   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2735                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2736                                      _dbus_string_get_const_data (&str)));
2737
2738   /* unsigned big */
2739   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2740                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2741
2742   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2743                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2744                                      _dbus_string_get_const_data (&str)));
2745
2746   /* unsigned little pack */
2747   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2748                      DBUS_LITTLE_ENDIAN,
2749                      _dbus_string_get_data (&str));
2750   
2751   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2752                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2753                                      _dbus_string_get_const_data (&str)));
2754
2755   /* unsigned big pack */
2756   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2757                      DBUS_BIG_ENDIAN,
2758                      _dbus_string_get_data (&str));
2759
2760   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2761                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2762                                      _dbus_string_get_const_data (&str)));
2763   
2764 #endif
2765
2766   /* set/pack 32-bit integers */
2767   _dbus_string_set_length (&str, 4);
2768
2769   /* signed little */
2770   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2771                            0, -0x123456);
2772   
2773   _dbus_assert (-0x123456 ==
2774                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2775                                     _dbus_string_get_const_data (&str)));
2776
2777   /* signed big */
2778   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2779                            0, -0x123456);
2780
2781   _dbus_assert (-0x123456 ==
2782                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2783                                     _dbus_string_get_const_data (&str)));
2784
2785   /* signed little pack */
2786   _dbus_pack_int32 (-0x123456,
2787                     DBUS_LITTLE_ENDIAN,
2788                     _dbus_string_get_data (&str));
2789   
2790   _dbus_assert (-0x123456 ==
2791                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2792                                     _dbus_string_get_const_data (&str)));
2793
2794   /* signed big pack */
2795   _dbus_pack_int32 (-0x123456,
2796                     DBUS_BIG_ENDIAN,
2797                     _dbus_string_get_data (&str));
2798
2799   _dbus_assert (-0x123456 ==
2800                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2801                                     _dbus_string_get_const_data (&str)));
2802
2803   /* unsigned little */
2804   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2805                             0, 0x123456);
2806   
2807   _dbus_assert (0x123456 ==
2808                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2809                                      _dbus_string_get_const_data (&str)));
2810
2811   /* unsigned big */
2812   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2813                             0, 0x123456);
2814
2815   _dbus_assert (0x123456 ==
2816                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2817                                      _dbus_string_get_const_data (&str)));
2818
2819   /* unsigned little pack */
2820   _dbus_pack_uint32 (0x123456,
2821                      DBUS_LITTLE_ENDIAN,
2822                      _dbus_string_get_data (&str));
2823   
2824   _dbus_assert (0x123456 ==
2825                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2826                                      _dbus_string_get_const_data (&str)));
2827
2828   /* unsigned big pack */
2829   _dbus_pack_uint32 (0x123456,
2830                      DBUS_BIG_ENDIAN,
2831                      _dbus_string_get_data (&str));
2832
2833   _dbus_assert (0x123456 ==
2834                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2835                                      _dbus_string_get_const_data (&str)));
2836
2837
2838   /* Strings */
2839   
2840   _dbus_string_set_length (&str, 0);
2841
2842   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2843                         "Hello world");
2844   
2845   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2846   _dbus_assert (strcmp (s, "Hello world") == 0);
2847   dbus_free (s);
2848
2849   _dbus_string_init_const (&t, "Hello world foo");
2850   
2851   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2852                             &t, _dbus_string_get_length (&t));
2853   
2854   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2855   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2856   dbus_free (s);
2857
2858   _dbus_string_init_const (&t, "Hello");
2859   
2860   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2861                             &t, _dbus_string_get_length (&t));
2862   
2863   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2864   _dbus_assert (strcmp (s, "Hello") == 0);
2865   dbus_free (s);
2866
2867   /* Strings (big endian) */
2868   
2869   _dbus_string_set_length (&str, 0);
2870
2871   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2872                         "Hello world");
2873   
2874   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2875   _dbus_assert (strcmp (s, "Hello world") == 0);
2876   dbus_free (s);
2877
2878   _dbus_string_init_const (&t, "Hello world foo");
2879   
2880   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2881                             &t, _dbus_string_get_length (&t));
2882   
2883   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2884   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2885   dbus_free (s);
2886
2887   _dbus_string_init_const (&t, "Hello");
2888   
2889   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2890                             &t, _dbus_string_get_length (&t));
2891   
2892   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2893   _dbus_assert (strcmp (s, "Hello") == 0);
2894   dbus_free (s);
2895   
2896   _dbus_string_free (&str);
2897       
2898   return TRUE;
2899 }
2900
2901 #endif /* DBUS_BUILD_TESTS */