2003-01-25 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  if (new_pos)
738     *new_pos = pos;
739
740   if (array_len)
741     *array_len = len;
742   
743   return retval;
744
745  error:
746   for (j = 0; j < i; j++)
747     dbus_free (retval[i]);
748   dbus_free (retval);
749
750   return NULL;
751 }
752
753 /** 
754  * Returns the position right after the end position 
755  * end position of a field
756  *
757  * @todo warns on invalid type in a message, but
758  * probably the whole message needs to be dumped,
759  * or we might even drop the connection due
760  * to bad protocol. Needs better error handling.
761  * Possible security issue.
762  *
763  * @param str a string
764  * @param byte_order the byte order to use
765  * @param pos the pos where the field starts
766  * @param end_pos pointer where the position right
767  * after the end position will follow
768  * @returns TRUE if more data exists after the field
769  */
770 dbus_bool_t
771 _dbus_marshal_get_field_end_pos (DBusString *str,
772                                  int         byte_order,
773                                  int         pos,
774                                  int        *end_pos)
775 {
776   const char *data;
777
778   if (pos >= _dbus_string_get_length (str))
779     return FALSE;
780
781   _dbus_string_get_const_data_len (str, &data, pos, 1);
782   
783   switch (*data)
784     {
785     case DBUS_TYPE_INVALID:
786       return FALSE;
787       break;
788
789     case DBUS_TYPE_INT32:
790       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
791
792       break;
793
794     case DBUS_TYPE_UINT32:
795       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
796
797       break;
798
799     case DBUS_TYPE_DOUBLE:
800       *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
801
802       break;
803
804     case DBUS_TYPE_STRING:
805       {
806         int len;
807
808         /* Demarshal the length */
809         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
810
811         *end_pos = pos + len + 1;
812
813         break;
814       }
815
816     case DBUS_TYPE_BYTE_ARRAY:
817       {
818         int len;
819
820         /* Demarshal the length */
821         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
822         
823         *end_pos = pos + len;
824
825         break;
826       }
827
828     case DBUS_TYPE_INT32_ARRAY:
829       {
830         int len, new_pos;
831
832         /* Demarshal the length */
833         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
834         
835         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
836           + (len * sizeof (dbus_int32_t));
837
838         break;
839       }
840
841     case DBUS_TYPE_UINT32_ARRAY:
842       {
843         int len, new_pos;
844
845         /* Demarshal the length */
846         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
847
848         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
849           + (len * sizeof (dbus_uint32_t));
850         
851         break;
852       }
853
854     case DBUS_TYPE_DOUBLE_ARRAY:
855       {
856         int len, new_pos;
857         
858         /* Demarshal the length */
859         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
860
861         *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
862           + (len * sizeof (double));
863         
864         break;
865       }
866       
867     case DBUS_TYPE_STRING_ARRAY:
868       {
869         int len, i;
870         
871         /* Demarshal the length */
872         len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
873
874         for (i = 0; i < len; i++)
875           {
876             int str_len;
877             
878             /* Demarshal string length */
879             str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
880             pos += str_len + 1;
881           }
882
883         *end_pos = pos;
884         break;
885       }      
886     default:
887       _dbus_warn ("Unknown message field type %d\n", *data);
888       return FALSE;
889     }
890
891   if (*end_pos >= _dbus_string_get_length (str))
892     return FALSE;
893   
894   return TRUE;
895 }
896
897 /**
898  * If in verbose mode, print a block of binary data.
899  *
900  * @todo right now it prints even if not in verbose mode
901  * 
902  * @param data the data
903  * @param len the length of the data
904  */
905 void
906 _dbus_verbose_bytes (const unsigned char *data,
907                      int                  len)
908 {
909   int i;
910   const unsigned char *aligned;
911
912   /* Print blanks on first row if appropriate */
913   aligned = _DBUS_ALIGN_ADDRESS (data, 4);
914   if (aligned > data)
915     aligned -= 4;
916   _dbus_assert (aligned <= data);
917
918   if (aligned != data)
919     {
920       _dbus_verbose ("%5d\t%p: ", - (data - aligned), aligned); 
921       while (aligned != data)
922         {
923           _dbus_verbose ("    ");
924           ++aligned;
925         }
926     }
927
928   /* now print the bytes */
929   i = 0;
930   while (i < len)
931     {
932       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
933         {
934           _dbus_verbose ("%5d\t%p: ",
935                    i, &data[i]);
936         }
937       
938       if (data[i] >= 32 &&
939           data[i] <= 126)
940         _dbus_verbose (" '%c' ", data[i]);
941       else
942         _dbus_verbose ("0x%s%x ",
943                  data[i] <= 0xf ? "0" : "", data[i]);
944
945       ++i;
946
947       if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
948         {
949           if (i > 3)
950             _dbus_verbose ("big: %d little: %d",
951                            _dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
952                            _dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
953           
954           _dbus_verbose ("\n");
955         }
956     }
957
958   _dbus_verbose ("\n");
959 }
960
961 /**
962  * Dump the given part of the string to verbose log.
963  *
964  * @param str the string
965  * @param start the start of range to dump
966  * @param len length of range
967  */
968 void
969 _dbus_verbose_bytes_of_string (const DBusString    *str,
970                                int                  start,
971                                int                  len)
972 {
973   const char *d;
974
975   _dbus_string_get_const_data_len (str, &d, start, len);
976
977   _dbus_verbose_bytes (d, len);
978 }
979
980 /** @} */
981
982 #ifdef DBUS_BUILD_TESTS
983 #include "dbus-test.h"
984 #include <stdio.h>
985
986 dbus_bool_t
987 _dbus_marshal_test (void)
988 {
989   DBusString str;
990   char *tmp1, *tmp2;
991   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
992   int pos = 0, len;
993   
994   if (!_dbus_string_init (&str, _DBUS_INT_MAX))
995     _dbus_assert_not_reached ("failed to init string");
996
997   /* Marshal doubles */
998   if (!_dbus_marshal_double (&str, DBUS_BIG_ENDIAN, 3.14))
999     _dbus_assert_not_reached ("could not marshal double value");
1000   _dbus_assert (_dbus_demarshal_double (&str, DBUS_BIG_ENDIAN, pos, &pos) == 3.14);
1001
1002   if (!_dbus_marshal_double (&str, DBUS_LITTLE_ENDIAN, 3.14))
1003     _dbus_assert_not_reached ("could not marshal double value");
1004   _dbus_assert (_dbus_demarshal_double (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 3.14);
1005   
1006   /* Marshal signed integers */
1007   if (!_dbus_marshal_int32 (&str, DBUS_BIG_ENDIAN, -12345678))
1008     _dbus_assert_not_reached ("could not marshal signed integer value");
1009   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == -12345678);
1010
1011   if (!_dbus_marshal_int32 (&str, DBUS_LITTLE_ENDIAN, -12345678))
1012     _dbus_assert_not_reached ("could not marshal signed integer value");
1013   _dbus_assert (_dbus_demarshal_int32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == -12345678);
1014   
1015   /* Marshal unsigned integers */
1016   if (!_dbus_marshal_uint32 (&str, DBUS_BIG_ENDIAN, 0x12345678))
1017     _dbus_assert_not_reached ("could not marshal signed integer value");
1018   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_BIG_ENDIAN, pos, &pos) == 0x12345678);
1019   
1020   if (!_dbus_marshal_uint32 (&str, DBUS_LITTLE_ENDIAN, 0x12345678))
1021     _dbus_assert_not_reached ("could not marshal signed integer value");
1022   _dbus_assert (_dbus_demarshal_uint32 (&str, DBUS_LITTLE_ENDIAN, pos, &pos) == 0x12345678);
1023
1024   /* Marshal strings */
1025   tmp1 = "This is the dbus test string";
1026   if (!_dbus_marshal_string (&str, DBUS_BIG_ENDIAN, tmp1))
1027     _dbus_assert_not_reached ("could not marshal string");
1028   tmp2 = _dbus_demarshal_string (&str, DBUS_BIG_ENDIAN, pos, &pos);
1029   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1030   dbus_free (tmp2);
1031
1032   tmp1 = "This is the dbus test string";
1033   if (!_dbus_marshal_string (&str, DBUS_LITTLE_ENDIAN, tmp1))
1034     _dbus_assert_not_reached ("could not marshal string");
1035   tmp2 = _dbus_demarshal_string (&str, DBUS_LITTLE_ENDIAN, pos, &pos);
1036   _dbus_assert (strcmp (tmp1, tmp2) == 0);
1037   dbus_free (tmp2);
1038
1039   /* Marshal signed integer arrays */
1040   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
1041     _dbus_assert_not_reached ("could not marshal integer array");
1042   array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
1043   printf ("length is: %d\n", len);
1044   if (len != 3)
1045     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
1046
1047   
1048
1049
1050   _dbus_string_free (&str);
1051   
1052       
1053   return TRUE;
1054 }
1055
1056 #endif /* DBUS_BUILD_TESTS */