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