2003-08-28 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  * @todo implement this function
876  * 
877  * @param str the string to append the marshalled value to
878  * @param byte_order the byte order to use
879  * @param path the path
880  * @param path_len length of the path
881  * @returns #TRUE on success
882  */
883 dbus_bool_t
884 _dbus_marshal_object_path (DBusString            *str,
885                            int                    byte_order,
886                            const char           **path,
887                            int                    path_len)
888 {
889   return TRUE;
890 }
891
892 static dbus_uint32_t
893 demarshal_4_octets (const DBusString *str,
894                     int               byte_order,
895                     int               pos,
896                     int              *new_pos)
897 {
898   const DBusRealString *real = (const DBusRealString*) str;
899   
900   pos = _DBUS_ALIGN_VALUE (pos, 4);
901   
902   if (new_pos)
903     *new_pos = pos + 4;
904
905   return unpack_4_octets (byte_order, real->str + pos);
906 }
907
908 static DBusOctets8
909 demarshal_8_octets (const DBusString *str,
910                     int               byte_order,
911                     int               pos,
912                     int              *new_pos)
913 {
914   const DBusRealString *real = (const DBusRealString*) str;
915   
916   pos = _DBUS_ALIGN_VALUE (pos, 8);
917   
918   if (new_pos)
919     *new_pos = pos + 8;
920
921   return unpack_8_octets (byte_order, real->str + pos);
922 }
923
924 /**
925  * Demarshals a double.
926  *
927  * @param str the string containing the data
928  * @param byte_order the byte order
929  * @param pos the position in the string
930  * @param new_pos the new position of the string
931  * @returns the demarshaled double.
932  */
933 double
934 _dbus_demarshal_double (const DBusString  *str,
935                         int                byte_order,
936                         int                pos,
937                         int               *new_pos)
938 {
939   DBusOctets8 r;
940
941   r = demarshal_8_octets (str, byte_order, pos, new_pos);
942
943   return r.d;
944 }
945
946 /**
947  * Demarshals a 32 bit signed integer.
948  *
949  * @param str the string containing the data
950  * @param byte_order the byte order
951  * @param pos the position in the string
952  * @param new_pos the new position of the string
953  * @returns the demarshaled integer.
954  */
955 dbus_int32_t
956 _dbus_demarshal_int32  (const DBusString *str,
957                         int               byte_order,
958                         int               pos,
959                         int              *new_pos)
960 {
961   return (dbus_int32_t) demarshal_4_octets (str, byte_order, pos, new_pos);
962 }
963
964 /**
965  * Demarshals a 32 bit unsigned integer.
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 integer.
972  */
973 dbus_uint32_t
974 _dbus_demarshal_uint32  (const DBusString *str,
975                          int         byte_order,
976                          int         pos,
977                          int        *new_pos)
978 {
979   return demarshal_4_octets (str, byte_order, pos, new_pos);
980 }
981
982 #ifdef DBUS_HAVE_INT64
983
984 /**
985  * Demarshals a 64 bit signed integer.
986  *
987  * @param str the string containing the data
988  * @param byte_order the byte order
989  * @param pos the position in the string
990  * @param new_pos the new position of the string
991  * @returns the demarshaled integer.
992  */
993 dbus_int64_t
994 _dbus_demarshal_int64  (const DBusString *str,
995                         int               byte_order,
996                         int               pos,
997                         int              *new_pos)
998 {
999   DBusOctets8 r;
1000
1001   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1002
1003   return r.s;
1004 }
1005
1006 /**
1007  * Demarshals a 64 bit unsigned integer.
1008  *
1009  * @param str the string containing the data
1010  * @param byte_order the byte order
1011  * @param pos the position in the string
1012  * @param new_pos the new position of the string
1013  * @returns the demarshaled integer.
1014  */
1015 dbus_uint64_t
1016 _dbus_demarshal_uint64  (const DBusString *str,
1017                          int         byte_order,
1018                          int         pos,
1019                          int        *new_pos)
1020 {
1021   DBusOctets8 r;
1022
1023   r = demarshal_8_octets (str, byte_order, pos, new_pos);
1024
1025   return r.u;
1026 }
1027
1028 #endif /* DBUS_HAVE_INT64 */
1029
1030 /**
1031  * Demarshals an UTF-8 string.
1032  *
1033  * @todo Should we check the string to make sure
1034  * that it's  valid UTF-8, and maybe "fix" the string
1035  * if it's broken?
1036  *
1037  * @todo Should probably demarshal to a DBusString,
1038  * having memcpy() in here is Evil(tm).
1039  *
1040  * @param str the string containing the data
1041  * @param byte_order the byte order
1042  * @param pos the position in the string
1043  * @param new_pos the new position of the string
1044  * @returns the demarshaled string.
1045  */
1046 char *
1047 _dbus_demarshal_string (const DBusString *str,
1048                         int               byte_order,
1049                         int               pos,
1050                         int              *new_pos)
1051 {
1052   int len;
1053   char *retval;
1054   const char *data;
1055   
1056   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1057
1058   retval = dbus_malloc (len + 1);
1059
1060   if (!retval)
1061     return NULL;
1062
1063   data = _dbus_string_get_const_data_len (str, pos, len + 1);
1064
1065   if (!data)
1066     return NULL;
1067
1068   memcpy (retval, data, len + 1);
1069
1070   if (new_pos)
1071     *new_pos = pos + len + 1;
1072   
1073   return retval;
1074 }
1075
1076 /**
1077  * Demarshals a byte array.
1078  *
1079  * @todo Should probably demarshal to a DBusString,
1080  * having memcpy() in here is Evil(tm).
1081  *
1082  * @param str the string containing the data
1083  * @param byte_order the byte order
1084  * @param pos the position in the string
1085  * @param new_pos the new position of the string
1086  * @param array the array
1087  * @param array_len length of the demarshaled data
1088  
1089  * @returns #TRUE on success
1090  */
1091 dbus_bool_t
1092 _dbus_demarshal_byte_array (const DBusString  *str,
1093                             int                byte_order,
1094                             int                pos,
1095                             int               *new_pos,
1096                             unsigned char    **array,
1097                             int               *array_len)
1098 {
1099   int len;
1100   unsigned char *retval;
1101   const char *data;
1102
1103   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1104
1105   if (len == 0)
1106     {
1107       *array_len = len;
1108       *array = NULL;
1109
1110       if (new_pos)
1111         *new_pos = pos;
1112       
1113       return TRUE;
1114     }
1115   
1116   retval = dbus_malloc (len);
1117
1118   if (!retval)
1119     return FALSE;
1120
1121   data = _dbus_string_get_const_data_len (str, pos, len);
1122
1123   if (!data)
1124     {
1125       dbus_free (retval);
1126       return FALSE;
1127     }
1128
1129   memcpy (retval, data, len);
1130
1131   if (new_pos)
1132     *new_pos = pos + len;
1133
1134   *array = retval;
1135   *array_len = len;
1136   
1137   return TRUE;
1138 }
1139
1140 static dbus_bool_t
1141 demarshal_4_octets_array (const DBusString  *str,
1142                           int                byte_order,
1143                           int                pos,
1144                           int               *new_pos,
1145                           dbus_uint32_t    **array,
1146                           int               *array_len)
1147 {
1148   int len, i;
1149   dbus_uint32_t *retval;
1150   int byte_len;
1151   
1152   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1153   len = byte_len / 4;
1154
1155   if (len == 0)
1156     {
1157       *array_len = 0;
1158       *array = NULL;
1159
1160       if (new_pos)
1161         *new_pos = pos;
1162       
1163       return TRUE;
1164     }
1165
1166   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1167                                    pos, byte_len))
1168     return FALSE;
1169   
1170   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1171     {
1172       for (i = 0; i < len; i++)
1173         retval[i] = DBUS_UINT32_SWAP_LE_BE (retval[i]);
1174     }
1175
1176   if (new_pos)
1177     *new_pos = pos + byte_len;
1178
1179   *array_len = len;
1180   *array = retval;
1181   
1182   return TRUE;  
1183 }
1184
1185 static dbus_bool_t
1186 demarshal_8_octets_array (const DBusString  *str,
1187                           int                byte_order,
1188                           int                pos,
1189                           int               *new_pos,
1190                           DBusOctets8      **array,
1191                           int               *array_len)
1192 {
1193   int len, i;
1194   DBusOctets8 *retval;
1195   int byte_len;
1196   
1197   byte_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1198   len = byte_len / 8;
1199
1200   if (len == 0)
1201     {
1202       *array_len = 0;
1203       *array = NULL;
1204
1205       if (new_pos)
1206         *new_pos = pos;
1207       
1208       return TRUE;
1209     }
1210
1211   if (!_dbus_string_copy_data_len (str, (char**) &retval,
1212                                    pos, byte_len))
1213     return FALSE;
1214   
1215   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
1216     {
1217       for (i = 0; i < len; i++)
1218         {
1219 #ifdef DBUS_HAVE_INT64
1220           retval[i].u = DBUS_UINT64_SWAP_LE_BE (retval[i].u);
1221 #else
1222           swap_bytes ((unsigned char *) &retval[i], 8);
1223 #endif
1224         }
1225     }
1226
1227   if (new_pos)
1228     *new_pos = pos + byte_len;
1229
1230   *array_len = len;
1231   *array = retval;
1232   
1233   return TRUE;  
1234 }
1235
1236 /**
1237  * Demarshals a 32 bit signed integer array.
1238  *
1239  * @param str the string containing the data
1240  * @param byte_order the byte order
1241  * @param pos the position in the string
1242  * @param new_pos the new position of the string
1243  * @param array the array
1244  * @param array_len length of the demarshaled data
1245  * @returns #TRUE on success
1246  */
1247 dbus_bool_t
1248 _dbus_demarshal_int32_array (const DBusString  *str,
1249                              int                byte_order,
1250                              int                pos,
1251                              int               *new_pos,
1252                              dbus_int32_t     **array,
1253                              int               *array_len)
1254 {
1255   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1256                                    (dbus_uint32_t**) array, array_len);
1257 }
1258
1259 /**
1260  * Demarshals a 32 bit unsigned integer array.
1261  *
1262  * @param str the string containing the data
1263  * @param byte_order the byte order
1264  * @param pos the position in the string
1265  * @param new_pos the new position of the string
1266  * @param array the array
1267  * @param array_len length of the demarshaled data
1268  * @returns #TRUE on success
1269  */
1270 dbus_bool_t
1271 _dbus_demarshal_uint32_array (const DBusString  *str,
1272                               int                byte_order,
1273                               int                pos,
1274                               int               *new_pos,
1275                               dbus_uint32_t    **array,
1276                               int               *array_len)
1277 {
1278   return demarshal_4_octets_array (str, byte_order, pos, new_pos,
1279                                    array, array_len);
1280 }
1281
1282 #ifdef DBUS_HAVE_INT64
1283
1284 /**
1285  * Demarshals a 64 bit signed integer array.
1286  *
1287  * @param str the string containing the data
1288  * @param byte_order the byte order
1289  * @param pos the position in the string
1290  * @param new_pos the new position of the string
1291  * @param array the array
1292  * @param array_len length of the demarshaled data
1293  * @returns #TRUE on success
1294  */
1295 dbus_bool_t
1296 _dbus_demarshal_int64_array (const DBusString  *str,
1297                              int                byte_order,
1298                              int                pos,
1299                              int               *new_pos,
1300                              dbus_int64_t     **array,
1301                              int               *array_len)
1302 {
1303   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1304                                    (DBusOctets8**) array, array_len);
1305 }
1306
1307 /**
1308  * Demarshals a 64 bit unsigned integer array.
1309  *
1310  * @param str the string containing the data
1311  * @param byte_order the byte order
1312  * @param pos the position in the string
1313  * @param new_pos the new position of the string
1314  * @param array the array
1315  * @param array_len length of the demarshaled data
1316  * @returns #TRUE on success
1317  */
1318 dbus_bool_t
1319 _dbus_demarshal_uint64_array (const DBusString  *str,
1320                               int                byte_order,
1321                               int                pos,
1322                               int               *new_pos,
1323                               dbus_uint64_t    **array,
1324                               int               *array_len)
1325 {
1326   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1327                                    (DBusOctets8**) array, array_len);
1328 }
1329
1330 #endif /* DBUS_HAVE_INT64 */
1331
1332 /**
1333  * Demarshals a double array.
1334  *
1335  * @param str the string containing the data
1336  * @param byte_order the byte order
1337  * @param pos the position in the string
1338  * @param new_pos the new position of the string
1339  * @param array the array
1340  * @param array_len length of the demarshaled data
1341  * @returns #TRUE on success
1342  */
1343 dbus_bool_t
1344 _dbus_demarshal_double_array (const DBusString  *str,
1345                               int                byte_order,
1346                               int                pos,
1347                               int               *new_pos,
1348                               double           **array,
1349                               int               *array_len)
1350 {
1351   return demarshal_8_octets_array (str, byte_order, pos, new_pos,
1352                                    (DBusOctets8**) array, array_len);
1353 }
1354
1355 /**
1356  * Demarshals a string array.
1357  *
1358  * @param str the string containing the data
1359  * @param byte_order the byte order
1360  * @param pos the position in the string
1361  * @param new_pos the new position of the string
1362  * @param array the array
1363  * @param array_len length of the demarshaled data
1364  * @returns #TRUE on success
1365  */
1366 dbus_bool_t
1367 _dbus_demarshal_string_array (const DBusString   *str,
1368                               int                 byte_order,
1369                               int                 pos,
1370                               int                *new_pos,
1371                               char             ***array,
1372                               int                *array_len)
1373 {
1374   int bytes_len, i;
1375   int len, allocated;
1376   int end_pos;
1377   char **retval;
1378   
1379   bytes_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1380   
1381   if (bytes_len == 0)
1382     {
1383       *array_len = 0;
1384       *array = NULL;
1385
1386       if (new_pos)
1387         *new_pos = pos;
1388       
1389       return TRUE;
1390     }
1391
1392   len = 0;
1393   allocated = 4;
1394   end_pos = pos + bytes_len;
1395   
1396   retval = dbus_new (char *, allocated);
1397
1398   if (!retval)
1399     return FALSE;
1400
1401   while (pos < end_pos)
1402     {
1403       retval[len] = _dbus_demarshal_string (str, byte_order, pos, &pos);
1404       
1405       if (retval[len] == NULL)
1406         goto error;
1407       
1408       len += 1;
1409
1410       if (len >= allocated - 1) /* -1 for NULL termination */
1411         {
1412           char **newp;
1413           newp = dbus_realloc (retval,
1414                                sizeof (char*) * allocated * 2);
1415           if (newp == NULL)
1416             goto error;
1417
1418           allocated *= 2;
1419           retval = newp;
1420         }
1421     }
1422       
1423   retval[len] = NULL;
1424
1425   if (new_pos)
1426     *new_pos = pos;
1427   
1428   *array = retval;
1429   *array_len = len;
1430   
1431   return TRUE;
1432
1433  error:
1434   for (i = 0; i < len; i++)
1435     dbus_free (retval[i]);
1436   dbus_free (retval);
1437
1438   return FALSE;
1439 }
1440
1441 /**
1442  * Demarshals an object path.
1443  *
1444  * @todo implement this function
1445  * 
1446  * @param str the string containing the data
1447  * @param byte_order the byte order
1448  * @param pos the position in the string
1449  * @param new_pos the new position of the string
1450  * @param path address to store new object path
1451  * @param path_len length of stored path
1452  */
1453 dbus_bool_t
1454 _dbus_demarshal_object_path (const DBusString *str,
1455                              int               byte_order,
1456                              int               pos,
1457                              int              *new_pos,
1458                              char           ***path,
1459                              int              *path_len)
1460 {
1461   
1462 }
1463
1464 /** 
1465  * Returns the position right after the end of an argument.  PERFORMS
1466  * NO VALIDATION WHATSOEVER. The message must have been previously
1467  * validated.
1468  *
1469  * @param str a string
1470  * @param byte_order the byte order to use
1471  * @param type the type of the argument
1472  * @param pos the pos where the arg starts
1473  * @param end_pos pointer where the position right
1474  * after the end position will follow
1475  * @returns TRUE if more data exists after the arg
1476  */
1477 dbus_bool_t
1478 _dbus_marshal_get_arg_end_pos (const DBusString *str,
1479                                int               byte_order,
1480                                int               type,
1481                                int               pos,
1482                                int              *end_pos)
1483 {
1484   if (pos >= _dbus_string_get_length (str))
1485     return FALSE;
1486
1487   switch (type)
1488     {
1489     case DBUS_TYPE_INVALID:
1490       return FALSE;
1491       break;
1492
1493     case DBUS_TYPE_NIL:
1494       *end_pos = pos;
1495       break;
1496
1497     case DBUS_TYPE_BYTE:
1498       *end_pos = pos + 1;
1499       break;
1500       
1501     case DBUS_TYPE_BOOLEAN:
1502       *end_pos = pos + 1;
1503       break;
1504
1505     case DBUS_TYPE_INT32:
1506     case DBUS_TYPE_UINT32:
1507       *end_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
1508       break;
1509
1510     case DBUS_TYPE_INT64:
1511     case DBUS_TYPE_UINT64:
1512     case DBUS_TYPE_DOUBLE:
1513       
1514       *end_pos = _DBUS_ALIGN_VALUE (pos, 8) + 8;
1515       break;
1516
1517     case DBUS_TYPE_STRING:
1518       {
1519         int len;
1520         
1521         /* Demarshal the length */
1522         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1523
1524         *end_pos = pos + len + 1;
1525       }
1526       break;
1527
1528     case DBUS_TYPE_NAMED:
1529       {
1530         int len;
1531         
1532         /* Demarshal the string length */
1533         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1534
1535         *end_pos = pos + len + 1;
1536         
1537         /* Demarshal the data length */
1538         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1539
1540         *end_pos = pos + len;
1541       }
1542       break;
1543
1544     case DBUS_TYPE_OBJECT_PATH:
1545     case DBUS_TYPE_ARRAY:
1546       {
1547         int len;
1548
1549         /* Demarshal the length  */
1550         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1551         
1552         *end_pos = pos + len;
1553       }
1554       break;
1555
1556     case DBUS_TYPE_DICT:
1557       {
1558         int len;
1559
1560         /* Demarshal the length */
1561         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1562         
1563         *end_pos = pos + len;
1564       }
1565       break;
1566       
1567     default:
1568       _dbus_warn ("Unknown message arg type %d\n", type);
1569       _dbus_assert_not_reached ("Unknown message argument type\n");
1570       return FALSE;
1571     }
1572
1573   if (*end_pos > _dbus_string_get_length (str))
1574     return FALSE;
1575   
1576   return TRUE;
1577 }
1578
1579 /**
1580  * Demarshals and validates a length; returns < 0 if the validation
1581  * fails. The length is required to be small enough that
1582  * len*sizeof(double) will not overflow, and small enough to fit in a
1583  * signed integer. DOES NOT check whether the length points
1584  * beyond the end of the string, because it doesn't know the
1585  * size of array elements.
1586  *
1587  * @param str the string
1588  * @param byte_order the byte order
1589  * @param pos the unaligned string position (snap to next aligned)
1590  * @param new_pos return location for new position.
1591  */
1592 static int
1593 demarshal_and_validate_len (const DBusString *str,
1594                             int               byte_order,
1595                             int               pos,
1596                             int              *new_pos)
1597 {
1598   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1599   unsigned int len;
1600
1601   _dbus_assert (new_pos != NULL);
1602   
1603   if ((align_4 + 4) > _dbus_string_get_length (str))
1604     {
1605       _dbus_verbose ("not enough room in message for array length\n");
1606       return -1;
1607     }
1608   
1609   if (!_dbus_string_validate_nul (str, pos,
1610                                   align_4 - pos))
1611     {
1612       _dbus_verbose ("array length alignment padding not initialized to nul\n");
1613       return -1;
1614     }
1615
1616   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1617
1618   /* note that the len is the number of bytes, so we need it to be
1619    * at least SIZE_T_MAX, but make it smaller just to keep things
1620    * sane.  We end up using ints for most sizes to avoid unsigned mess
1621    * so limit to maximum 32-bit signed int divided by at least 8, more
1622    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1623    */  
1624 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1625   if (len > MAX_ARRAY_LENGTH)
1626     {
1627       _dbus_verbose ("array length %u exceeds maximum of %u\n",
1628                      len, MAX_ARRAY_LENGTH);
1629       return -1;
1630     }
1631   else
1632     return (int) len;
1633 }
1634
1635 static dbus_bool_t
1636 validate_string (const DBusString *str,
1637                  int               pos,
1638                  int               len_without_nul,
1639                  int              *end_pos)
1640 {
1641   *end_pos = pos + len_without_nul + 1;
1642   
1643   if (*end_pos > _dbus_string_get_length (str))
1644     {
1645       _dbus_verbose ("string length outside length of the message\n");
1646       return FALSE;
1647     }
1648   
1649   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1650     {
1651       _dbus_verbose ("string arg not nul-terminated\n");
1652       return FALSE;
1653     }
1654   
1655   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1656     {
1657       _dbus_verbose ("string is not valid UTF-8\n");
1658       return FALSE;
1659     }
1660
1661   return TRUE;
1662 }   
1663
1664 /**
1665  * Validates and returns a typecode at a specific position
1666  * in the message
1667  *
1668  * @param str a string
1669  * @param type the type of the argument
1670  * @param pos the pos where the typecode starts
1671  * @param end_pos pointer where the position right
1672  * after the end position will follow
1673  * @returns #TRUE if the type is valid.
1674  */
1675 dbus_bool_t
1676 _dbus_marshal_validate_type   (const DBusString *str,
1677                                int               pos,
1678                                int              *type,
1679                                int              *end_pos)
1680 {
1681   const char *data;
1682   
1683   if (pos >= _dbus_string_get_length (str))
1684     return FALSE;
1685
1686   data = _dbus_string_get_const_data_len (str, pos, 1);
1687
1688   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1689     {
1690       *type = *data;
1691       if (end_pos != NULL)
1692         *end_pos = pos + 1;
1693       return TRUE;
1694     }
1695   
1696   return FALSE;
1697 }
1698
1699 /* Faster validator for array data that doesn't call
1700  * validate_arg for each value
1701  */
1702 static dbus_bool_t
1703 validate_array_data (const DBusString *str,
1704                      int               byte_order,
1705                      int               depth,
1706                      int               type,
1707                      int               array_type_pos,
1708                      int               pos,
1709                      int              *new_pos,
1710                      int               end)
1711 {
1712   switch (type)
1713     {
1714     case DBUS_TYPE_INVALID:
1715       return FALSE;
1716       break;
1717
1718     case DBUS_TYPE_NIL:
1719       break;
1720
1721     case DBUS_TYPE_OBJECT_PATH:
1722     case DBUS_TYPE_STRING:
1723     case DBUS_TYPE_NAMED:      
1724     case DBUS_TYPE_ARRAY:
1725     case DBUS_TYPE_DICT:
1726       /* This clean recursion to validate_arg is what we
1727        * are doing logically for all types, but we don't
1728        * really want to call validate_arg for every byte
1729        * in a byte array, so the primitive types are
1730        * special-cased.
1731        */
1732       while (pos < end)
1733         {
1734           if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1735                                            type, array_type_pos, pos, &pos))
1736             return FALSE;
1737         }
1738       break;
1739       
1740     case DBUS_TYPE_BYTE:
1741       pos = end;
1742       break;
1743       
1744     case DBUS_TYPE_BOOLEAN:
1745       while (pos < end)
1746         {
1747           unsigned char c;
1748           
1749           c = _dbus_string_get_byte (str, pos);
1750           
1751           if (!(c == 0 || c == 1))
1752             {
1753               _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1754               return FALSE;
1755             }
1756           
1757           ++pos;
1758         }
1759       break;
1760       
1761     case DBUS_TYPE_INT32:
1762     case DBUS_TYPE_UINT32:
1763       /* Call validate arg one time to check alignment padding
1764        * at start of array
1765        */
1766       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1767                                        type, array_type_pos, pos, &pos))
1768         return FALSE;
1769       pos = _DBUS_ALIGN_VALUE (end, 4);
1770       break;
1771
1772     case DBUS_TYPE_INT64:
1773     case DBUS_TYPE_UINT64:
1774     case DBUS_TYPE_DOUBLE:
1775       /* Call validate arg one time to check alignment padding
1776        * at start of array
1777        */
1778       if (!_dbus_marshal_validate_arg (str, byte_order, depth,
1779                                        type, array_type_pos, pos, &pos))
1780         return FALSE;
1781       pos = _DBUS_ALIGN_VALUE (end, 8);
1782       break;
1783       
1784     default:
1785       _dbus_verbose ("Unknown message arg type %d\n", type);
1786       return FALSE;
1787     }
1788
1789   *new_pos = pos;
1790
1791   return TRUE;
1792 }
1793
1794 /** 
1795  * Validates an argument of a specific type, checking that it
1796  * is well-formed, for example no ludicrous length fields, strings
1797  * are nul-terminated, etc.
1798  * Returns the end position of the argument in end_pos, and
1799  * returns #TRUE if a valid arg begins at "pos"
1800  *
1801  * @todo security: need to audit this function.
1802  *
1803  * @todo For array types that can't be invalid, we should not
1804  * walk the whole array validating it. e.g. just skip all the
1805  * int values in an int array. (maybe this is already done now -hp)
1806  *
1807  * @todo support DBUS_TYPE_OBJECT_PATH
1808  * 
1809  * @param str a string
1810  * @param byte_order the byte order to use
1811  * @param depth current recursion depth, to prevent excessive recursion
1812  * @param type the type of the argument
1813  * @param array_type_pos the position of the current array type, or
1814  *        -1 if not in an array
1815  * @param pos the pos where the arg starts
1816  * @param end_pos pointer where the position right
1817  * after the end position will follow
1818  * @returns #TRUE if the arg is valid.
1819  */
1820 dbus_bool_t
1821 _dbus_marshal_validate_arg (const DBusString *str,
1822                             int               byte_order,
1823                             int               depth,
1824                             int               type,
1825                             int               array_type_pos,
1826                             int               pos,
1827                             int              *end_pos)
1828 {
1829   if (pos > _dbus_string_get_length (str))
1830     {
1831       _dbus_verbose ("Validation went off the end of the message\n");
1832       return FALSE;
1833     }
1834
1835 #define MAX_VALIDATION_DEPTH 32
1836   
1837   if (depth > MAX_VALIDATION_DEPTH)
1838     {
1839       _dbus_verbose ("Maximum recursion depth reached validating message\n");
1840       return FALSE;
1841     }
1842   
1843   switch (type)
1844     {
1845     case DBUS_TYPE_INVALID:
1846       return FALSE;
1847       break;
1848
1849     case DBUS_TYPE_NIL:
1850       *end_pos = pos;
1851       break;
1852
1853     case DBUS_TYPE_BYTE:
1854       if (1 > _dbus_string_get_length (str) - pos)
1855         {
1856           _dbus_verbose ("no room for byte value\n");
1857           return FALSE;
1858         }
1859         
1860       *end_pos = pos + 1;
1861       break;
1862       
1863     case DBUS_TYPE_BOOLEAN:
1864       {
1865         unsigned char c;
1866
1867         if (1 > _dbus_string_get_length (str) - pos)
1868           {
1869             _dbus_verbose ("no room for boolean value\n");
1870             return FALSE;
1871           }
1872         
1873         c = _dbus_string_get_byte (str, pos);
1874
1875         if (!(c == 0 || c == 1))
1876           {
1877             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1878             return FALSE;
1879           }
1880         
1881         *end_pos = pos + 1;
1882       }
1883       break;
1884       
1885     case DBUS_TYPE_INT32:
1886     case DBUS_TYPE_UINT32:
1887       {
1888         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1889         
1890         if (!_dbus_string_validate_nul (str, pos,
1891                                         align_4 - pos))
1892           {
1893             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1894             return FALSE;
1895           }
1896
1897         *end_pos = align_4 + 4;
1898       }
1899       break;
1900
1901     case DBUS_TYPE_INT64:
1902     case DBUS_TYPE_UINT64:      
1903     case DBUS_TYPE_DOUBLE:
1904       {
1905         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1906
1907         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1908         
1909         if (!_dbus_string_validate_nul (str, pos,
1910                                         align_8 - pos))
1911           {
1912             _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul\n");
1913             return FALSE;
1914           }
1915
1916         *end_pos = align_8 + 8;
1917       }
1918       break;
1919
1920     case DBUS_TYPE_STRING:
1921       {
1922         int len;
1923
1924         /* Demarshal the length, which does NOT include
1925          * nul termination
1926          */
1927         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1928         if (len < 0)
1929           return FALSE;
1930
1931         if (!validate_string (str, pos, len, end_pos))
1932           return FALSE;
1933       }
1934       break;
1935
1936     case DBUS_TYPE_NAMED:
1937       {
1938         int len;
1939
1940         /* Demarshal the string length, which does NOT include
1941          * nul termination
1942          */
1943         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1944         if (len < 0)
1945           return FALSE;
1946
1947         if (!validate_string (str, pos, len, &pos))
1948           return FALSE;
1949
1950         /* Validate data */
1951         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1952         if (len < 0)
1953           return FALSE;
1954
1955         *end_pos = pos + len;
1956       }
1957       break;
1958       
1959     case DBUS_TYPE_ARRAY:
1960       {
1961         int len;
1962         int end;
1963         int array_type;
1964
1965         if (array_type_pos == -1)
1966           {
1967             array_type_pos = pos;
1968
1969             do
1970               {
1971                 if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
1972                   {
1973                     _dbus_verbose ("invalid array type\n");
1974                     return FALSE;
1975                   }
1976                 
1977                 /* NIL values take up no space, so you couldn't iterate over an array of them.
1978                  * array of nil seems useless anyway; the useful thing might be array of
1979                  * (nil OR string) but we have no framework for that.
1980                  */
1981                 if (array_type == DBUS_TYPE_NIL)
1982                   {
1983                     _dbus_verbose ("array of NIL is not allowed\n");
1984                     return FALSE;
1985                   }
1986               }
1987             while (array_type == DBUS_TYPE_ARRAY);
1988           }
1989         else
1990           array_type_pos++;
1991
1992         if (!_dbus_marshal_validate_type (str, array_type_pos, &array_type, NULL))
1993           {
1994             _dbus_verbose ("invalid array type\n");
1995             return FALSE;
1996           }
1997         
1998         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1999         if (len < 0)
2000           return FALSE;
2001
2002         if (len > _dbus_string_get_length (str) - pos)
2003           {
2004             _dbus_verbose ("array length outside length of the message\n");
2005             return FALSE;
2006           }
2007         
2008         end = pos + len;
2009
2010         if (!validate_array_data (str, byte_order, depth + 1,
2011                                   array_type, array_type_pos,
2012                                   pos, &pos, end))
2013           return FALSE;
2014
2015         if (pos < end)
2016           {
2017             /* This should not be able to happen, as long as validate_arg moves forward;
2018              * but the check is here just to be paranoid.
2019              */
2020             _dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
2021                            len, end - pos);
2022             return FALSE;
2023           }
2024         
2025         if (pos > end)
2026           {
2027             _dbus_verbose ("array contents exceeds array length %d by %d\n", len, pos - end);
2028             return FALSE;
2029           }
2030
2031         *end_pos = pos;
2032       }
2033       break;
2034
2035     case DBUS_TYPE_DICT:
2036       {
2037         int dict_type;
2038         int len;
2039         int end;
2040         
2041         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
2042         if (len < 0)
2043           return FALSE;
2044
2045         if (len > _dbus_string_get_length (str) - pos)
2046           {
2047             _dbus_verbose ("dict length outside length of the message\n");
2048             return FALSE;
2049           }
2050         
2051         end = pos + len;
2052         
2053         while (pos < end)
2054           {
2055             /* Validate name */
2056             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2057                                              DBUS_TYPE_STRING, -1, pos, &pos))
2058               return FALSE;
2059             
2060             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
2061               {
2062                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
2063                 return FALSE;
2064               }
2065             
2066             /* Validate element */
2067             if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
2068                                              dict_type, -1, pos, &pos))
2069               return FALSE;
2070           }
2071         
2072         if (pos > end)
2073           {
2074             _dbus_verbose ("dict contents exceed stated dict length\n");
2075             return FALSE;
2076           }
2077         
2078         *end_pos = pos;
2079       }
2080       break;
2081       
2082     default:
2083       _dbus_verbose ("Unknown message arg type %d\n", type);
2084       return FALSE;
2085     }
2086
2087   if (*end_pos > _dbus_string_get_length (str))
2088     return FALSE;
2089   
2090   return TRUE;
2091 }
2092
2093
2094 /**
2095  * If in verbose mode, print a block of binary data.
2096  *
2097  * @todo right now it prints even if not in verbose mode
2098  * 
2099  * @param data the data
2100  * @param len the length of the data
2101  */
2102 void
2103 _dbus_verbose_bytes (const unsigned char *data,
2104                      int                  len)
2105 {
2106   int i;
2107   const unsigned char *aligned;
2108
2109   _dbus_assert (len >= 0);
2110   
2111   /* Print blanks on first row if appropriate */
2112   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
2113   if (aligned > data)
2114     aligned -= 4;
2115   _dbus_assert (aligned <= data);
2116
2117   if (aligned != data)
2118     {
2119       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
2120       while (aligned != data)
2121         {
2122           _dbus_verbose ("    ");
2123           ++aligned;
2124         }
2125     }
2126
2127   /* now print the bytes */
2128   i = 0;
2129   while (i < len)
2130     {
2131       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2132         {
2133           _dbus_verbose ("%4d\t%p: ",
2134                    i, &data[i]);
2135         }
2136       
2137       if (data[i] >= 32 &&
2138           data[i] <= 126)
2139         _dbus_verbose (" '%c' ", data[i]);
2140       else
2141         _dbus_verbose ("0x%s%x ",
2142                  data[i] <= 0xf ? "0" : "", data[i]);
2143
2144       ++i;
2145
2146       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
2147         {
2148           if (i > 3)
2149             _dbus_verbose ("BE: %d LE: %d",
2150                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
2151                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
2152
2153           if (i > 7 && 
2154               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
2155             {
2156               _dbus_verbose (" dbl: %g",
2157                              *(double*)&data[i-8]);
2158             }
2159           
2160           _dbus_verbose ("\n");
2161         }
2162     }
2163
2164   _dbus_verbose ("\n");
2165 }
2166
2167 /**
2168  * Dump the given part of the string to verbose log.
2169  *
2170  * @param str the string
2171  * @param start the start of range to dump
2172  * @param len length of range
2173  */
2174 void
2175 _dbus_verbose_bytes_of_string (const DBusString    *str,
2176                                int                  start,
2177                                int                  len)
2178 {
2179   const char *d;
2180   int real_len;
2181
2182   real_len = _dbus_string_get_length (str);
2183
2184   _dbus_assert (start >= 0);
2185   
2186   if (start > real_len)
2187     {
2188       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
2189                      start, len, real_len);
2190       return;
2191     }
2192
2193   if ((start + len) > real_len)
2194     {
2195       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
2196                      start, len, real_len);
2197       len = real_len - start;
2198     }
2199   
2200   d = _dbus_string_get_const_data_len (str, start, len);
2201
2202   _dbus_verbose_bytes (d, len);
2203 }
2204
2205 /** @} */
2206
2207 #ifdef DBUS_BUILD_TESTS
2208 #include "dbus-test.h"
2209 #include <stdio.h>
2210
2211 dbus_bool_t
2212 _dbus_marshal_test (void)
2213 {
2214   DBusString str;
2215   char *tmp1, *tmp2;
2216   int pos = 0, len;
2217   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
2218 #ifdef DBUS_HAVE_INT64
2219   dbus_int64_t array3[3] = { 0x123ffffffff, 0x456ffffffff, 0x789ffffffff }, *array4;
2220 #endif
2221   char *s;
2222   DBusString t;
2223   
2224   if (!_dbus_string_init (&str))
2225     _dbus_assert_not_reached ("failed to init string");
2226
2227   /* Marshal doubles */
2228   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
2229     _dbus_assert_not_reached ("could not marshal double value");
2230   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
2231     _dbus_assert_not_reached ("demarshal failed");
2232
2233   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
2234     _dbus_assert_not_reached ("could not marshal double value");
2235   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
2236     _dbus_assert_not_reached ("demarshal failed");
2237   
2238   /* Marshal signed integers */
2239   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
2240     _dbus_assert_not_reached ("could not marshal signed integer value");
2241   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
2242     _dbus_assert_not_reached ("demarshal failed");
2243
2244   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
2245     _dbus_assert_not_reached ("could not marshal signed integer value");
2246   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
2247     _dbus_assert_not_reached ("demarshal failed");
2248   
2249   /* Marshal unsigned integers */
2250   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
2251     _dbus_assert_not_reached ("could not marshal signed integer value");
2252   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
2253     _dbus_assert_not_reached ("demarshal failed");
2254   
2255   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
2256     _dbus_assert_not_reached ("could not marshal signed integer value");
2257   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
2258     _dbus_assert_not_reached ("demarshal failed");
2259
2260 #ifdef DBUS_HAVE_INT64
2261   /* Marshal signed integers */
2262   if (!_dbus_marshal_int64 (&str, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2263     _dbus_assert_not_reached ("could not marshal signed integer value");
2264   if (!_dbus_demarshal_int64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2265     _dbus_assert_not_reached ("demarshal failed");
2266
2267   if (!_dbus_marshal_int64 (&str, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7)))
2268     _dbus_assert_not_reached ("could not marshal signed integer value");
2269   if (!_dbus_demarshal_int64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_INT64_CONSTANT (-0x123456789abc7))
2270     _dbus_assert_not_reached ("demarshal failed");
2271   
2272   /* Marshal unsigned integers */
2273   if (!_dbus_marshal_uint64 (&str, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2274     _dbus_assert_not_reached ("could not marshal signed integer value");
2275   if (!(_dbus_demarshal_uint64 (&str, DBUS_BIG_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2276     _dbus_assert_not_reached ("demarshal failed");
2277   
2278   if (!_dbus_marshal_uint64 (&str, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7)))
2279     _dbus_assert_not_reached ("could not marshal signed integer value");
2280   if (!(_dbus_demarshal_uint64 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == DBUS_UINT64_CONSTANT (0x123456789abc7)))
2281     _dbus_assert_not_reached ("demarshal failed");
2282 #endif /* DBUS_HAVE_INT64 */
2283   
2284   /* Marshal strings */
2285   tmp1 = "This is the dbus test string";
2286   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
2287     _dbus_assert_not_reached ("could not marshal string");
2288   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
2289   if (!strcmp (tmp1, tmp2) == 0)
2290     _dbus_assert_not_reached ("demarshal failed");
2291   dbus_free (tmp2);
2292
2293   tmp1 = "This is the dbus test string";
2294   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
2295     _dbus_assert_not_reached ("could not marshal string");
2296   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
2297   if (!strcmp (tmp1, tmp2) == 0)
2298     _dbus_assert_not_reached ("demarshal failed");
2299   dbus_free (tmp2);
2300
2301   /* Marshal signed integer arrays */
2302   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
2303     _dbus_assert_not_reached ("could not marshal integer array");
2304   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
2305     _dbus_assert_not_reached ("could not demarshal integer array");
2306
2307   if (len != 3)
2308     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2309   dbus_free (array2);
2310
2311 #ifdef DBUS_HAVE_INT64
2312   /* Marshal 64-bit signed integer arrays */
2313   if (!_dbus_marshal_int64_array (&str, DBUS_BIG_ENDIAN, array3, 3))
2314     _dbus_assert_not_reached ("could not marshal integer array");
2315   if (!_dbus_demarshal_int64_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array4, &len))
2316     _dbus_assert_not_reached ("could not demarshal integer array");
2317
2318   if (len != 3)
2319     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
2320   dbus_free (array4);
2321
2322   /* set/pack 64-bit integers */
2323   _dbus_string_set_length (&str, 8);
2324
2325   /* signed little */
2326   _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
2327                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2328   
2329   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2330                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2331                                     _dbus_string_get_const_data (&str)));
2332
2333   /* signed big */
2334   _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
2335                            0, DBUS_INT64_CONSTANT (-0x123456789abc7));
2336
2337   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2338                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2339                                     _dbus_string_get_const_data (&str)));
2340
2341   /* signed little pack */
2342   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2343                     DBUS_LITTLE_ENDIAN,
2344                     _dbus_string_get_data (&str));
2345   
2346   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2347                 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
2348                                     _dbus_string_get_const_data (&str)));
2349
2350   /* signed big pack */
2351   _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
2352                     DBUS_BIG_ENDIAN,
2353                     _dbus_string_get_data (&str));
2354
2355   _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
2356                 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
2357                                     _dbus_string_get_const_data (&str)));
2358
2359   /* unsigned little */
2360   _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
2361                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2362   
2363   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2364                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2365                                      _dbus_string_get_const_data (&str)));
2366
2367   /* unsigned big */
2368   _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
2369                             0, DBUS_UINT64_CONSTANT (0x123456789abc7));
2370
2371   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2372                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2373                                      _dbus_string_get_const_data (&str)));
2374
2375   /* unsigned little pack */
2376   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2377                      DBUS_LITTLE_ENDIAN,
2378                      _dbus_string_get_data (&str));
2379   
2380   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2381                 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
2382                                      _dbus_string_get_const_data (&str)));
2383
2384   /* unsigned big pack */
2385   _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
2386                      DBUS_BIG_ENDIAN,
2387                      _dbus_string_get_data (&str));
2388
2389   _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
2390                 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
2391                                      _dbus_string_get_const_data (&str)));
2392   
2393 #endif
2394
2395   /* set/pack 32-bit integers */
2396   _dbus_string_set_length (&str, 4);
2397
2398   /* signed little */
2399   _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
2400                            0, -0x123456);
2401   
2402   _dbus_assert (-0x123456 ==
2403                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2404                                     _dbus_string_get_const_data (&str)));
2405
2406   /* signed big */
2407   _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
2408                            0, -0x123456);
2409
2410   _dbus_assert (-0x123456 ==
2411                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2412                                     _dbus_string_get_const_data (&str)));
2413
2414   /* signed little pack */
2415   _dbus_pack_int32 (-0x123456,
2416                     DBUS_LITTLE_ENDIAN,
2417                     _dbus_string_get_data (&str));
2418   
2419   _dbus_assert (-0x123456 ==
2420                 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
2421                                     _dbus_string_get_const_data (&str)));
2422
2423   /* signed big pack */
2424   _dbus_pack_int32 (-0x123456,
2425                     DBUS_BIG_ENDIAN,
2426                     _dbus_string_get_data (&str));
2427
2428   _dbus_assert (-0x123456 ==
2429                 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
2430                                     _dbus_string_get_const_data (&str)));
2431
2432   /* unsigned little */
2433   _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
2434                             0, 0x123456);
2435   
2436   _dbus_assert (0x123456 ==
2437                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2438                                      _dbus_string_get_const_data (&str)));
2439
2440   /* unsigned big */
2441   _dbus_marshal_set_uint32 (&str, DBUS_BIG_ENDIAN,
2442                             0, 0x123456);
2443
2444   _dbus_assert (0x123456 ==
2445                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2446                                      _dbus_string_get_const_data (&str)));
2447
2448   /* unsigned little pack */
2449   _dbus_pack_uint32 (0x123456,
2450                      DBUS_LITTLE_ENDIAN,
2451                      _dbus_string_get_data (&str));
2452   
2453   _dbus_assert (0x123456 ==
2454                 _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
2455                                      _dbus_string_get_const_data (&str)));
2456
2457   /* unsigned big pack */
2458   _dbus_pack_uint32 (0x123456,
2459                      DBUS_BIG_ENDIAN,
2460                      _dbus_string_get_data (&str));
2461
2462   _dbus_assert (0x123456 ==
2463                 _dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
2464                                      _dbus_string_get_const_data (&str)));
2465
2466
2467   /* Strings */
2468   
2469   _dbus_string_set_length (&str, 0);
2470
2471   _dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN,
2472                         "Hello world");
2473   
2474   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2475   _dbus_assert (strcmp (s, "Hello world") == 0);
2476   dbus_free (s);
2477
2478   _dbus_string_init_const (&t, "Hello world foo");
2479   
2480   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2481                             &t, _dbus_string_get_length (&t));
2482   
2483   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2484   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2485   dbus_free (s);
2486
2487   _dbus_string_init_const (&t, "Hello");
2488   
2489   _dbus_marshal_set_string (&str, DBUS_LITTLE_ENDIAN, 0,
2490                             &t, _dbus_string_get_length (&t));
2491   
2492   s = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, 0, NULL);
2493   _dbus_assert (strcmp (s, "Hello") == 0);
2494   dbus_free (s);
2495
2496   /* Strings (big endian) */
2497   
2498   _dbus_string_set_length (&str, 0);
2499
2500   _dbus_marshal_string (&str, DBUS_BIG_ENDIAN,
2501                         "Hello world");
2502   
2503   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2504   _dbus_assert (strcmp (s, "Hello world") == 0);
2505   dbus_free (s);
2506
2507   _dbus_string_init_const (&t, "Hello world foo");
2508   
2509   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2510                             &t, _dbus_string_get_length (&t));
2511   
2512   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2513   _dbus_assert (strcmp (s, "Hello world foo") == 0);
2514   dbus_free (s);
2515
2516   _dbus_string_init_const (&t, "Hello");
2517   
2518   _dbus_marshal_set_string (&str, DBUS_BIG_ENDIAN, 0,
2519                             &t, _dbus_string_get_length (&t));
2520   
2521   s = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, 0, NULL);
2522   _dbus_assert (strcmp (s, "Hello") == 0);
2523   dbus_free (s);
2524
2525   
2526   _dbus_string_free (&str);
2527       
2528   return TRUE;
2529 }
2530
2531 #endif /* DBUS_BUILD_TESTS */