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