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