2003-01-21 Anders Carlsson <andersca@codefactory.se>
[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
27 #include <string.h>
28
29 /* from ORBit */
30 static void
31 swap_bytes (unsigned char *data,
32             unsigned int   len)
33 {
34   unsigned char *p1 = data;
35   unsigned char *p2 = data + len - 1;
36
37   while (p1 < p2)
38     {
39       unsigned char tmp = *p1;
40       *p1 = *p2;
41       *p2 = tmp;
42
43       --p2;
44       ++p1;
45     }
46 }
47
48 /**
49  * @defgroup DBusMarshal marshaling and unmarshaling
50  * @ingroup  DBusInternals
51  * @brief functions to marshal/unmarshal data from the wire
52  *
53  * Types and functions related to converting primitive data types from
54  * wire format to native machine format, and vice versa.
55  *
56  * @{
57  */
58
59 /**
60  * Unpacks a 32 bit unsigned integer from a data pointer
61  *
62  * @param byte_order The byte order to use
63  * @param data the data pointer
64  * @returns the integer
65  */
66 dbus_uint32_t
67 _dbus_unpack_uint32 (int                  byte_order,
68                      const unsigned char *data)
69 {
70   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
71   
72   if (byte_order == DBUS_LITTLE_ENDIAN)
73     return DBUS_UINT32_FROM_LE (*(dbus_uint32_t*)data);
74   else
75     return DBUS_UINT32_FROM_BE (*(dbus_uint32_t*)data);
76 }             
77
78 /**
79  * Unpacks a 32 bit signed integer from a data pointer
80  *
81  * @param byte_order The byte order to use
82  * @param data the data pointer
83  * @returns the integer
84  */
85 dbus_int32_t
86 _dbus_unpack_int32 (int                  byte_order,
87                     const unsigned char *data)
88 {
89   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
90   
91   if (byte_order == DBUS_LITTLE_ENDIAN)
92     return DBUS_INT32_FROM_LE (*(dbus_int32_t*)data);
93   else
94     return DBUS_INT32_FROM_BE (*(dbus_int32_t*)data);
95 }
96
97 /**
98  * Packs a 32 bit unsigned integer into a data pointer.
99  *
100  * @param value the value
101  * @param byte_order the byte order to use
102  * @param data the data pointer
103  */
104 void
105 _dbus_pack_uint32 (dbus_uint32_t   value,
106                    int             byte_order,
107                    unsigned char  *data)
108 {
109   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
110   
111   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
112     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);       
113   else
114     *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
115 }
116
117 /**
118  * Packs a 32 bit signed integer into a data pointer.
119  *
120  * @param value the value
121  * @param byte_order the byte order to use
122  * @param data the data pointer
123  */
124 void
125 _dbus_pack_int32 (dbus_int32_t   value,
126                   int            byte_order,
127                   unsigned char *data)
128 {
129   _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
130   
131   if ((byte_order) == DBUS_LITTLE_ENDIAN)                  
132     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_LE (value);       
133   else
134     *((dbus_int32_t*)(data)) = DBUS_INT32_TO_BE (value);
135 }
136
137 /**
138  * Marshals a double value.
139  *
140  * @param str the string to append the marshalled value to
141  * @param byte_order the byte order to use
142  * @param value the value
143  * @returns #TRUE on success
144  */
145 dbus_bool_t
146 _dbus_marshal_double (DBusString *str,
147                       int         byte_order,
148                       double      value)
149 {
150   _dbus_assert (sizeof (double) == 8);
151
152   if (!_dbus_string_align_length (str, sizeof (double)))
153     return FALSE;
154   
155   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
156     swap_bytes ((unsigned char *)&value, sizeof (double));
157
158   return _dbus_string_append_len (str, (const char *)&value, sizeof (double));
159 }
160
161 /**
162  * Marshals a 32 bit signed integer value.
163  *
164  * @param str the string to append the marshalled value to
165  * @param byte_order the byte order to use
166  * @param value the value
167  * @returns #TRUE on success
168  */
169 dbus_bool_t
170 _dbus_marshal_int32  (DBusString   *str,
171                       int           byte_order,
172                       dbus_int32_t  value)
173 {
174   if (!_dbus_string_align_length (str, sizeof (dbus_int32_t)))
175     return FALSE;
176   
177   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
178     swap_bytes ((unsigned char *)&value, sizeof (dbus_int32_t));
179
180   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_int32_t));
181 }
182
183 /**
184  * Marshals a 32 bit unsigned integer value.
185  *
186  * @param str the string to append the marshalled value to
187  * @param byte_order the byte order to use
188  * @param value the value
189  * @returns #TRUE on success
190  */
191 dbus_bool_t
192 _dbus_marshal_uint32 (DBusString    *str,
193                       int            byte_order,
194                       dbus_uint32_t  value)
195 {
196   if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
197     return FALSE;
198   
199   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
200     swap_bytes ((unsigned char *)&value, sizeof (dbus_uint32_t));
201
202   return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
203 }
204
205 /**
206  * Marshals a UTF-8 string
207  *
208  * @param str the string to append the marshalled value to
209  * @param byte_order the byte order to use
210  * @param value the string
211  * @returns #TRUE on success
212  */
213 dbus_bool_t
214 _dbus_marshal_string (DBusString    *str,
215                       int            byte_order,
216                       const char    *value)
217 {
218   int len, old_string_len;
219
220   old_string_len = _dbus_string_get_length (str);
221   
222   len = strlen (value);
223
224   if (!_dbus_marshal_uint32 (str, byte_order, len))
225     {
226       /* Restore the previous length */
227       _dbus_string_set_length (str, old_string_len);
228
229       return FALSE;
230     }
231
232   return _dbus_string_append_len (str, value, len + 1);
233 }
234
235 /**
236  * Marshals a byte array
237  *
238  * @param str the string to append the marshalled value to
239  * @param byte_order the byte order to use
240  * @param value the array
241  * @param len number of elements in the array
242  * @returns #TRUE on success
243  */
244 dbus_bool_t
245 _dbus_marshal_byte_array (DBusString          *str,
246                           int                  byte_order,
247                           const unsigned char *value,
248                           int                  len)
249 {
250   int old_string_len;
251
252   old_string_len = _dbus_string_get_length (str);
253   
254   if (!_dbus_marshal_uint32 (str, byte_order, len))
255     {
256       /* Restore the previous length */
257       _dbus_string_set_length (str, old_string_len);
258
259       return FALSE;
260     }
261
262   return _dbus_string_append_len (str, value, len);
263 }
264
265 /**
266  * Marshals a 32 bit signed integer array
267  *
268  * @param str the string to append the marshalled value to
269  * @param byte_order the byte order to use
270  * @param value the array
271  * @param len the length of the array
272  * @returns #TRUE on success
273  */
274 dbus_bool_t
275 _dbus_marshal_int32_array (DBusString         *str,
276                            int                 byte_order,
277                            const dbus_int32_t *value,
278                            int                 len)
279 {
280   int i, old_string_len;
281
282   old_string_len = _dbus_string_get_length (str);
283
284   if (!_dbus_marshal_uint32 (str, byte_order, len))
285     goto error;
286
287   for (i = 0; i < len; i++)
288     if (!_dbus_marshal_int32 (str, byte_order, value[i]))
289       goto error;
290
291   return TRUE;
292   
293  error:
294   /* Restore previous length */
295   _dbus_string_set_length (str, old_string_len);
296   
297   return FALSE;
298 }
299
300 /**
301  * Marshals a 32 bit unsigned integer array
302  *
303  * @param str the string to append the marshalled value to
304  * @param byte_order the byte order to use
305  * @param value the array
306  * @param len the length of the array
307  * @returns #TRUE on success
308  */
309 dbus_bool_t
310 _dbus_marshal_uint32_array (DBusString          *str,
311                             int                  byte_order,
312                             const dbus_uint32_t  *value,
313                             int                  len)
314 {
315   int i, old_string_len;
316
317   old_string_len = _dbus_string_get_length (str);
318
319   if (!_dbus_marshal_uint32 (str, byte_order, len))
320     goto error;
321
322   for (i = 0; i < len; i++)
323     if (!_dbus_marshal_uint32 (str, byte_order, value[i]))
324       goto error;
325
326   return TRUE;
327   
328  error:
329   /* Restore previous length */
330   _dbus_string_set_length (str, old_string_len);
331   
332   return FALSE;  
333 }
334
335 /**
336  * Marshals a double array
337  *
338  * @param str the string to append the marshalled value to
339  * @param byte_order the byte order to use
340  * @param value the array
341  * @param len the length of the array
342  * @returns #TRUE on success
343  */
344 dbus_bool_t
345 _dbus_marshal_double_array (DBusString          *str,
346                             int                  byte_order,
347                             const double        *value,
348                             int                  len)
349 {
350   int i, old_string_len;
351
352   old_string_len = _dbus_string_get_length (str);
353
354   if (!_dbus_marshal_uint32 (str, byte_order, len))
355     goto error;
356
357   for (i = 0; i < len; i++)
358     if (!_dbus_marshal_double (str, byte_order, value[i]))
359       goto error;
360
361   return TRUE;
362   
363  error:
364   /* Restore previous length */
365   _dbus_string_set_length (str, old_string_len);
366   
367   return FALSE;    
368 }
369
370 /**
371  * Marshals a string array
372  *
373  * @param str the string to append the marshalled value to
374  * @param byte_order the byte order to use
375  * @param value the array
376  * @param len the length of the array
377  * @returns #TRUE on success
378  */
379 dbus_bool_t
380 _dbus_marshal_string_array (DBusString  *str,
381                             int          byte_order,
382                             const char **value,
383                             int          len)
384 {
385   int i, old_string_len;
386
387   old_string_len = _dbus_string_get_length (str);
388
389   if (!_dbus_marshal_uint32 (str, byte_order, len))
390     goto error;
391
392   for (i = 0; i < len; i++)
393     if (!_dbus_marshal_string (str, byte_order, value[i]))
394       goto error;
395
396   return TRUE;
397   
398  error:
399   /* Restore previous length */
400   _dbus_string_set_length (str, old_string_len);
401   
402   return FALSE;      
403 }
404
405 /**
406  * Demarshals a double.
407  *
408  * @param str the string containing the data
409  * @param byte_order the byte order
410  * @param pos the position in the string
411  * @param new_pos the new position of the string
412  * @returns the demarshaled double.
413  */
414 double
415 _dbus_demarshal_double (DBusString  *str,
416                         int          byte_order,
417                         int          pos,
418                         int         *new_pos)
419 {
420   double retval;
421   const char *buffer;
422
423   pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
424
425   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
426
427   retval = *(double *)buffer;
428   
429   if (byte_order != DBUS_COMPILER_BYTE_ORDER)
430     swap_bytes ((unsigned char *)&retval, sizeof (double));
431
432   if (new_pos)
433     *new_pos = pos + sizeof (double);
434   
435   return retval;  
436 }
437
438 /**
439  * Demarshals a 32 bit signed integer.
440  *
441  * @param str the string containing the data
442  * @param byte_order the byte order
443  * @param pos the position in the string
444  * @param new_pos the new position of the string
445  * @returns the demarshaled integer.
446  */
447 dbus_int32_t
448 _dbus_demarshal_int32  (DBusString *str,
449                         int         byte_order,
450                         int         pos,
451                         int        *new_pos)
452 {
453   const char *buffer;
454
455   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t));
456   
457   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_int32_t));
458
459   if (new_pos)
460     *new_pos = pos + sizeof (dbus_int32_t);
461
462   return _dbus_unpack_int32 (byte_order, buffer);
463 }
464
465 /**
466  * Demarshals a 32 bit unsigned integer.
467  *
468  * @param str the string containing the data
469  * @param byte_order the byte order
470  * @param pos the position in the string
471  * @param new_pos the new position of the string
472  * @returns the demarshaled integer.
473  */
474 dbus_uint32_t
475 _dbus_demarshal_uint32  (DBusString *str,
476                          int         byte_order,
477                          int         pos,
478                          int        *new_pos)
479 {
480   const char *buffer;
481
482   pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
483   
484   _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (dbus_uint32_t));
485
486   if (new_pos)
487     *new_pos = pos + sizeof (dbus_uint32_t);
488
489   return _dbus_unpack_uint32 (byte_order, buffer);
490 }
491
492 /**
493  * Demarshals an UTF-8 string.
494  *
495  * @todo Should we check the string to make sure
496  * that it's  valid UTF-8, and maybe "fix" the string
497  * if it's broken?
498  *
499  * @todo Should probably demarshal to a DBusString,
500  * having memcpy() in here is Evil(tm).
501  *
502  * @param str the string containing the data
503  * @param byte_order the byte order
504  * @param pos the position in the string
505  * @param new_pos the new position of the string
506  * @returns the demarshaled string.
507  */
508 char *
509 _dbus_demarshal_string (DBusString *str,
510                         int         byte_order,
511                         int         pos,
512                         int        *new_pos)
513 {
514   int len;
515   char *retval;
516   const char *data;
517
518   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
519
520   retval = dbus_malloc (len + 1);
521
522   if (!retval)
523     return NULL;
524
525   _dbus_string_get_const_data_len (str, &data, pos, len);
526
527   if (!data)
528     return NULL;
529
530   memcpy (retval, data, len + 1);
531
532   if (new_pos)
533     *new_pos = pos + len + 1;
534   
535   return retval;
536 }
537
538 /**
539  * Demarshals a byte array.
540  *
541  * @todo Should probably demarshal to a DBusString,
542  * having memcpy() in here is Evil(tm).
543  *
544  * @param str the string containing the data
545  * @param byte_order the byte order
546  * @param pos the position in the string
547  * @param new_pos the new position of the string
548  * @param array_len length of the demarshaled data
549  * @returns the demarshaled data.
550  */
551 unsigned char *
552 _dbus_demarshal_byte_array (DBusString *str,
553                             int         byte_order,
554                             int         pos,
555                             int        *new_pos,
556                             int        *array_len)
557 {
558   int len;
559   unsigned char *retval;
560   const char *data;
561
562   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
563
564   retval = dbus_malloc (len);
565
566   if (!retval)
567     return NULL;
568
569   _dbus_string_get_const_data_len (str, &data, pos, len);
570
571   if (!data)
572     return NULL;
573
574   memcpy (retval, data, len);
575
576   if (new_pos)
577     *new_pos = pos + len;
578
579   if (array_len)
580     *array_len = len;
581
582   return retval;
583 }
584
585 /**
586  * Demarshals a 32 bit signed integer array.
587  *
588  * @param str the string containing the data
589  * @param byte_order the byte order
590  * @param pos the position in the string
591  * @param new_pos the new position of the string
592  * @param array_len length of the demarshaled data
593  * @returns the demarshaled data.
594  */
595 dbus_int32_t *
596 _dbus_demarshal_int32_array (DBusString *str,
597                              int         byte_order,
598                              int         pos,
599                              int        *new_pos,
600                              int        *array_len)
601 {
602   int len, i;
603   dbus_int32_t *retval;
604   
605   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
606
607   retval = dbus_new (dbus_int32_t, len);
608
609   if (!retval)
610     return NULL;
611
612   for (i = 0; i < len; i++)
613     retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
614
615   if (new_pos)
616     *new_pos = pos;
617
618   if (array_len)
619     *array_len = len;
620   
621   return retval;
622 }
623
624 /**
625  * Demarshals a 32 bit unsigned integer array.
626  *
627  * @param str the string containing the data
628  * @param byte_order the byte order
629  * @param pos the position in the string
630  * @param new_pos the new position of the string
631  * @param array_len length of the demarshaled data
632  * @returns the demarshaled data.
633  */
634 dbus_uint32_t *
635 _dbus_demarshal_uint32_array (DBusString *str,
636                               int         byte_order,
637                               int         pos,
638                               int        *new_pos,
639                               int        *array_len)
640 {
641   int len, i;
642   dbus_uint32_t *retval;
643   
644   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
645
646   retval = dbus_new (dbus_uint32_t, len);
647
648   if (!retval)
649     return NULL;
650
651   for (i = 0; i < len; i++)
652     retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
653
654   if (new_pos)
655     *new_pos = pos;
656
657   if (array_len)
658     *array_len = len;
659   
660   return retval;  
661 }
662
663 /**
664  * Demarshals a double array.
665  *
666  * @param str the string containing the data
667  * @param byte_order the byte order
668  * @param pos the position in the string
669  * @param new_pos the new position of the string
670  * @param array_len length of the demarshaled data
671  * @returns the demarshaled data.
672  */
673 double *
674 _dbus_demarshal_double_array (DBusString *str,
675                               int         byte_order,
676                               int         pos,
677                               int        *new_pos,
678                               int        *array_len)
679 {
680   int len, i;
681   double *retval;
682   
683   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
684
685   retval = dbus_new (double, len);
686
687   if (!retval)
688     return NULL;
689
690   for (i = 0; i < len; i++)
691     retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
692
693   if (new_pos)
694     *new_pos = pos;
695
696   if (array_len)
697     *array_len = len;
698   
699   return retval;  
700 }
701
702 /**
703  * Demarshals a string array.
704  *
705  * @param str the string containing the data
706  * @param byte_order the byte order
707  * @param pos the position in the string
708  * @param new_pos the new position of the string
709  * @param array_len length of the demarshaled data
710  * @returns the demarshaled data.
711  */
712 char **
713 _dbus_demarshal_string_array (DBusString *str,
714                               int         byte_order,
715                               int         pos,
716                               int        *new_pos,
717                               int        *array_len)
718 {
719   int len, i, j;
720   char **retval;
721   
722   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
723   
724   retval = dbus_new (char *, len);
725
726   if (!retval)
727     return NULL;
728
729   for (i = 0; i < len; i++)
730     {
731       retval[i] = _dbus_demarshal_string (str, byte_order, pos, &pos);
732
733       if (retval[i] == 0)
734         goto error;
735     }
736
737   return retval;
738
739  error:
740   for (j = 0; j < i; j++)
741     dbus_free (retval[i]);
742   dbus_free (retval);
743
744   return NULL;
745 }
746
747 /** 
748  * Returns the position right after the end position 
749  * end position of a field
750  *
751  * @todo warns on invalid type in a message, but
752  * probably the whole message needs to be dumped,
753  * or we might even drop the connection due
754  * to bad protocol. Needs better error handling.
755  * Possible security issue.
756  *
757  * @param str a string
758  * @param byte_order the byte order to use
759  * @param pos the pos where the field starts
760  * @param end_pos pointer where the position right
761  * after the end position will follow
762  * @returns TRUE if more data exists after the field
763  */
764 dbus_bool_t
765 _dbus_marshal_get_field_end_pos (DBusString *str,
766                                  int         byte_order,
767                                  int         pos,
768                                  int        *end_pos)
769 {
770   const char *data;
771
772   if (pos >= _dbus_string_get_length (str))
773     return FALSE;
774
775   _dbus_string_get_const_data_len (str, &data, pos, 1);
776   
777   switch (*data)
778     {
779     case DBUS_TYPE_INVALID:
780       return FALSE;
781       break;
782
783     case DBUS_TYPE_INT32:
784       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
785
786       break;
787
788     case DBUS_TYPE_UINT32:
789       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
790
791       break;
792
793     case DBUS_TYPE_DOUBLE:
794       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
795
796       break;
797
798     case DBUS_TYPE_STRING:
799       {
800         int len;
801
802         /* Demarshal the length */
803         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
804
805         *end_pos = pos + len + 1;
806
807         break;
808       }
809
810     case DBUS_TYPE_BYTE_ARRAY:
811       {
812         int len;
813
814         /* Demarshal the length */
815         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
816         
817         *end_pos = pos + len;
818
819         break;
820       }
821
822     case DBUS_TYPE_INT32_ARRAY:
823       {
824         int len, new_pos;
825
826         /* Demarshal the length */
827         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
828         
829         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
830           + (len * sizeof (dbus_int32_t));
831
832         break;
833       }
834
835     case DBUS_TYPE_UINT32_ARRAY:
836       {
837         int len, new_pos;
838
839         /* Demarshal the length */
840         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
841
842         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
843           + (len * sizeof (dbus_uint32_t));
844         
845         break;
846       }
847
848     case DBUS_TYPE_DOUBLE_ARRAY:
849       {
850         int len, new_pos;
851         
852         /* Demarshal the length */
853         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
854
855         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
856           + (len * sizeof (double));
857         
858         break;
859       }
860       
861     case DBUS_TYPE_STRING_ARRAY:
862       {
863         int len, i;
864         
865         /* Demarshal the length */
866         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
867
868         for (i = 0; i < len; i++)
869           {
870             int str_len;
871             
872             /* Demarshal string length */
873             str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
874             pos += str_len + 1;
875           }
876
877         *end_pos = pos;
878         break;
879       }      
880     default:
881       _dbus_warn ("Unknown message field type %d\n", *data);
882       return FALSE;
883     }
884
885   if (*end_pos >= _dbus_string_get_length (str))
886     return FALSE;
887   
888   return TRUE;
889 }
890
891 /**
892  * If in verbose mode, print a block of binary data.
893  *
894  * @todo right now it prints even if not in verbose mode
895  * 
896  * @param data the data
897  * @param len the length of the data
898  */
899 void
900 _dbus_verbose_bytes (const unsigned char *data,
901                      int                  len)
902 {
903   int i;
904   const unsigned char *aligned;
905
906   /* Print blanks on first row if appropriate */
907   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
908   if (aligned > data)
909     aligned -= 4;
910   _dbus_assert (aligned <= data);
911
912   if (aligned != data)
913     {
914       _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned); 
915       while (aligned != data)
916         {
917           _dbus_verbose ("    ");
918           ++aligned;
919         }
920     }
921
922   /* now print the bytes */
923   i = 0;
924   while (i < len)
925     {
926       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
927         {
928           _dbus_verbose ("%5d\t%p: ",
929                    i, &data[i]);
930         }
931       
932       if (data[i] >= 32 &&
933           data[i] <= 126)
934         _dbus_verbose (" '%c' ", data[i]);
935       else
936         _dbus_verbose ("0x%s%x ",
937                  data[i] <= 0xf ? "0" : "", data[i]);
938
939       ++i;
940
941       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
942         {
943           if (i > 3)
944             _dbus_verbose ("big: %d little: %d",
945                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
946                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
947           
948           _dbus_verbose ("\n");
949         }
950     }
951
952   _dbus_verbose ("\n");
953 }
954
955 /**
956  * Dump the given part of the string to verbose log.
957  *
958  * @param str the string
959  * @param start the start of range to dump
960  * @param len length of range
961  */
962 void
963 _dbus_verbose_bytes_of_string (const DBusString    *str,
964                                int                  start,
965                                int                  len)
966 {
967   const char *d;
968
969   _dbus_string_get_const_data_len (str, &d, start, len);
970
971   _dbus_verbose_bytes (d, len);
972 }
973
974 /** @} */
975
976 #ifdef DBUS_BUILD_TESTS
977 #include "dbus-test.h"
978 #include <stdio.h>
979
980 dbus_bool_t
981 _dbus_marshal_test (void)
982 {
983   DBusString str;
984   char *tmp1, *tmp2;
985   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
986   int pos = 0, len;
987   
988   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
989     _dbus_assert_not_reached ("failed to init string");
990
991   /* Marshal doubles */
992   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
993     _dbus_assert_not_reached ("could not marshal double value");
994   _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
995
996   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
997     _dbus_assert_not_reached ("could not marshal double value");
998   _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
999   
1000   /* Marshal signed integers */
1001   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1002     _dbus_assert_not_reached ("could not marshal signed integer value");
1003   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
1004
1005   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1006     _dbus_assert_not_reached ("could not marshal signed integer value");
1007   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
1008   
1009   /* Marshal unsigned integers */
1010   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1011     _dbus_assert_not_reached ("could not marshal signed integer value");
1012   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
1013   
1014   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1015     _dbus_assert_not_reached ("could not marshal signed integer value");
1016   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
1017
1018   /* Marshal strings */
1019   tmp1 = "This is the dbus test string";
1020   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1021     _dbus_assert_not_reached ("could not marshal string");
1022   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1023   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1024   dbus_free (tmp2);
1025
1026   tmp1 = "This is the dbus test string";
1027   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1028     _dbus_assert_not_reached ("could not marshal string");
1029   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1030   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1031   dbus_free (tmp2);
1032
1033   /* Marshal signed integer arrays */
1034   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1035     _dbus_assert_not_reached ("could not marshal integer array");
1036   _dbus_verbose_bytes_of_string (&str, 0, _dbus_string_get_length (&str));
1037   array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
1038   printf ("length is: %d\n", len);
1039   if (len != 3)
1040     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1041
1042   
1043
1044
1045   _dbus_string_free (&str);
1046   
1047       
1048   return TRUE;
1049 }
1050
1051 #endif /* DBUS_BUILD_TESTS */