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