2003-04-08 Alexander Larsson <alexl@redhat.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  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-marshal.h"
25 #include "dbus-internals.h"
26 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
27 #include "dbus-string-private.h"
28
29 #include <string.h>
30
31 /* from ORBit */
32 static void
33 swap_bytes (unsigned char *data,
34             unsigned int   len)
35 {
36   unsigned char *p1 = data;
37   unsigned char *p2 = data + len - 1;
38
39   while (p1 < p2)
40     {
41       unsigned char tmp = *p1;
42       *p1 = *p2;
43       *p2 = tmp;
44
45       --p2;
46       ++p1;
47     }
48 }
49
50 /**
51  * @defgroup DBusMarshal marshaling and unmarshaling
52  * @ingroup  DBusInternals
53  * @brief functions to marshal/unmarshal data from the wire
54  *
55  * Types and functions related to converting primitive data types from
56  * wire format to native machine format, and vice versa.
57  *
58  * @{
59  */
60
61 /**
62  * Unpacks a 32 bit unsigned integer from a data pointer
63  *
64  * @param byte_order The byte order to use
65  * @param data the data pointer
66  * @returns the integer
67  */
68 dbus_uint32_t
69 _dbus_unpack_uint32 (int                  byte_order,
70                      const unsigned char *data)
71 {
72   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
73   
74   if (byte_order == DBUS_LITTLE_ENDIAN)
75     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
76   else
77     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
78 }  
79
80 /**
81  * Unpacks a 32 bit signed integer from a data pointer
82  *
83  * @param byte_order The byte order to use
84  * @param data the data pointer
85  * @returns the integer
86  */
87 dbus_int32_t
88 _dbus_unpack_int32 (int                  byte_order,
89                     const unsigned char *data)
90 {
91   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
92   
93   if (byte_order == DBUS_LITTLE_ENDIAN)
94     return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
95   else
96     return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
97 }
98
99 /**
100  * Packs a 32 bit unsigned integer into a data pointer.
101  *
102  * @param value the value
103  * @param byte_order the byte order to use
104  * @param data the data pointer
105  */
106 void
107 _dbus_pack_uint32 (dbus_uint32_t   value,
108                    int             byte_order,
109                    unsigned char  *data)
110 {
111   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
112   
113   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
114     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
115   else
116     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
117 }
118
119 /**
120  * Packs a 32 bit signed integer into a data pointer.
121  *
122  * @param value the value
123  * @param byte_order the byte order to use
124  * @param data the data pointer
125  */
126 void
127 _dbus_pack_int32 (dbus_int32_t   value,
128                   int            byte_order,
129                   unsigned char *data)
130 {
131   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
132   
133   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
134     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);       
135   else
136     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
137 }
138
139 /**
140  * Sets the 4 bytes at the given offset to a marshaled signed integer,
141  * replacing anything found there previously.
142  *
143  * @param str the string to write the marshalled int to
144  * @param offset the byte offset where int should be written
145  * @param byte_order the byte order to use
146  * @param value the value
147  * 
148  */
149 void
150 _dbus_marshal_set_int32 (DBusString          *str,
151                          int                  byte_order,
152                          int                  offset,
153                          dbus_int32_t         value)
154 {
155   char *data;
156   
157   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
158                 byte_order == DBUS_BIG_ENDIAN);
159   
160   data = _dbus_string_get_data_len (str, offset, 4);
161
162   _dbus_pack_int32 (value, byte_order, data);
163 }
164
165 /**
166  * Sets the 4 bytes at the given offset to a marshaled unsigned
167  * integer, replacing anything found there previously.
168  *
169  * @param str the string to write the marshalled int to
170  * @param offset the byte offset where int should be written
171  * @param byte_order the byte order to use
172  * @param value the value
173  * 
174  */
175 void
176 _dbus_marshal_set_uint32 (DBusString          *str,
177                           int                  byte_order,
178                           int                  offset,
179                           dbus_uint32_t        value)
180 {
181   char *data;
182   
183   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
184                 byte_order == DBUS_BIG_ENDIAN);
185   
186   data = _dbus_string_get_data_len (str, offset, 4);
187
188   _dbus_pack_uint32 (value, byte_order, data);
189 }
190
191 /**
192  * Sets the existing marshaled string at the given offset with
193  * a new marshaled string. The given offset must point to
194  * an existing string or the wrong length will be deleted
195  * and replaced with the new string.
196  *
197  * @param str the string to write the marshalled string to
198  * @param offset the byte offset where string should be written
199  * @param byte_order the byte order to use
200  * @param value the value
201  * @param len the length to use
202  * @returns #TRUE on success
203  * 
204  */
205 dbus_bool_t
206 _dbus_marshal_set_string (DBusString          *str,
207                           int                  byte_order,
208                           int                  offset,
209                           const DBusString    *value,
210                           int                  len)
211 {
212   int old_len;
213   
214   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
215                 byte_order == DBUS_BIG_ENDIAN);
216   
217   old_len = _dbus_demarshal_uint32 (str, byte_order,
218                                     offset, NULL);
219
220   if (!_dbus_string_replace_len (value, 0, len,
221                                  str, offset + 4, old_len))
222     return FALSE;
223
224   _dbus_marshal_set_uint32 (str, byte_order,
225                             offset, len);
226
227   return TRUE;
228 }
229
230 /**
231  * Marshals a double value.
232  *
233  * @param str the string to append the marshalled value to
234  * @param byte_order the byte order to use
235  * @param value the value
236  * @returns #TRUE on success
237  */
238 dbus_bool_t
239 _dbus_marshal_double (DBusString *str,
240                       int         byte_order,
241                       double      value)
242 {
243   _dbus_assert (sizeof (double) == 8);
244
245   if (!_dbus_string_align_length (str, sizeof (double)))
246     return FALSE;
247   
248   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
249     swap_bytes ((unsigned char *)&value, sizeof (double));
250
251   return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
252 }
253
254 /**
255  * Marshals a 32 bit signed integer value.
256  *
257  * @param str the string to append the marshalled value to
258  * @param byte_order the byte order to use
259  * @param value the value
260  * @returns #TRUE on success
261  */
262 dbus_bool_t
263 _dbus_marshal_int32  (DBusString   *str,
264                       int           byte_order,
265                       dbus_int32_t  value)
266 {
267   if (!_dbus_string_align_length (str, sizeof (dbus_int32_t)))
268     return FALSE;
269   
270   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
271     value = DBUS_INT32_SWAP_LE_BE (value);
272
273   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
274 }
275
276 /**
277  * Marshals a 32 bit unsigned integer value.
278  *
279  * @param str the string to append the marshalled value to
280  * @param byte_order the byte order to use
281  * @param value the value
282  * @returns #TRUE on success
283  */
284 dbus_bool_t
285 _dbus_marshal_uint32 (DBusString    *str,
286                       int            byte_order,
287                       dbus_uint32_t  value)
288 {
289   if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
290     return FALSE;
291   
292   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
293     value = DBUS_UINT32_SWAP_LE_BE (value);
294
295   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
296 }
297
298 /**
299  * Marshals a UTF-8 string
300  *
301  * @todo: If the string append fails we need to restore
302  * the old length. (also for other marshallers)
303  * 
304  * @param str the string to append the marshalled value to
305  * @param byte_order the byte order to use
306  * @param value the string
307  * @returns #TRUE on success
308  */
309 dbus_bool_t
310 _dbus_marshal_string (DBusString    *str,
311                       int            byte_order,
312                       const char    *value)
313 {
314   int len, old_string_len;
315
316   old_string_len = _dbus_string_get_length (str);
317   
318   len = strlen (value);
319
320   if (!_dbus_marshal_uint32 (str, byte_order, len))
321     {
322       /* Restore the previous length */
323       _dbus_string_set_length (str, old_string_len);
324
325       return FALSE;
326     }
327
328   return _dbus_string_append_len (str, value, len + 1);
329 }
330
331 /**
332  * Marshals a byte array
333  *
334  * @param str the string to append the marshalled value to
335  * @param byte_order the byte order to use
336  * @param value the array
337  * @param len number of elements in the array
338  * @returns #TRUE on success
339  */
340 dbus_bool_t
341 _dbus_marshal_byte_array (DBusString          *str,
342                           int                  byte_order,
343                           const unsigned char *value,
344                           int                  len)
345 {
346   int old_string_len;
347
348   old_string_len = _dbus_string_get_length (str);
349   
350   if (!_dbus_marshal_uint32 (str, byte_order, len))
351     {
352       /* Restore the previous length */
353       _dbus_string_set_length (str, old_string_len);
354
355       return FALSE;
356     }
357
358   if (len == 0)
359     return TRUE;
360   else
361     return _dbus_string_append_len (str, value, len);
362 }
363
364 /**
365  * Marshals a 32 bit signed integer array
366  *
367  * @param str the string to append the marshalled value to
368  * @param byte_order the byte order to use
369  * @param value the array
370  * @param len the length of the array
371  * @returns #TRUE on success
372  */
373 dbus_bool_t
374 _dbus_marshal_int32_array (DBusString         *str,
375                            int                 byte_order,
376                            const dbus_int32_t *value,
377                            int                 len)
378 {
379   int i, old_string_len;
380
381   old_string_len = _dbus_string_get_length (str);
382
383   if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_int32_t)))
384     goto error;
385
386   for (i = 0; i < len; i++)
387     if (!_dbus_marshal_int32 (str, byte_order, value[i]))
388       goto error;
389
390   return TRUE;
391   
392  error:
393   /* Restore previous length */
394   _dbus_string_set_length (str, old_string_len);
395   
396   return FALSE;
397 }
398
399 /**
400  * Marshals a 32 bit unsigned integer array
401  *
402  * @param str the string to append the marshalled value to
403  * @param byte_order the byte order to use
404  * @param value the array
405  * @param len the length of the array
406  * @returns #TRUE on success
407  */
408 dbus_bool_t
409 _dbus_marshal_uint32_array (DBusString          *str,
410                             int                  byte_order,
411                             const dbus_uint32_t  *value,
412                             int                  len)
413 {
414   int i, old_string_len;
415
416   old_string_len = _dbus_string_get_length (str);
417
418   if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_uint32_t)))
419     goto error;
420
421   for (i = 0; i < len; i++)
422     if (!_dbus_marshal_uint32 (str, byte_order, value[i]))
423       goto error;
424
425   return TRUE;
426   
427  error:
428   /* Restore previous length */
429   _dbus_string_set_length (str, old_string_len);
430   
431   return FALSE;  
432 }
433
434 /**
435  * Marshals a double array
436  *
437  * @param str the string to append the marshalled value to
438  * @param byte_order the byte order to use
439  * @param value the array
440  * @param len the length of the array
441  * @returns #TRUE on success
442  */
443 dbus_bool_t
444 _dbus_marshal_double_array (DBusString          *str,
445                             int                  byte_order,
446                             const double        *value,
447                             int                  len)
448 {
449   int i, old_string_len, array_start;
450
451   old_string_len = _dbus_string_get_length (str);
452
453   /* Set the length to 0 temporarily */
454   if (!_dbus_marshal_uint32 (str, byte_order, 0))
455     goto error;
456       
457   array_start = _dbus_string_get_length (str);
458       
459   for (i = 0; i < len; i++)
460     if (!_dbus_marshal_double (str, byte_order, value[i]))
461       goto error;
462
463   /* Write the length now that we know it */
464   _dbus_marshal_set_uint32 (str, byte_order,
465                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
466                             _dbus_string_get_length (str) - array_start);
467   
468   return TRUE;
469   
470  error:
471   /* Restore previous length */
472   _dbus_string_set_length (str, old_string_len);
473   
474   return FALSE;    
475 }
476
477 /**
478  * Marshals a string array
479  *
480  * @param str the string to append the marshalled value to
481  * @param byte_order the byte order to use
482  * @param value the array
483  * @param len the length of the array
484  * @returns #TRUE on success
485  */
486 dbus_bool_t
487 _dbus_marshal_string_array (DBusString  *str,
488                             int          byte_order,
489                             const char **value,
490                             int          len)
491 {
492   int i, old_string_len, array_start;
493
494   old_string_len = _dbus_string_get_length (str);
495
496   /* Set the length to 0 temporarily */
497   if (!_dbus_marshal_uint32 (str, byte_order, 0))
498     goto error;
499
500   array_start = _dbus_string_get_length (str);
501   
502   for (i = 0; i < len; i++)
503     if (!_dbus_marshal_string (str, byte_order, value[i]))
504       goto error;
505
506   /* Write the length now that we know it */
507   _dbus_marshal_set_uint32 (str, byte_order,
508                             _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
509                             _dbus_string_get_length (str) - array_start);
510   
511   return TRUE;
512   
513  error:
514   /* Restore previous length */
515   _dbus_string_set_length (str, old_string_len);
516   
517   return FALSE;      
518 }
519
520
521 /**
522  * Demarshals a double.
523  *
524  * @param str the string containing the data
525  * @param byte_order the byte order
526  * @param pos the position in the string
527  * @param new_pos the new position of the string
528  * @returns the demarshaled double.
529  */
530 double
531 _dbus_demarshal_double (const DBusString  *str,
532                         int          byte_order,
533                         int          pos,
534                         int         *new_pos)
535 {
536   double retval;
537   const char *buffer;
538
539   pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
540
541   buffer = _dbus_string_get_const_data_len (str, pos, sizeof (double));
542
543   retval = *(double *)buffer;
544   
545   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
546     swap_bytes ((unsigned char *)&retval, sizeof (double));
547
548   if (new_pos)
549     *new_pos = pos + sizeof (double);
550   
551   return retval;  
552 }
553
554 /**
555  * Demarshals a 32 bit signed integer.
556  *
557  * @param str the string containing the data
558  * @param byte_order the byte order
559  * @param pos the position in the string
560  * @param new_pos the new position of the string
561  * @returns the demarshaled integer.
562  */
563 dbus_int32_t
564 _dbus_demarshal_int32  (const DBusString *str,
565                         int               byte_order,
566                         int               pos,
567                         int              *new_pos)
568 {
569   const DBusRealString *real = (const DBusRealString*) str;
570   
571   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
572   
573   if (new_pos)
574     *new_pos = pos + sizeof (dbus_int32_t);
575
576   if (byte_order == DBUS_LITTLE_ENDIAN)
577     return DBUS_INT32_FROM_LE (*(dbus_int32_t*)(real->str + pos));
578   else
579     return DBUS_INT32_FROM_BE (*(dbus_int32_t*)(real->str + pos));
580 }
581
582 /**
583  * Demarshals a 32 bit unsigned integer.
584  *
585  * @param str the string containing the data
586  * @param byte_order the byte order
587  * @param pos the position in the string
588  * @param new_pos the new position of the string
589  * @returns the demarshaled integer.
590  */
591 dbus_uint32_t
592 _dbus_demarshal_uint32  (const DBusString *str,
593                          int         byte_order,
594                          int         pos,
595                          int        *new_pos)
596 {
597   const DBusRealString *real = (const DBusRealString*) str;
598   
599   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
600   
601   if (new_pos)
602     *new_pos = pos + sizeof (dbus_uint32_t);
603
604   if (byte_order == DBUS_LITTLE_ENDIAN)
605     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)(real->str + pos));
606   else
607     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)(real->str + pos));
608 }
609
610 /**
611  * Demarshals an UTF-8 string.
612  *
613  * @todo Should we check the string to make sure
614  * that it's  valid UTF-8, and maybe "fix" the string
615  * if it's broken?
616  *
617  * @todo Should probably demarshal to a DBusString,
618  * having memcpy() in here is Evil(tm).
619  *
620  * @param str the string containing the data
621  * @param byte_order the byte order
622  * @param pos the position in the string
623  * @param new_pos the new position of the string
624  * @returns the demarshaled string.
625  */
626 char *
627 _dbus_demarshal_string (const DBusString *str,
628                         int         byte_order,
629                         int         pos,
630                         int        *new_pos)
631 {
632   int len;
633   char *retval;
634   const char *data;
635   
636   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
637
638   retval = dbus_malloc (len + 1);
639
640   if (!retval)
641     return NULL;
642
643   data = _dbus_string_get_const_data_len (str, pos, len + 1);
644
645   if (!data)
646     return NULL;
647
648   memcpy (retval, data, len + 1);
649
650   if (new_pos)
651     *new_pos = pos + len + 1;
652   
653   return retval;
654 }
655
656 /**
657  * Demarshals a byte array.
658  *
659  * @todo Should probably demarshal to a DBusString,
660  * having memcpy() in here is Evil(tm).
661  *
662  * @param str the string containing the data
663  * @param byte_order the byte order
664  * @param pos the position in the string
665  * @param new_pos the new position of the string
666  * @param array the array
667  * @param array_len length of the demarshaled data
668  
669  * @returns #TRUE on success
670  */
671 dbus_bool_t
672 _dbus_demarshal_byte_array (const DBusString  *str,
673                             int                byte_order,
674                             int                pos,
675                             int               *new_pos,
676                             unsigned char    **array,
677                             int               *array_len)
678 {
679   int len;
680   unsigned char *retval;
681   const char *data;
682
683   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
684
685   if (len == 0)
686     {
687       *array_len = len;
688       *array = NULL;
689
690       if (new_pos)
691         *new_pos = pos;
692       
693       return TRUE;
694     }
695   
696   retval = dbus_malloc (len);
697
698   if (!retval)
699     return FALSE;
700
701   data = _dbus_string_get_const_data_len (str, pos, len);
702
703   if (!data)
704     {
705       dbus_free (retval);
706       return FALSE;
707     }
708
709   memcpy (retval, data, len);
710
711   if (new_pos)
712     *new_pos = pos + len;
713
714   *array = retval;
715   *array_len = len;
716   
717   return TRUE;
718 }
719
720 /**
721  * Demarshals a 32 bit signed integer array.
722  *
723  * @param str the string containing the data
724  * @param byte_order the byte order
725  * @param pos the position in the string
726  * @param new_pos the new position of the string
727  * @param array the array
728  * @param array_len length of the demarshaled data
729  * @returns #TRUE on success
730  */
731 dbus_bool_t
732 _dbus_demarshal_int32_array (const DBusString  *str,
733                              int                byte_order,
734                              int                pos,
735                              int               *new_pos,
736                              dbus_int32_t     **array,
737                              int               *array_len)
738 {
739   int len, i;
740   dbus_int32_t *retval;
741   
742   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos)  / sizeof (dbus_int32_t);
743
744   if (len == 0)
745     {
746       *array_len = 0;
747       *array = NULL;
748
749       if (new_pos)
750         *new_pos = pos;
751       
752       return TRUE;
753     }
754   
755   retval = dbus_new (dbus_int32_t, len);
756   
757   if (!retval)
758     return FALSE;
759
760   for (i = 0; i < len; i++)
761     retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
762
763   if (new_pos)
764     *new_pos = pos;
765
766   *array_len = len;
767   *array = retval;
768   
769   return TRUE;
770 }
771
772 /**
773  * Demarshals a 32 bit unsigned integer array.
774  *
775  * @param str the string containing the data
776  * @param byte_order the byte order
777  * @param pos the position in the string
778  * @param new_pos the new position of the string
779  * @param array the array
780  * @param array_len length of the demarshaled data
781  * @returns #TRUE on success
782  */
783 dbus_bool_t
784 _dbus_demarshal_uint32_array (const DBusString  *str,
785                               int                byte_order,
786                               int                pos,
787                               int               *new_pos,
788                               dbus_uint32_t    **array,
789                               int               *array_len)
790 {
791   int len, i;
792   dbus_uint32_t *retval;
793   
794   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (dbus_uint32_t);
795
796   if (len == 0)
797     {
798       *array_len = 0;
799       *array = NULL;
800
801       if (new_pos)
802         *new_pos = pos;
803       
804       return TRUE;
805     }
806   
807   retval = dbus_new (dbus_uint32_t, len);
808
809   if (!retval)
810     return FALSE;
811
812   for (i = 0; i < len; i++)
813     retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
814
815   if (new_pos)
816     *new_pos = pos;
817
818   *array_len = len;
819   *array = retval;
820   
821   return TRUE;  
822 }
823
824 /**
825  * Demarshals a double array.
826  *
827  * @param str the string containing the data
828  * @param byte_order the byte order
829  * @param pos the position in the string
830  * @param new_pos the new position of the string
831  * @param array the array
832  * @param array_len length of the demarshaled data
833  * @returns #TRUE on success
834  */
835 dbus_bool_t
836 _dbus_demarshal_double_array (const DBusString  *str,
837                               int                byte_order,
838                               int                pos,
839                               int               *new_pos,
840                               double           **array,
841                               int               *array_len)
842 {
843   int len, i;
844   double *retval;
845   
846   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (double);
847
848   if (len == 0)
849     {
850       *array_len = 0;
851       *array = NULL;
852
853       if (new_pos)
854         *new_pos = pos;
855       
856       return TRUE;
857     }
858   
859   retval = dbus_new (double, len);
860
861   if (!retval)
862     return FALSE;
863
864   for (i = 0; i < len; i++)
865     retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
866
867   if (new_pos)
868     *new_pos = pos;
869
870   *array_len = len;
871   *array = retval;
872   
873   return TRUE; 
874 }
875
876 /**
877  * Demarshals a string array.
878  *
879  * @param str the string containing the data
880  * @param byte_order the byte order
881  * @param pos the position in the string
882  * @param new_pos the new position of the string
883  * @param array the array
884  * @param array_len length of the demarshaled data
885  * @returns #TRUE on success
886  */
887 dbus_bool_t
888 _dbus_demarshal_string_array (const DBusString   *str,
889                               int                 byte_order,
890                               int                 pos,
891                               int                *new_pos,
892                               char             ***array,
893                               int                *array_len)
894 {
895   int len, i, j;
896   char **retval;
897
898   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
899
900   if (len == 0)
901     {
902       *array_len = 0;
903       *array = NULL;
904
905       if (new_pos)
906         *new_pos = pos;
907       
908       return TRUE;
909     }
910   
911   retval = dbus_new (char *, len + 1);
912
913   if (!retval)
914     return FALSE;
915
916   retval[len] = NULL;
917   
918   for (i = 0; i < len; i++)
919     {
920       retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
921
922       if (retval[i] == 0)
923         goto error;
924     }
925
926  if (new_pos)
927     *new_pos = pos;
928
929  *array = retval;
930  *array_len = len;
931   
932   return TRUE;
933
934  error:
935   for (j = 0; j < i; j++)
936     dbus_free (retval[i]);
937   dbus_free (retval);
938
939   return FALSE;
940 }
941
942 /** 
943  * Returns the position right after the end of an argument.  PERFORMS
944  * NO VALIDATION WHATSOEVER. The message must have been previously
945  * validated.
946  *
947  * @param str a string
948  * @param byte_order the byte order to use
949  * @param type the type of the argument
950  * @param pos the pos where the arg starts
951  * @param end_pos pointer where the position right
952  * after the end position will follow
953  * @returns TRUE if more data exists after the arg
954  */
955 dbus_bool_t
956 _dbus_marshal_get_arg_end_pos (const DBusString *str,
957                                int               byte_order,
958                                int               type,
959                                int               pos,
960                                int              *end_pos)
961 {
962   if (pos >= _dbus_string_get_length (str))
963     return FALSE;
964
965   switch (type)
966     {
967     case DBUS_TYPE_INVALID:
968       return FALSE;
969       break;
970
971     case DBUS_TYPE_NIL:
972       *end_pos = pos;
973       break;
974
975     case DBUS_TYPE_BYTE:
976       *end_pos = pos + 1;
977       break;
978       
979     case DBUS_TYPE_BOOLEAN:
980       *end_pos = pos + 1;
981       break;
982
983     case DBUS_TYPE_INT32:
984       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
985
986       break;
987
988     case DBUS_TYPE_UINT32:
989       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
990
991       break;
992
993     case DBUS_TYPE_DOUBLE:
994       *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
995
996       break;
997
998     case DBUS_TYPE_STRING:
999       {
1000         int len;
1001         
1002         /* Demarshal the length */
1003         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1004
1005         *end_pos = pos + len + 1;
1006       }
1007       break;
1008
1009     case DBUS_TYPE_NAMED:
1010       {
1011         int len;
1012         
1013         /* Demarshal the string length */
1014         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1015
1016         *end_pos = pos + len + 1;
1017         
1018         /* Demarshal the data length */
1019         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1020
1021         *end_pos = pos + len;
1022       }
1023       break;
1024       
1025     case DBUS_TYPE_ARRAY:
1026       {
1027         int len;
1028
1029         /* Demarshal the length (element type is at pos + 0 */
1030         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
1031         
1032         *end_pos = pos + len;
1033       }
1034       break;
1035
1036     case DBUS_TYPE_DICT:
1037       {
1038         int len;
1039
1040         /* Demarshal the length */
1041         len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
1042         
1043         *end_pos = pos + len;
1044       }
1045       break;
1046       
1047     default:
1048       _dbus_warn ("Unknown message arg type %d\n", type);
1049       _dbus_assert_not_reached ("Unknown message argument type\n");
1050       return FALSE;
1051     }
1052
1053   if (*end_pos > _dbus_string_get_length (str))
1054     return FALSE;
1055   
1056   return TRUE;
1057 }
1058
1059 /**
1060  * Demarshals and validates a length; returns < 0 if the validation
1061  * fails. The length is required to be small enough that
1062  * len*sizeof(double) will not overflow, and small enough to fit in a
1063  * signed integer. DOES NOT check whether the length points
1064  * beyond the end of the string, because it doesn't know the
1065  * size of array elements.
1066  *
1067  * @param str the string
1068  * @param byte_order the byte order
1069  * @param pos the unaligned string position (snap to next aligned)
1070  * @param new_pos return location for new position.
1071  */
1072 static int
1073 demarshal_and_validate_len (const DBusString *str,
1074                             int               byte_order,
1075                             int               pos,
1076                             int              *new_pos)
1077 {
1078   int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1079   unsigned int len;
1080
1081   _dbus_assert (new_pos != NULL);
1082   
1083   if ((align_4 + 4) > _dbus_string_get_length (str))
1084     {
1085       _dbus_verbose ("not enough room in message for array length\n");
1086       return -1;
1087     }
1088   
1089   if (!_dbus_string_validate_nul (str, pos,
1090                                   align_4 - pos))
1091     {
1092       _dbus_verbose ("array length alignment padding not initialized to nul\n");
1093       return -1;
1094     }
1095
1096   len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
1097
1098   /* note that the len is the number of bytes, so we need it to be
1099    * at least SIZE_T_MAX, but make it smaller just to keep things
1100    * sane.  We end up using ints for most sizes to avoid unsigned mess
1101    * so limit to maximum 32-bit signed int divided by at least 8, more
1102    * for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
1103    */  
1104 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
1105   if (len > MAX_ARRAY_LENGTH)
1106     {
1107       _dbus_verbose ("array length %u exceeds maximum of %u\n",
1108                      len, MAX_ARRAY_LENGTH);
1109       return -1;
1110     }
1111   else
1112     return (int) len;
1113 }
1114
1115 static dbus_bool_t
1116 validate_string (const DBusString *str,
1117                  int               pos,
1118                  int               len_without_nul,
1119                  int              *end_pos)
1120 {
1121   *end_pos = pos + len_without_nul + 1;
1122   
1123   if (*end_pos > _dbus_string_get_length (str))
1124     {
1125       _dbus_verbose ("string length outside length of the message\n");
1126       return FALSE;
1127     }
1128   
1129   if (_dbus_string_get_byte (str, pos + len_without_nul) != '\0')
1130     {
1131       _dbus_verbose ("string arg not nul-terminated\n");
1132       return FALSE;
1133     }
1134   
1135   if (!_dbus_string_validate_utf8 (str, pos, len_without_nul))
1136     {
1137       _dbus_verbose ("string is not valid UTF-8\n");
1138       return FALSE;
1139     }
1140
1141   return TRUE;
1142 }   
1143
1144 /**
1145  * Validates and returns a typecode at a specific position
1146  * in the message
1147  *
1148  * @param str a string
1149  * @param type the type of the argument
1150  * @param pos the pos where the typecode starts
1151  * @param end_pos pointer where the position right
1152  * after the end position will follow
1153  * @returns #TRUE if the type is valid.
1154  */
1155 dbus_bool_t
1156 _dbus_marshal_validate_type   (const DBusString *str,
1157                                int               pos,
1158                                int              *type,
1159                                int              *end_pos)
1160 {
1161   const char *data;
1162   
1163   if (pos >= _dbus_string_get_length (str))
1164     return FALSE;
1165
1166   data = _dbus_string_get_const_data_len (str, pos, 1);
1167
1168   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1169     {
1170       *type = *data;
1171       *end_pos = pos + 1;
1172       return TRUE;
1173     }
1174   
1175   return FALSE;
1176 }
1177
1178
1179 /** 
1180  * Validates an argument of a specific type, checking that it
1181  * is well-formed, for example no ludicrous length fields, strings
1182  * are nul-terminated, etc.
1183  * Returns the end position of the argument in end_pos, and
1184  * returns #TRUE if a valid arg begins at "pos"
1185  *
1186  * @todo security: need to audit this function.
1187  * 
1188  * @param str a string
1189  * @param byte_order the byte order to use
1190  * @param type the type of the argument
1191  * @param pos the pos where the arg starts
1192  * @param end_pos pointer where the position right
1193  * after the end position will follow
1194  * @returns #TRUE if the arg is valid.
1195  */
1196 dbus_bool_t
1197 _dbus_marshal_validate_arg (const DBusString *str,
1198                             int               byte_order,
1199                             int               type,
1200                             int               pos,
1201                             int              *end_pos)
1202 {
1203   if (pos > _dbus_string_get_length (str))
1204     return FALSE;
1205
1206   switch (type)
1207     {
1208     case DBUS_TYPE_INVALID:
1209       return FALSE;
1210       break;
1211
1212     case DBUS_TYPE_NIL:
1213       *end_pos = pos;
1214       break;
1215
1216     case DBUS_TYPE_BYTE:
1217       if (1 > _dbus_string_get_length (str) - pos)
1218         {
1219           _dbus_verbose ("no room for boolean value\n");
1220           return FALSE;
1221         }
1222         
1223       *end_pos = pos + 1;
1224       break;
1225       
1226     case DBUS_TYPE_BOOLEAN:
1227       {
1228         unsigned char c;
1229
1230         if (1 > _dbus_string_get_length (str) - pos)
1231           {
1232             _dbus_verbose ("no room for boolean value\n");
1233             return FALSE;
1234           }
1235         
1236         c = _dbus_string_get_byte (str, pos);
1237
1238         if (c != 0 && c != 1)
1239           {
1240             _dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
1241             return FALSE;
1242           }
1243         
1244       *end_pos = pos + 1;
1245       break;
1246       }
1247     case DBUS_TYPE_INT32:
1248     case DBUS_TYPE_UINT32:
1249       {
1250         int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
1251         
1252         if (!_dbus_string_validate_nul (str, pos,
1253                                         align_4 - pos))
1254           {
1255             _dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
1256             return FALSE;
1257           }
1258
1259         *end_pos = align_4 + 4;
1260       }
1261       break;
1262
1263     case DBUS_TYPE_DOUBLE:
1264       {
1265         int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
1266
1267         _dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
1268         
1269         if (!_dbus_string_validate_nul (str, pos,
1270                                         align_8 - pos))
1271           {
1272             _dbus_verbose ("double alignment padding not initialized to nul\n");
1273             return FALSE;
1274           }
1275
1276         *end_pos = align_8 + 8;
1277       }
1278       break;
1279
1280     case DBUS_TYPE_STRING:
1281       {
1282         int len;
1283
1284         /* Demarshal the length, which does NOT include
1285          * nul termination
1286          */
1287         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1288         if (len < 0)
1289           return FALSE;
1290
1291         if (!validate_string (str, pos, len, end_pos))
1292           return FALSE;
1293       }
1294       break;
1295
1296     case DBUS_TYPE_NAMED:
1297       {
1298         int len;
1299
1300         /* Demarshal the string length, which does NOT include
1301          * nul termination
1302          */
1303         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1304         if (len < 0)
1305           return FALSE;
1306
1307         if (!validate_string (str, pos, len, &pos))
1308           return FALSE;
1309
1310         /* Validate data */
1311         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1312         if (len < 0)
1313           return FALSE;
1314
1315         *end_pos = pos + len;
1316       }
1317       break;
1318       
1319     case DBUS_TYPE_ARRAY:
1320       {
1321         int len;
1322         int end;
1323         int array_type;
1324
1325         if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
1326           {
1327             _dbus_verbose ("invalid array type\n");
1328             return FALSE;
1329           }
1330         
1331         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1332         if (len < 0)
1333           return FALSE;
1334
1335         if (len > _dbus_string_get_length (str) - pos)
1336           {
1337             _dbus_verbose ("array length outside length of the message\n");
1338             return FALSE;
1339           }
1340         
1341         end = pos + len;
1342         
1343         while (pos < end)
1344           {
1345             if (!_dbus_marshal_validate_arg (str, byte_order,
1346                                              array_type, pos, &pos))
1347               return FALSE;
1348           }
1349         
1350         if (pos > end)
1351           {
1352             _dbus_verbose ("array contents exceeds array length\n");
1353             return FALSE;
1354           }
1355
1356         *end_pos = pos;
1357       }
1358       break;
1359
1360       case DBUS_TYPE_DICT:
1361       {
1362         int dict_type;
1363         int len;
1364         int end;
1365         
1366         len = demarshal_and_validate_len (str, byte_order, pos, &pos);
1367         if (len < 0)
1368           return FALSE;
1369
1370         if (len > _dbus_string_get_length (str) - pos)
1371           {
1372             _dbus_verbose ("dict length outside length of the message\n");
1373             return FALSE;
1374           }
1375         
1376         end = pos + len;
1377         
1378         while (pos < end)
1379           {
1380             /* Validate name */
1381             if (!_dbus_marshal_validate_arg (str, byte_order,
1382                                              DBUS_TYPE_STRING, pos, &pos))
1383               return FALSE;
1384             
1385             if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
1386               {
1387                 _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
1388                 return FALSE;
1389               }
1390             
1391             /* Validate element */
1392             if (!_dbus_marshal_validate_arg (str, byte_order,
1393                                              dict_type, pos, &pos))
1394               return FALSE;
1395           }
1396         
1397         if (pos > end)
1398           {
1399             _dbus_verbose ("dict contents exceeds array length\n");
1400             return FALSE;
1401           }
1402         *end_pos = pos;
1403       }
1404       break;
1405       
1406     default:
1407       _dbus_verbose ("Unknown message arg type %d\n", type);
1408       return FALSE;
1409     }
1410
1411   if (*end_pos > _dbus_string_get_length (str))
1412     return FALSE;
1413   
1414   return TRUE;
1415 }
1416
1417
1418 /**
1419  * If in verbose mode, print a block of binary data.
1420  *
1421  * @todo right now it prints even if not in verbose mode
1422  * 
1423  * @param data the data
1424  * @param len the length of the data
1425  */
1426 void
1427 _dbus_verbose_bytes (const unsigned char *data,
1428                      int                  len)
1429 {
1430   int i;
1431   const unsigned char *aligned;
1432
1433   _dbus_assert (len >= 0);
1434   
1435   /* Print blanks on first row if appropriate */
1436   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1437   if (aligned > data)
1438     aligned -= 4;
1439   _dbus_assert (aligned <= data);
1440
1441   if (aligned != data)
1442     {
1443       _dbus_verbose ("%4d\t%p: ", - (data - aligned), aligned); 
1444       while (aligned != data)
1445         {
1446           _dbus_verbose ("    ");
1447           ++aligned;
1448         }
1449     }
1450
1451   /* now print the bytes */
1452   i = 0;
1453   while (i < len)
1454     {
1455       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1456         {
1457           _dbus_verbose ("%4d\t%p: ",
1458                    i, &data[i]);
1459         }
1460       
1461       if (data[i] >= 32 &&
1462           data[i] <= 126)
1463         _dbus_verbose (" '%c' ", data[i]);
1464       else
1465         _dbus_verbose ("0x%s%x ",
1466                  data[i] <= 0xf ? "0" : "", data[i]);
1467
1468       ++i;
1469
1470       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1471         {
1472           if (i > 3)
1473             _dbus_verbose ("BE: %d LE: %d",
1474                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
1475                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
1476
1477           if (i > 7 && 
1478               _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1479             {
1480               _dbus_verbose (" dbl: %g",
1481                              *(double*)&data[i-8]);
1482             }
1483           
1484           _dbus_verbose ("\n");
1485         }
1486     }
1487
1488   _dbus_verbose ("\n");
1489 }
1490
1491 /**
1492  * Dump the given part of the string to verbose log.
1493  *
1494  * @param str the string
1495  * @param start the start of range to dump
1496  * @param len length of range
1497  */
1498 void
1499 _dbus_verbose_bytes_of_string (const DBusString    *str,
1500                                int                  start,
1501                                int                  len)
1502 {
1503   const char *d;
1504   int real_len;
1505
1506   real_len = _dbus_string_get_length (str);
1507
1508   _dbus_assert (start >= 0);
1509   
1510   if (start > real_len)
1511     {
1512       _dbus_verbose ("  [%d,%d) is not inside string of length %d\n",
1513                      start, len, real_len);
1514       return;
1515     }
1516
1517   if ((start + len) > real_len)
1518     {
1519       _dbus_verbose ("  [%d,%d) extends outside string of length %d\n",
1520                      start, len, real_len);
1521       len = real_len - start;
1522     }
1523   
1524   d = _dbus_string_get_const_data_len (str, start, len);
1525
1526   _dbus_verbose_bytes (d, len);
1527 }
1528
1529 /** @} */
1530
1531 #ifdef DBUS_BUILD_TESTS
1532 #include "dbus-test.h"
1533 #include <stdio.h>
1534
1535 dbus_bool_t
1536 _dbus_marshal_test (void)
1537 {
1538   DBusString str;
1539   char *tmp1, *tmp2;
1540   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
1541   int pos = 0, len;
1542   
1543   if (!_dbus_string_init (&str))
1544     _dbus_assert_not_reached ("failed to init string");
1545
1546   /* Marshal doubles */
1547   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
1548     _dbus_assert_not_reached ("could not marshal double value");
1549   if (!_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14)
1550     _dbus_assert_not_reached ("demarshal failed");
1551
1552   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
1553     _dbus_assert_not_reached ("could not marshal double value");
1554   if (!_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14)
1555     _dbus_assert_not_reached ("demarshal failed");
1556   
1557   /* Marshal signed integers */
1558   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1559     _dbus_assert_not_reached ("could not marshal signed integer value");
1560   if (!_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678)
1561     _dbus_assert_not_reached ("demarshal failed");
1562
1563   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1564     _dbus_assert_not_reached ("could not marshal signed integer value");
1565   if (!_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678)
1566     _dbus_assert_not_reached ("demarshal failed");
1567   
1568   /* Marshal unsigned integers */
1569   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1570     _dbus_assert_not_reached ("could not marshal signed integer value");
1571   if (!_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678)
1572     _dbus_assert_not_reached ("demarshal failed");
1573   
1574   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1575     _dbus_assert_not_reached ("could not marshal signed integer value");
1576   if (!_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678)
1577     _dbus_assert_not_reached ("demarshal failed");
1578
1579   /* Marshal strings */
1580   tmp1 = "This is the dbus test string";
1581   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1582     _dbus_assert_not_reached ("could not marshal string");
1583   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1584   if (!strcmp (tmp1, tmp2) == 0)
1585     _dbus_assert_not_reached ("demarshal failed");
1586   dbus_free (tmp2);
1587
1588   tmp1 = "This is the dbus test string";
1589   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1590     _dbus_assert_not_reached ("could not marshal string");
1591   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1592   if (!strcmp (tmp1, tmp2) == 0)
1593     _dbus_assert_not_reached ("demarshal failed");
1594   dbus_free (tmp2);
1595
1596   /* Marshal signed integer arrays */
1597   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1598     _dbus_assert_not_reached ("could not marshal integer array");
1599   if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
1600     _dbus_assert_not_reached ("could not demarshal integer array");
1601
1602   if (len != 3)
1603     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1604   dbus_free (array2);
1605   
1606   _dbus_string_free (&str);
1607   
1608       
1609   return TRUE;
1610 }
1611
1612 #endif /* DBUS_BUILD_TESTS */