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