2003-08-30 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  * @todo For array types that can't be invalid, we should not
1911  * walk the whole array validating it. e.g. just skip all the
1912  * int values in an int array. (maybe this is already done now -hp)
1913  *
1914  * @todo support DBUS_TYPE_OBJECT_PATH
1915  * 
1916  * @param str a string
1917  * @param byte_order the byte order to use
1918  * @param depth current recursion depth, to prevent excessive recursion
1919  * @param type the type of the argument
1920  * @param array_type_pos the position of the current array type, or
1921  *        -1 if not in an array
1922  * @param pos the pos where the arg starts
1923  * @param end_pos pointer where the position right
1924  * after the end position will follow
1925  * @returns #TRUE if the arg is valid.
1926  */
1927 dbus_bool_t
1928 _dbus_marshal_validate_arg (const DBusString *str,
1929                             int               byte_order,
1930                             int               depth,
1931                             int               type,
1932                             int               array_type_pos,
1933                             int               pos,
1934                             int              *end_pos)
1935 {
1936   if (pos > _dbus_string_get_length (str))
1937     {
1938       _dbus_verbose ("Validation went off the end of the message\n");
1939       return FALSE;
1940     }
1941
1942 #define MAX_VALIDATION_DEPTH 32
1943   
1944   if (depth > MAX_VALIDATION_DEPTH)
1945     {
1946       _dbus_verbose ("Maximum recursion depth reached validating message\n");
1947       return FALSE;
1948     }
1949   
1950   switch (type)
1951     {
1952     case DBUS_TYPE_INVALID:
1953       return FALSE;
1954       break;
1955
1956     case DBUS_TYPE_NIL:
1957       *end_pos = pos;
1958       break;
1959
1960     case DBUS_TYPE_BYTE:
1961       if (1 > _dbus_string_get_length (str) - pos)
1962         {
1963           _dbus_verbose ("no room for byte value\n");
1964           return FALSE;
1965         }
1966         
1967       *end_pos = pos + 1;
1968       break;
1969       
1970     case DBUS_TYPE_BOOLEAN:
1971       {
1972         unsigned char c;
1973
1974         if (1 > _dbus_string_get_length (str) - pos)
1975           {
1976             _dbus_verbose ("no room for boolean value\n");
1977             return FALSE;
1978           }
1979         
1980         c = _dbus_string_get_byte (str, pos);
1981
1982         if (!(c == 0 || c == 1))
1983           {
1984             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1985             return FALSE;
1986           }
1987         
1988         *end_pos = pos + 1;
1989       }
1990       break;
1991       
1992     case DBUS_TYPE_INT32:
1993     case DBUS_TYPE_UINT32:
1994       {
1995         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1996         
1997         if (!_dbus_string_validate_nul (str, pos,
1998                                         align_4 - pos))
1999           {
2000             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
2001             return FALSE;
2002           }
2003
2004         *end_pos = align_4 + 4;
2005       }
2006       break;
2007
2008     case DBUS_TYPE_INT64:
2009     case DBUS_TYPE_UINT64:      
2010     case DBUS_TYPE_DOUBLE:
2011       {
2012         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
2013
2014         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
2015         
2016         if (!_dbus_string_validate_nul (str, pos,
2017                                         align_8 - pos))
2018           {
2019             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul\n");
2020             return FALSE;
2021           }
2022
2023         *end_pos = align_8 + 8;
2024       }
2025       break;
2026
2027     case DBUS_TYPE_OBJECT_PATH:
2028     case DBUS_TYPE_STRING:
2029       {
2030         int len;
2031
2032         /* Demarshal the length, which does NOT include
2033          * nul termination
2034          */
2035         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2036         if (len < 0)
2037           return FALSE;
2038
2039         if (!validate_string (str, pos, len, end_pos))
2040           return FALSE;
2041
2042         if (type == DBUS_TYPE_OBJECT_PATH)
2043           {
2044             if (!_dbus_string_validate_path (str, pos, len))
2045               return FALSE;
2046           }
2047       }
2048       break;
2049
2050     case DBUS_TYPE_NAMED:
2051       {
2052         int len;
2053
2054         /* Demarshal the string length, which does NOT include
2055          * nul termination
2056          */
2057         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2058         if (len < 0)
2059           return FALSE;
2060
2061         if (!validate_string (str, pos, len, &pos))
2062           return FALSE;
2063
2064         /* Validate data */
2065         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2066         if (len < 0)
2067           return FALSE;
2068
2069         *end_pos = pos + len;
2070       }
2071       break;
2072       
2073     case DBUS_TYPE_ARRAY:
2074       {
2075         int len;
2076         int end;
2077         int array_type;
2078
2079         if (array_type_pos == -1)
2080           {
2081             array_type_pos = pos;
2082
2083             do
2084               {
2085                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
2086                   {
2087                     _dbus_verbose ("invalid array type\n");
2088                     return FALSE;
2089                   }
2090                 
2091                 /* NIL values take up no space, so you couldn't iterate over an array of them.
2092                  * array of nil seems useless anyway; the useful thing might be array of
2093                  * (nil OR string) but we have no framework for that.
2094                  */
2095                 if (array_type == DBUS_TYPE_NIL)
2096                   {
2097                     _dbus_verbose ("array of NIL is not allowed\n");
2098                     return FALSE;
2099                   }
2100               }
2101             while (array_type == DBUS_TYPE_ARRAY);
2102           }
2103         else
2104           array_type_pos++;
2105
2106         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
2107           {
2108             _dbus_verbose ("invalid array type\n");
2109             return FALSE;
2110           }
2111         
2112         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2113         if (len < 0)
2114           return FALSE;
2115
2116         if (len > _dbus_string_get_length (str) - pos)
2117           {
2118             _dbus_verbose ("array length outside length of the message\n");
2119             return FALSE;
2120           }
2121         
2122         end = pos + len;
2123
2124         if (!validate_array_data (str, byte_order, depth + 1,
2125                                   array_type, array_type_pos,
2126                                   pos, &pos, end))
2127           return FALSE;
2128
2129         if (pos < end)
2130           {
2131             /* This should not be able to happen, as long as validate_arg moves forward;
2132              * but the check is here just to be paranoid.
2133              */
2134             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2135                            len, end - pos);
2136             return FALSE;
2137           }
2138         
2139         if (pos > end)
2140           {
2141             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2142             return FALSE;
2143           }
2144
2145         *end_pos = pos;
2146       }
2147       break;
2148
2149     case DBUS_TYPE_DICT:
2150       {
2151         int dict_type;
2152         int len;
2153         int end;
2154         
2155         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2156         if (len < 0)
2157           return FALSE;
2158
2159         if (len > _dbus_string_get_length (str) - pos)
2160           {
2161             _dbus_verbose ("dict length outside length of the message\n");
2162             return FALSE;
2163           }
2164         
2165         end = pos + len;
2166         
2167         while (pos < end)
2168           {
2169             /* Validate name */
2170             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2171                                              DBUS_TYPE_STRING, -1, pos, &pos))
2172               return FALSE;
2173             
2174             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2175               {
2176                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2177                 return FALSE;
2178               }
2179             
2180             /* Validate element */
2181             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2182                                              dict_type, -1, pos, &pos))
2183               return FALSE;
2184           }
2185         
2186         if (pos > end)
2187           {
2188             _dbus_verbose ("dict contents exceed stated dict length\n");
2189             return FALSE;
2190           }
2191         
2192         *end_pos = pos;
2193       }
2194       break;
2195       
2196     default:
2197       _dbus_verbose ("Unknown message arg type %d\n", type);
2198       return FALSE;
2199     }
2200
2201   if (*end_pos > _dbus_string_get_length (str))
2202     return FALSE;
2203   
2204   return TRUE;
2205 }
2206
2207
2208 /**
2209  * If in verbose mode, print a block of binary data.
2210  *
2211  * @todo right now it prints even if not in verbose mode
2212  * 
2213  * @param data the data
2214  * @param len the length of the data
2215  */
2216 void
2217 _dbus_verbose_bytes (const unsigned char *data,
2218                      int                  len)
2219 {
2220   int i;
2221   const unsigned char *aligned;
2222
2223   _dbus_assert (len >= 0);
2224   
2225   /* Print blanks on first row if appropriate */
2226   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2227   if (aligned > data)
2228     aligned -= 4;
2229   _dbus_assert (aligned <= data);
2230
2231   if (aligned != data)
2232     {
2233       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2234       while (aligned != data)
2235         {
2236           _dbus_verbose ("    ");
2237           ++aligned;
2238         }
2239     }
2240
2241   /* now print the bytes */
2242   i = 0;
2243   while (i < len)
2244     {
2245       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2246         {
2247           _dbus_verbose ("%4d\t%p: ",
2248                    i, &data[i]);
2249         }
2250       
2251       if (data[i] >= 32 &&
2252           data[i] <= 126)
2253         _dbus_verbose (" '%c' ", data[i]);
2254       else
2255         _dbus_verbose ("0x%s%x ",
2256                  data[i] <= 0xf ? "0" : "", data[i]);
2257
2258       ++i;
2259
2260       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2261         {
2262           if (i > 3)
2263             _dbus_verbose ("BE: %d LE: %d",
2264                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2265                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2266
2267           if (i > 7 && 
2268               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2269             {
2270               _dbus_verbose (" dbl: %g",
2271                              *(double*)&data[i-8]);
2272             }
2273           
2274           _dbus_verbose ("\n");
2275         }
2276     }
2277
2278   _dbus_verbose ("\n");
2279 }
2280
2281 /**
2282  * Dump the given part of the string to verbose log.
2283  *
2284  * @param str the string
2285  * @param start the start of range to dump
2286  * @param len length of range
2287  */
2288 void
2289 _dbus_verbose_bytes_of_string (const DBusString    *str,
2290                                int                  start,
2291                                int                  len)
2292 {
2293   const char *d;
2294   int real_len;
2295
2296   real_len = _dbus_string_get_length (str);
2297
2298   _dbus_assert (start >= 0);
2299   
2300   if (start > real_len)
2301     {
2302       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2303                      start, len, real_len);
2304       return;
2305     }
2306
2307   if ((start + len) > real_len)
2308     {
2309       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2310                      start, len, real_len);
2311       len = real_len - start;
2312     }
2313   
2314   d = _dbus_string_get_const_data_len (str, start, len);
2315
2316   _dbus_verbose_bytes (d, len);
2317 }
2318
2319 /** @} */
2320
2321 #ifdef DBUS_BUILD_TESTS
2322 #include "dbus-test.h"
2323 #include <stdio.h>
2324
2325 dbus_bool_t
2326 _dbus_marshal_test (void)
2327 {
2328   DBusString str;
2329   char *tmp1, *tmp2;
2330   int pos = 0, len;
2331   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2332 #ifdef DBUS_HAVE_INT64
2333   dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
2334 #endif
2335   char *s;
2336   DBusString t;
2337   
2338   if (!_dbus_string_init (&str))
2339     _dbus_assert_not_reached ("failed to init string");
2340
2341   /* Marshal doubles */
2342   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2343     _dbus_assert_not_reached ("could not marshal double value");
2344   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2345     _dbus_assert_not_reached ("demarshal failed");
2346
2347   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2348     _dbus_assert_not_reached ("could not marshal double value");
2349   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2350     _dbus_assert_not_reached ("demarshal failed");
2351   
2352   /* Marshal signed integers */
2353   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2354     _dbus_assert_not_reached ("could not marshal signed integer value");
2355   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2356     _dbus_assert_not_reached ("demarshal failed");
2357
2358   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2359     _dbus_assert_not_reached ("could not marshal signed integer value");
2360   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2361     _dbus_assert_not_reached ("demarshal failed");
2362   
2363   /* Marshal unsigned integers */
2364   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2365     _dbus_assert_not_reached ("could not marshal signed integer value");
2366   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2367     _dbus_assert_not_reached ("demarshal failed");
2368   
2369   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2370     _dbus_assert_not_reached ("could not marshal signed integer value");
2371   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2372     _dbus_assert_not_reached ("demarshal failed");
2373
2374 #ifdef DBUS_HAVE_INT64
2375   /* Marshal signed integers */
2376   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2377     _dbus_assert_not_reached ("could not marshal signed integer value");
2378   if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2379     _dbus_assert_not_reached ("demarshal failed");
2380
2381   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2382     _dbus_assert_not_reached ("could not marshal signed integer value");
2383   if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2384     _dbus_assert_not_reached ("demarshal failed");
2385   
2386   /* Marshal unsigned integers */
2387   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2388     _dbus_assert_not_reached ("could not marshal signed integer value");
2389   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2390     _dbus_assert_not_reached ("demarshal failed");
2391   
2392   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2393     _dbus_assert_not_reached ("could not marshal signed integer value");
2394   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2395     _dbus_assert_not_reached ("demarshal failed");
2396 #endif /* DBUS_HAVE_INT64 */
2397   
2398   /* Marshal strings */
2399   tmp1 = "This is the dbus test string";
2400   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2401     _dbus_assert_not_reached ("could not marshal string");
2402   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2403   if (!strcmp (tmp1, tmp2) == 0)
2404     _dbus_assert_not_reached ("demarshal failed");
2405   dbus_free (tmp2);
2406
2407   tmp1 = "This is the dbus test string";
2408   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2409     _dbus_assert_not_reached ("could not marshal string");
2410   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2411   if (!strcmp (tmp1, tmp2) == 0)
2412     _dbus_assert_not_reached ("demarshal failed");
2413   dbus_free (tmp2);
2414
2415   /* Marshal signed integer arrays */
2416   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2417     _dbus_assert_not_reached ("could not marshal integer array");
2418   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2419     _dbus_assert_not_reached ("could not demarshal integer array");
2420
2421   if (len != 3)
2422     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2423   dbus_free (array2);
2424
2425 #ifdef DBUS_HAVE_INT64
2426   /* Marshal 64-bit signed integer arrays */
2427   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2428     _dbus_assert_not_reached ("could not marshal integer array");
2429   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2430     _dbus_assert_not_reached ("could not demarshal integer array");
2431
2432   if (len != 3)
2433     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2434   dbus_free (array4);
2435
2436   /* set/pack 64-bit integers */
2437   _dbus_string_set_length (&str, 8);
2438
2439   /* signed little */
2440   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2441                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2442   
2443   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2444                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2445                                     _dbus_string_get_const_data (&str)));
2446
2447   /* signed big */
2448   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2449                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2450
2451   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2452                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2453                                     _dbus_string_get_const_data (&str)));
2454
2455   /* signed little pack */
2456   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2457                     DBUS_LITTLE_ENDIAN,
2458                     _dbus_string_get_data (&str));
2459   
2460   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2461                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2462                                     _dbus_string_get_const_data (&str)));
2463
2464   /* signed big pack */
2465   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2466                     DBUS_BIG_ENDIAN,
2467                     _dbus_string_get_data (&str));
2468
2469   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2470                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2471                                     _dbus_string_get_const_data (&str)));
2472
2473   /* unsigned little */
2474   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2475                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2476   
2477   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2478                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2479                                      _dbus_string_get_const_data (&str)));
2480
2481   /* unsigned big */
2482   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2483                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2484
2485   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2486                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2487                                      _dbus_string_get_const_data (&str)));
2488
2489   /* unsigned little pack */
2490   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2491                      DBUS_LITTLE_ENDIAN,
2492                      _dbus_string_get_data (&str));
2493   
2494   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2495                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2496                                      _dbus_string_get_const_data (&str)));
2497
2498   /* unsigned big pack */
2499   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2500                      DBUS_BIG_ENDIAN,
2501                      _dbus_string_get_data (&str));
2502
2503   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2504                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2505                                      _dbus_string_get_const_data (&str)));
2506   
2507 #endif
2508
2509   /* set/pack 32-bit integers */
2510   _dbus_string_set_length (&str, 4);
2511
2512   /* signed little */
2513   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2514                            0, -0x123456);
2515   
2516   _dbus_assert (-0x123456 ==
2517                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2518                                     _dbus_string_get_const_data (&str)));
2519
2520   /* signed big */
2521   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2522                            0, -0x123456);
2523
2524   _dbus_assert (-0x123456 ==
2525                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2526                                     _dbus_string_get_const_data (&str)));
2527
2528   /* signed little pack */
2529   _dbus_pack_int32 (-0x123456,
2530                     DBUS_LITTLE_ENDIAN,
2531                     _dbus_string_get_data (&str));
2532   
2533   _dbus_assert (-0x123456 ==
2534                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2535                                     _dbus_string_get_const_data (&str)));
2536
2537   /* signed big pack */
2538   _dbus_pack_int32 (-0x123456,
2539                     DBUS_BIG_ENDIAN,
2540                     _dbus_string_get_data (&str));
2541
2542   _dbus_assert (-0x123456 ==
2543                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2544                                     _dbus_string_get_const_data (&str)));
2545
2546   /* unsigned little */
2547   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2548                             0, 0x123456);
2549   
2550   _dbus_assert (0x123456 ==
2551                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2552                                      _dbus_string_get_const_data (&str)));
2553
2554   /* unsigned big */
2555   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2556                             0, 0x123456);
2557
2558   _dbus_assert (0x123456 ==
2559                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2560                                      _dbus_string_get_const_data (&str)));
2561
2562   /* unsigned little pack */
2563   _dbus_pack_uint32 (0x123456,
2564                      DBUS_LITTLE_ENDIAN,
2565                      _dbus_string_get_data (&str));
2566   
2567   _dbus_assert (0x123456 ==
2568                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2569                                      _dbus_string_get_const_data (&str)));
2570
2571   /* unsigned big pack */
2572   _dbus_pack_uint32 (0x123456,
2573                      DBUS_BIG_ENDIAN,
2574                      _dbus_string_get_data (&str));
2575
2576   _dbus_assert (0x123456 ==
2577                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2578                                      _dbus_string_get_const_data (&str)));
2579
2580
2581   /* Strings */
2582   
2583   _dbus_string_set_length (&str, 0);
2584
2585   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2586                         "Hello world");
2587   
2588   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2589   _dbus_assert (strcmp (s, "Hello world") == 0);
2590   dbus_free (s);
2591
2592   _dbus_string_init_const (&t, "Hello world foo");
2593   
2594   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2595                             &t, _dbus_string_get_length (&t));
2596   
2597   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2598   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2599   dbus_free (s);
2600
2601   _dbus_string_init_const (&t, "Hello");
2602   
2603   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2604                             &t, _dbus_string_get_length (&t));
2605   
2606   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2607   _dbus_assert (strcmp (s, "Hello") == 0);
2608   dbus_free (s);
2609
2610   /* Strings (big endian) */
2611   
2612   _dbus_string_set_length (&str, 0);
2613
2614   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2615                         "Hello world");
2616   
2617   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2618   _dbus_assert (strcmp (s, "Hello world") == 0);
2619   dbus_free (s);
2620
2621   _dbus_string_init_const (&t, "Hello world foo");
2622   
2623   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2624                             &t, _dbus_string_get_length (&t));
2625   
2626   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2627   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2628   dbus_free (s);
2629
2630   _dbus_string_init_const (&t, "Hello");
2631   
2632   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2633                             &t, _dbus_string_get_length (&t));
2634   
2635   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2636   _dbus_assert (strcmp (s, "Hello") == 0);
2637   dbus_free (s);
2638   
2639   _dbus_string_free (&str);
2640       
2641   return TRUE;
2642 }
2643
2644 #endif /* DBUS_BUILD_TESTS */