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