D-Bus 1.15.2
dbus-marshal-basic.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-marshal-basic.c Marshalling routines for basic (primitive) types
3 *
4 * Copyright (C) 2002 CodeFactory AB
5 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "dbus-internals.h"
27#include "dbus-marshal-basic.h"
28#include "dbus-signature.h"
29#include <dbus/dbus-test-tap.h>
30
31#include <string.h>
32
33#if defined(__GNUC__) && (__GNUC__ >= 4)
34# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
35 _DBUS_STATIC_ASSERT (__extension__ __alignof__ (type) op val)
36# define _DBUS_ASSERT_CMP_ALIGNMENT(left, op, right) \
37 _DBUS_STATIC_ASSERT (__extension__ __alignof__ (left) op __extension__ __alignof__ (right))
38#else
39 /* not gcc, so probably no alignof operator: just use a no-op statement
40 * that's valid in the same contexts */
41# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
42 _DBUS_STATIC_ASSERT (TRUE)
43# define _DBUS_ASSERT_CMP_ALIGNMENT(left, op, right) \
44 _DBUS_STATIC_ASSERT (TRUE)
45#endif
46
47/* True by definition, but just for completeness... */
48_DBUS_STATIC_ASSERT (sizeof (char) == 1);
49_DBUS_ASSERT_ALIGNMENT (char, ==, 1);
50
51_DBUS_STATIC_ASSERT (sizeof (dbus_int16_t) == 2);
52_DBUS_ASSERT_ALIGNMENT (dbus_int16_t, <=, 2);
53_DBUS_STATIC_ASSERT (sizeof (dbus_uint16_t) == 2);
54_DBUS_ASSERT_ALIGNMENT (dbus_uint16_t, <=, 2);
55_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint16_t, ==, dbus_int16_t);
56
57_DBUS_STATIC_ASSERT (sizeof (dbus_int32_t) == 4);
58_DBUS_ASSERT_ALIGNMENT (dbus_int32_t, <=, 4);
59_DBUS_STATIC_ASSERT (sizeof (dbus_uint32_t) == 4);
60_DBUS_ASSERT_ALIGNMENT (dbus_uint32_t, <=, 4);
61_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint32_t, ==, dbus_int32_t);
62_DBUS_STATIC_ASSERT (sizeof (dbus_bool_t) == 4);
63_DBUS_ASSERT_ALIGNMENT (dbus_bool_t, <=, 4);
64_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint32_t, ==, dbus_bool_t);
65
66_DBUS_STATIC_ASSERT (sizeof (double) == 8);
67_DBUS_ASSERT_ALIGNMENT (double, <=, 8);
68/* Doubles might sometimes be more strictly aligned than int64, but we
69 * assume they are no less strictly aligned. This means every (double *)
70 * has enough alignment to be treated as though it was a
71 * (dbus_uint64_t *). */
72_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint64_t, <=, double);
73
74_DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8);
75_DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8);
76_DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8);
77_DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8);
78_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint64_t, ==, dbus_int64_t);
79
80_DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8);
81/* The alignment of a DBusBasicValue might conceivably be > 8 because of the
82 * pointer, so we don't assert about it */
83
84_DBUS_STATIC_ASSERT (sizeof (DBus8ByteStruct) == 8);
85_DBUS_ASSERT_ALIGNMENT (DBus8ByteStruct, <=, 8);
86
102static void
103pack_2_octets (dbus_uint16_t value,
104 int byte_order,
105 void *data)
106{
107 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
108
109 if ((byte_order) == DBUS_LITTLE_ENDIAN)
110 *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
111 else
112 *((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
113}
114
115static void
116pack_4_octets (dbus_uint32_t value,
117 int byte_order,
118 void *data)
119{
120 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
121
122 if ((byte_order) == DBUS_LITTLE_ENDIAN)
123 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
124 else
125 *((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
126}
127
128static void
129pack_8_octets (dbus_uint64_t value,
130 int byte_order,
131 void *data)
132{
133 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
134
135 if ((byte_order) == DBUS_LITTLE_ENDIAN)
136 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value);
137 else
138 *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value);
139}
140
148void
150 int byte_order,
151 unsigned char *data)
152{
153 pack_4_octets (value, byte_order, data);
154}
155
156static void
157swap_8_octets (dbus_uint64_t *value,
158 int byte_order)
159{
160 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
161 {
162 *value = DBUS_UINT64_SWAP_LE_BE (*value);
163 }
164}
165
166#ifndef _dbus_unpack_uint16
175_dbus_unpack_uint16 (int byte_order,
176 const unsigned char *data)
177{
178 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
179
180 if (byte_order == DBUS_LITTLE_ENDIAN)
181 return DBUS_UINT16_FROM_LE (*(dbus_uint16_t *) (void *) data);
182 else
183 return DBUS_UINT16_FROM_BE (*(dbus_uint16_t *) (void *) data);
184}
185#endif /* _dbus_unpack_uint16 */
186
187#ifndef _dbus_unpack_uint32
196_dbus_unpack_uint32 (int byte_order,
197 const unsigned char *data)
198{
199 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
200
201 if (byte_order == DBUS_LITTLE_ENDIAN)
202 return DBUS_UINT32_FROM_LE (*(dbus_uint32_t *) (void *) data);
203 else
204 return DBUS_UINT32_FROM_BE (*(dbus_uint32_t *) (void *) data);
205}
206#endif /* _dbus_unpack_uint32 */
207
208static void
209set_2_octets (DBusString *str,
210 int offset,
211 dbus_uint16_t value,
212 int byte_order)
213{
214 char *data;
215
216 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
217 byte_order == DBUS_BIG_ENDIAN);
218
219 data = _dbus_string_get_data_len (str, offset, 2);
220
221 pack_2_octets (value, byte_order, (unsigned char *) data);
222}
223
224static void
225set_4_octets (DBusString *str,
226 int offset,
227 dbus_uint32_t value,
228 int byte_order)
229{
230 char *data;
231
232 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
233 byte_order == DBUS_BIG_ENDIAN);
234
235 data = _dbus_string_get_data_len (str, offset, 4);
236
237 pack_4_octets (value, byte_order, (unsigned char *) data);
238}
239
240static void
241set_8_octets (DBusString *str,
242 int offset,
243 dbus_uint64_t value,
244 int byte_order)
245{
246 char *data;
247
248 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
249 byte_order == DBUS_BIG_ENDIAN);
250
251 data = _dbus_string_get_data_len (str, offset, 8);
252
253 pack_8_octets (value, byte_order, (unsigned char *) data);
254}
255
266void
268 int pos,
269 dbus_uint32_t value,
270 int byte_order)
271{
272 set_4_octets (str, pos, value, byte_order);
273}
274
294static dbus_bool_t
295set_string (DBusString *str,
296 int pos,
297 const char *value,
298 int byte_order,
299 int *old_end_pos,
300 int *new_end_pos)
301{
302 int old_len, new_len;
303 DBusString dstr;
304
305 _dbus_string_init_const (&dstr, value);
306
307 _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
308 old_len = _dbus_unpack_uint32 (byte_order,
309 _dbus_string_get_const_udata_len (str, pos, 4));
310
311 new_len = _dbus_string_get_length (&dstr);
312
313 if (!_dbus_string_replace_len (&dstr, 0, new_len,
314 str, pos + 4, old_len))
315 return FALSE;
316
317 _dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
318
319 if (old_end_pos)
320 *old_end_pos = pos + 4 + old_len + 1;
321 if (new_end_pos)
322 *new_end_pos = pos + 4 + new_len + 1;
323
324 return TRUE;
325}
326
340static dbus_bool_t
341set_signature (DBusString *str,
342 int pos,
343 const char *value,
344 int byte_order,
345 int *old_end_pos,
346 int *new_end_pos)
347{
348 int old_len, new_len;
349 DBusString dstr;
350
351 _dbus_string_init_const (&dstr, value);
352
353 old_len = _dbus_string_get_byte (str, pos);
354 new_len = _dbus_string_get_length (&dstr);
355
356 if (!_dbus_string_replace_len (&dstr, 0, new_len,
357 str, pos + 1, old_len))
358 return FALSE;
359
360 _dbus_string_set_byte (str, pos, new_len);
361
362 if (old_end_pos)
363 *old_end_pos = pos + 1 + old_len + 1;
364 if (new_end_pos)
365 *new_end_pos = pos + 1 + new_len + 1;
366
367 return TRUE;
368}
369
385 int pos,
386 int type,
387 const void *value,
388 int byte_order,
389 int *old_end_pos,
390 int *new_end_pos)
391{
392 /* Static assertions near the top of this file assert that signed and
393 * unsigned 16- and 32-bit quantities have the same alignment, and that
394 * doubles have alignment at least as strict as unsigned int64, so we
395 * don't have to distinguish further: every (double *)
396 * has strong enough alignment to be treated as though it was a
397 * (dbus_uint64_t *). Going via a (void *) means the compiler should
398 * know that pointers can alias each other. */
399 const unsigned char *u8_p;
400 const dbus_uint16_t *u16_p;
401 const dbus_uint32_t *u32_p;
402 const dbus_uint64_t *u64_p;
403 const char * const *string_p;
404
405 switch (type)
406 {
407 case DBUS_TYPE_BYTE:
408 u8_p = value;
409 _dbus_string_set_byte (str, pos, *u8_p);
410 if (old_end_pos)
411 *old_end_pos = pos + 1;
412 if (new_end_pos)
413 *new_end_pos = pos + 1;
414 return TRUE;
415 break;
416 case DBUS_TYPE_INT16:
417 case DBUS_TYPE_UINT16:
418 u16_p = value;
419 pos = _DBUS_ALIGN_VALUE (pos, 2);
420 set_2_octets (str, pos, *u16_p, byte_order);
421 if (old_end_pos)
422 *old_end_pos = pos + 2;
423 if (new_end_pos)
424 *new_end_pos = pos + 2;
425 return TRUE;
426 break;
428 case DBUS_TYPE_INT32:
429 case DBUS_TYPE_UINT32:
431 u32_p = value;
432 pos = _DBUS_ALIGN_VALUE (pos, 4);
433 set_4_octets (str, pos, *u32_p, byte_order);
434 if (old_end_pos)
435 *old_end_pos = pos + 4;
436 if (new_end_pos)
437 *new_end_pos = pos + 4;
438 return TRUE;
439 break;
440 case DBUS_TYPE_INT64:
441 case DBUS_TYPE_UINT64:
442 case DBUS_TYPE_DOUBLE:
443 u64_p = value;
444 pos = _DBUS_ALIGN_VALUE (pos, 8);
445 set_8_octets (str, pos, *u64_p, byte_order);
446 if (old_end_pos)
447 *old_end_pos = pos + 8;
448 if (new_end_pos)
449 *new_end_pos = pos + 8;
450 return TRUE;
451 break;
452 case DBUS_TYPE_STRING:
454 string_p = value;
455 pos = _DBUS_ALIGN_VALUE (pos, 4);
456 _dbus_assert (*string_p != NULL);
457 return set_string (str, pos, *string_p, byte_order,
458 old_end_pos, new_end_pos);
459 break;
461 string_p = value;
462 _dbus_assert (*string_p != NULL);
463 return set_signature (str, pos, *string_p, byte_order,
464 old_end_pos, new_end_pos);
465 break;
466 default:
467 _dbus_assert_not_reached ("not a basic type");
468 return FALSE;
469 break;
470 }
471}
472
484 int pos,
485 int byte_order,
486 int *new_pos)
487{
488 pos = _DBUS_ALIGN_VALUE (pos, 4);
489
490 if (new_pos)
491 *new_pos = pos + 4;
492
493 _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
494
495 return _dbus_unpack_uint32 (byte_order,
496 _dbus_string_get_const_udata (str) + pos);
497}
498
520void
522 int pos,
523 int type,
524 void *value,
525 int byte_order,
526 int *new_pos)
527{
528 const char *str_data;
529
531
532 str_data = _dbus_string_get_const_data (str);
533
534 /* Below we volatile types to avoid aliasing issues;
535 * see http://bugs.freedesktop.org/show_bug.cgi?id=20137
536 */
537
538 switch (type)
539 {
540 case DBUS_TYPE_BYTE:
541 {
542 volatile unsigned char *vp = value;
543 *vp = (unsigned char) _dbus_string_get_byte (str, pos);
544 (pos)++;
545 }
546 break;
547 case DBUS_TYPE_INT16:
548 case DBUS_TYPE_UINT16:
549 {
550 volatile dbus_uint16_t *vp = value;
551 pos = _DBUS_ALIGN_VALUE (pos, 2);
552 *vp = *(dbus_uint16_t *) (void *) (str_data + pos);
553 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
554 *vp = DBUS_UINT16_SWAP_LE_BE (*vp);
555 pos += 2;
556 }
557 break;
558 case DBUS_TYPE_INT32:
559 case DBUS_TYPE_UINT32:
562 {
563 volatile dbus_uint32_t *vp = value;
564 pos = _DBUS_ALIGN_VALUE (pos, 4);
565 *vp = *(dbus_uint32_t *) (void *) (str_data + pos);
566 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
567 *vp = DBUS_UINT32_SWAP_LE_BE (*vp);
568 pos += 4;
569 }
570 break;
571 case DBUS_TYPE_INT64:
572 case DBUS_TYPE_UINT64:
573 case DBUS_TYPE_DOUBLE:
574 {
575 volatile dbus_uint64_t *vp = value;
576 pos = _DBUS_ALIGN_VALUE (pos, 8);
577 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
578 *vp = DBUS_UINT64_SWAP_LE_BE (
579 *(dbus_uint64_t *) (void *) (str_data + pos));
580 else
581 *vp = *(dbus_uint64_t *) (void *) (str_data + pos);
582 pos += 8;
583 }
584 break;
585 case DBUS_TYPE_STRING:
587 {
588 int len;
589 volatile char **vp = value;
590
591 len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
592
593 *vp = (char*) str_data + pos;
594
595 pos += len + 1; /* length plus nul */
596 }
597 break;
599 {
600 int len;
601 volatile char **vp = value;
602
603 len = _dbus_string_get_byte (str, pos);
604 pos += 1;
605
606 *vp = (char*) str_data + pos;
607
608 pos += len + 1; /* length plus nul */
609 }
610 break;
611 default:
612 _dbus_warn_check_failed ("type %s %d not a basic type",
613 _dbus_type_to_string (type), type);
614 _dbus_assert_not_reached ("not a basic type");
615 break;
616 }
617
618 if (new_pos)
619 *new_pos = pos;
620}
621
622static dbus_bool_t
623marshal_2_octets (DBusString *str,
624 int insert_at,
625 dbus_uint16_t value,
626 int byte_order,
627 int *pos_after)
628{
629 dbus_bool_t retval;
630 int orig_len;
631
632 _DBUS_STATIC_ASSERT (sizeof (value) == 2);
633
634 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
635 value = DBUS_UINT16_SWAP_LE_BE (value);
636
637 orig_len = _dbus_string_get_length (str);
638
639 retval = _dbus_string_insert_2_aligned (str, insert_at,
640 (const unsigned char *)&value);
641
642 if (pos_after)
643 {
644 *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
645 _dbus_assert (*pos_after <= _dbus_string_get_length (str));
646 }
647
648 return retval;
649}
650
651static dbus_bool_t
652marshal_4_octets (DBusString *str,
653 int insert_at,
654 dbus_uint32_t value,
655 int byte_order,
656 int *pos_after)
657{
658 dbus_bool_t retval;
659 int orig_len;
660
661 _DBUS_STATIC_ASSERT (sizeof (value) == 4);
662
663 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
664 value = DBUS_UINT32_SWAP_LE_BE (value);
665
666 orig_len = _dbus_string_get_length (str);
667
668 retval = _dbus_string_insert_4_aligned (str, insert_at,
669 (const unsigned char *)&value);
670
671 if (pos_after)
672 {
673 *pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
674 _dbus_assert (*pos_after <= _dbus_string_get_length (str));
675 }
676
677 return retval;
678}
679
680static dbus_bool_t
681marshal_8_octets (DBusString *str,
682 int insert_at,
683 dbus_uint64_t value,
684 int byte_order,
685 int *pos_after)
686{
687 dbus_bool_t retval;
688 int orig_len;
689
690 _DBUS_STATIC_ASSERT (sizeof (value) == 8);
691
692 swap_8_octets (&value, byte_order);
693
694 orig_len = _dbus_string_get_length (str);
695
696 retval = _dbus_string_insert_8_aligned (str, insert_at,
697 (const unsigned char *)&value);
698
699 if (pos_after)
700 *pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
701
702 return retval;
703}
704
705enum
706 {
707 MARSHAL_AS_STRING,
708 MARSHAL_AS_SIGNATURE,
709 MARSHAL_AS_BYTE_ARRAY
710 };
711
712static dbus_bool_t
713marshal_len_followed_by_bytes (int marshal_as,
714 DBusString *str,
715 int insert_at,
716 const unsigned char *value,
717 int data_len, /* doesn't include nul if any */
718 int byte_order,
719 int *pos_after)
720{
721 int pos;
722 DBusString value_str;
723 int value_len;
724
725 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
726 if (insert_at > _dbus_string_get_length (str))
727 _dbus_warn ("insert_at = %d string len = %d data_len = %d",
728 insert_at, _dbus_string_get_length (str), data_len);
729
730 if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
731 value_len = data_len;
732 else
733 value_len = data_len + 1; /* value has a nul */
734
735 _dbus_string_init_const_len (&value_str, (const char *) value, value_len);
736
737 pos = insert_at;
738
739 if (marshal_as == MARSHAL_AS_SIGNATURE)
740 {
742 _dbus_assert (data_len <= 255); /* same as max sig len right now */
743
744 if (!_dbus_string_insert_byte (str, pos, data_len))
745 goto oom;
746
747 pos += 1;
748 }
749 else
750 {
751 if (!marshal_4_octets (str, pos, data_len,
752 byte_order, &pos))
753 goto oom;
754 }
755
756 if (!_dbus_string_copy_len (&value_str, 0, value_len,
757 str, pos))
758 goto oom;
759
760#if 0
761 /* too expensive */
762 _dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
763 str, pos));
764 _dbus_verbose_bytes_of_string (str, pos, value_len);
765#endif
766
767 pos += value_len;
768
769 if (pos_after)
770 *pos_after = pos;
771
772 return TRUE;
773
774 oom:
775 /* Delete what we've inserted */
776 _dbus_string_delete (str, insert_at, pos - insert_at);
777
778 return FALSE;
779}
780
781static dbus_bool_t
782marshal_string (DBusString *str,
783 int insert_at,
784 const char *value,
785 int byte_order,
786 int *pos_after)
787{
788 return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
789 str, insert_at, (const unsigned char *) value,
790 strlen (value),
791 byte_order, pos_after);
792}
793
794static dbus_bool_t
795marshal_signature (DBusString *str,
796 int insert_at,
797 const char *value,
798 int *pos_after)
799{
800 return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
801 str, insert_at, (const unsigned char *) value,
802 strlen (value),
803 DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
804 pos_after);
805}
806
825 int insert_at,
826 int type,
827 const void *value,
828 int byte_order,
829 int *pos_after)
830{
831 /* Static assertions near the top of this file assert that signed and
832 * unsigned 16- and 32-bit quantities have the same alignment, and that
833 * doubles have alignment at least as strict as unsigned int64, so we
834 * don't have to distinguish further: every (double *)
835 * has strong enough alignment to be treated as though it was a
836 * (dbus_uint64_t *). Going via a (void *) means the compiler should
837 * know that pointers can alias each other. */
838 const unsigned char *u8_p;
839 const dbus_uint16_t *u16_p;
840 const dbus_uint32_t *u32_p;
841 const dbus_uint64_t *u64_p;
842 const char * const *string_p;
843
845
846 switch (type)
847 {
848 case DBUS_TYPE_BYTE:
849 u8_p = value;
850 if (!_dbus_string_insert_byte (str, insert_at, *u8_p))
851 return FALSE;
852 if (pos_after)
853 *pos_after = insert_at + 1;
854 return TRUE;
855 break;
856 case DBUS_TYPE_INT16:
857 case DBUS_TYPE_UINT16:
858 u16_p = value;
859 return marshal_2_octets (str, insert_at, *u16_p,
860 byte_order, pos_after);
861 break;
863 u32_p = value;
864 return marshal_4_octets (str, insert_at, (*u32_p != FALSE),
865 byte_order, pos_after);
866 break;
867 case DBUS_TYPE_INT32:
868 case DBUS_TYPE_UINT32:
870 u32_p = value;
871 return marshal_4_octets (str, insert_at, *u32_p,
872 byte_order, pos_after);
873 break;
874 case DBUS_TYPE_INT64:
875 case DBUS_TYPE_UINT64:
876 case DBUS_TYPE_DOUBLE:
877 u64_p = value;
878 return marshal_8_octets (str, insert_at, *u64_p, byte_order, pos_after);
879 break;
880
881 case DBUS_TYPE_STRING:
883 string_p = value;
884 _dbus_assert (*string_p != NULL);
885 return marshal_string (str, insert_at, *string_p, byte_order, pos_after);
886 break;
888 string_p = value;
889 _dbus_assert (*string_p != NULL);
890 return marshal_signature (str, insert_at, *string_p, pos_after);
891 break;
892 default:
893 _dbus_assert_not_reached ("not a basic type");
894 return FALSE;
895 break;
896 }
897}
898
899static dbus_bool_t
900marshal_1_octets_array (DBusString *str,
901 int insert_at,
902 const unsigned char *value,
903 int n_elements,
904 int byte_order,
905 int *pos_after)
906{
907 int pos;
908 DBusString value_str;
909
910 _dbus_string_init_const_len (&value_str, (const char *) value, n_elements);
911
912 pos = insert_at;
913
914 if (!_dbus_string_copy_len (&value_str, 0, n_elements,
915 str, pos))
916 return FALSE;
917
918 pos += n_elements;
919
920 if (pos_after)
921 *pos_after = pos;
922
923 return TRUE;
924}
925
933void
934_dbus_swap_array (unsigned char *data,
935 int n_elements,
936 int alignment)
937{
938 void *d;
939 void *end;
940
941 _dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
942
943 /* we use const_data and cast it off so DBusString can be a const string
944 * for the unit tests. don't ask.
945 */
946 d = data;
947 end = data + (n_elements * alignment);
948
949 if (alignment == 8)
950 {
951 while (d != end)
952 {
953 *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
954 d = ((unsigned char *) d) + 8;
955 }
956 }
957 else if (alignment == 4)
958 {
959 while (d != end)
960 {
961 *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
962 d = ((unsigned char *) d) + 4;
963 }
964 }
965 else
966 {
967 _dbus_assert (alignment == 2);
968
969 while (d != end)
970 {
971 *((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
972 d = ((unsigned char *) d) + 2;
973 }
974 }
975}
976
977static void
978swap_array (DBusString *str,
979 int array_start,
980 int n_elements,
981 int byte_order,
982 int alignment)
983{
984 _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
985
986 if (byte_order != DBUS_COMPILER_BYTE_ORDER)
987 {
988 /* we use const_data and cast it off so DBusString can be a const string
989 * for the unit tests. don't ask.
990 */
991 _dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
992 n_elements, alignment);
993 }
994}
995
996static dbus_bool_t
997marshal_fixed_multi (DBusString *str,
998 int insert_at,
999 const void *value,
1000 int n_elements,
1001 int byte_order,
1002 int alignment,
1003 int *pos_after)
1004{
1005 int old_string_len;
1006 int array_start;
1007 DBusString t;
1008 int len_in_bytes;
1009
1010 _dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
1011
1012 old_string_len = _dbus_string_get_length (str);
1013
1014 len_in_bytes = n_elements * alignment;
1015 array_start = insert_at;
1016
1017 /* Note that we do alignment padding unconditionally
1018 * even if the array is empty; this means that
1019 * padding + len is always equal to the number of bytes
1020 * in the array.
1021 */
1022
1023 if (!_dbus_string_insert_alignment (str, &array_start, alignment))
1024 goto error;
1025
1027 (const char *) value,
1028 len_in_bytes);
1029
1030 if (!_dbus_string_copy (&t, 0,
1031 str, array_start))
1032 goto error;
1033
1034 swap_array (str, array_start, n_elements, byte_order, alignment);
1035
1036 if (pos_after)
1037 *pos_after = array_start + len_in_bytes;
1038
1039 return TRUE;
1040
1041 error:
1042 _dbus_string_delete (str, insert_at,
1043 _dbus_string_get_length (str) - old_string_len);
1044
1045 return FALSE;
1046}
1047
1067 int insert_at,
1068 int element_type,
1069 const void *value,
1070 int n_elements,
1071 int byte_order,
1072 int *pos_after)
1073{
1074 /* Static assertions near the top of this file assert that signed and
1075 * unsigned 16- and 32-bit quantities have the same alignment, and that
1076 * doubles have alignment at least as strict as unsigned int64, so we
1077 * don't have to distinguish further: every (double *)
1078 * has strong enough alignment to be treated as though it was a
1079 * (dbus_uint64_t *). Going via a (void *) means the compiler should
1080 * know that pointers can alias each other. */
1081 const unsigned char * const *u8_pp;
1082 const dbus_uint16_t * const *u16_pp;
1083 const dbus_uint32_t * const *u32_pp;
1084 const dbus_uint64_t * const *u64_pp;
1085
1086 _dbus_assert (dbus_type_is_fixed (element_type));
1087 _dbus_assert (n_elements >= 0);
1088
1089#if 0
1090 _dbus_verbose ("writing %d elements of %s\n",
1091 n_elements, _dbus_type_to_string (element_type));
1092#endif
1093
1094 switch (element_type)
1095 {
1096 case DBUS_TYPE_BYTE:
1097 u8_pp = value;
1098 return marshal_1_octets_array (str, insert_at, *u8_pp, n_elements, byte_order, pos_after);
1099 break;
1100 case DBUS_TYPE_INT16:
1101 case DBUS_TYPE_UINT16:
1102 u16_pp = value;
1103 return marshal_fixed_multi (str, insert_at, *u16_pp, n_elements, byte_order, 2, pos_after);
1104 case DBUS_TYPE_BOOLEAN:
1105 case DBUS_TYPE_INT32:
1106 case DBUS_TYPE_UINT32:
1107 case DBUS_TYPE_UNIX_FD:
1108 u32_pp = value;
1109 return marshal_fixed_multi (str, insert_at, *u32_pp, n_elements, byte_order, 4, pos_after);
1110 break;
1111 case DBUS_TYPE_INT64:
1112 case DBUS_TYPE_UINT64:
1113 case DBUS_TYPE_DOUBLE:
1114 u64_pp = value;
1115 return marshal_fixed_multi (str, insert_at, *u64_pp, n_elements, byte_order, 8, pos_after);
1116 break;
1117
1118 default:
1119 _dbus_assert_not_reached ("non fixed type in array write");
1120 break;
1121 }
1122
1123 return FALSE;
1124}
1125
1126
1136void
1138 int type,
1139 int byte_order,
1140 int *pos)
1141{
1142 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
1143 byte_order == DBUS_BIG_ENDIAN);
1144
1145 switch (type)
1146 {
1147 case DBUS_TYPE_BYTE:
1148 (*pos)++;
1149 break;
1150 case DBUS_TYPE_INT16:
1151 case DBUS_TYPE_UINT16:
1152 *pos = _DBUS_ALIGN_VALUE (*pos, 2);
1153 *pos += 2;
1154 break;
1155 case DBUS_TYPE_BOOLEAN:
1156 case DBUS_TYPE_INT32:
1157 case DBUS_TYPE_UINT32:
1158 case DBUS_TYPE_UNIX_FD:
1159 *pos = _DBUS_ALIGN_VALUE (*pos, 4);
1160 *pos += 4;
1161 break;
1162 case DBUS_TYPE_INT64:
1163 case DBUS_TYPE_UINT64:
1164 case DBUS_TYPE_DOUBLE:
1165 *pos = _DBUS_ALIGN_VALUE (*pos, 8);
1166 *pos += 8;
1167 break;
1168 case DBUS_TYPE_STRING:
1170 {
1171 int len;
1172
1173 len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
1174
1175 *pos += len + 1; /* length plus nul */
1176 }
1177 break;
1179 {
1180 int len;
1181
1182 len = _dbus_string_get_byte (str, *pos);
1183
1184 *pos += len + 2; /* length byte plus length plus nul */
1185 }
1186 break;
1187 default:
1188 _dbus_warn ("type %s not a basic type",
1189 _dbus_type_to_string (type));
1190 _dbus_assert_not_reached ("not a basic type");
1191 break;
1192 }
1193}
1194
1204void
1206 int element_type,
1207 int byte_order,
1208 int *pos)
1209{
1210 dbus_uint32_t array_len;
1211 int i;
1212 int alignment;
1213
1214 i = _DBUS_ALIGN_VALUE (*pos, 4);
1215
1216 array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
1217
1218 alignment = _dbus_type_get_alignment (element_type);
1219
1220 i = _DBUS_ALIGN_VALUE (i, alignment);
1221
1222 *pos = i + array_len;
1223}
1224
1232int
1234{
1235 switch (typecode)
1236 {
1237 case DBUS_TYPE_BYTE:
1238 case DBUS_TYPE_VARIANT:
1240 return 1;
1241 case DBUS_TYPE_INT16:
1242 case DBUS_TYPE_UINT16:
1243 return 2;
1244 case DBUS_TYPE_BOOLEAN:
1245 case DBUS_TYPE_INT32:
1246 case DBUS_TYPE_UINT32:
1247 case DBUS_TYPE_UNIX_FD:
1248 /* this stuff is 4 since it starts with a length */
1249 case DBUS_TYPE_STRING:
1251 case DBUS_TYPE_ARRAY:
1252 return 4;
1253 case DBUS_TYPE_INT64:
1254 case DBUS_TYPE_UINT64:
1255 case DBUS_TYPE_DOUBLE:
1256 /* struct is 8 since it could contain an 8-aligned item
1257 * and it's simpler to just always align structs to 8;
1258 * we want the amount of padding in a struct of a given
1259 * type to be predictable, not location-dependent.
1260 * DICT_ENTRY is always the same as struct.
1261 */
1262 case DBUS_TYPE_STRUCT:
1264 return 8;
1265
1266 default:
1267 _dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
1268 return 0;
1269 }
1270}
1271
1278const char *
1280{
1281 switch (typecode)
1282 {
1283 case DBUS_TYPE_INVALID:
1284 return "invalid";
1285 case DBUS_TYPE_BOOLEAN:
1286 return "boolean";
1287 case DBUS_TYPE_BYTE:
1288 return "byte";
1289 case DBUS_TYPE_INT16:
1290 return "int16";
1291 case DBUS_TYPE_UINT16:
1292 return "uint16";
1293 case DBUS_TYPE_INT32:
1294 return "int32";
1295 case DBUS_TYPE_UINT32:
1296 return "uint32";
1297 case DBUS_TYPE_INT64:
1298 return "int64";
1299 case DBUS_TYPE_UINT64:
1300 return "uint64";
1301 case DBUS_TYPE_DOUBLE:
1302 return "double";
1303 case DBUS_TYPE_STRING:
1304 return "string";
1306 return "object_path";
1308 return "signature";
1309 case DBUS_TYPE_STRUCT:
1310 return "struct";
1312 return "dict_entry";
1313 case DBUS_TYPE_ARRAY:
1314 return "array";
1315 case DBUS_TYPE_VARIANT:
1316 return "variant";
1318 return "begin_struct";
1320 return "end_struct";
1322 return "begin_dict_entry";
1324 return "end_dict_entry";
1325 case DBUS_TYPE_UNIX_FD:
1326 return "unix_fd";
1327 default:
1328 return "unknown";
1329 }
1330}
1331
1339void
1340_dbus_verbose_bytes (const unsigned char *data,
1341 int len,
1342 int offset)
1343{
1344 int i;
1345 const unsigned char *aligned;
1346
1347 _dbus_assert (len >= 0);
1348
1349 if (!_dbus_is_verbose())
1350 return;
1351
1352 /* Print blanks on first row if appropriate */
1353 aligned = _DBUS_ALIGN_ADDRESS (data, 4);
1354 if (aligned > data)
1355 aligned -= 4;
1356 _dbus_assert (aligned <= data);
1357
1358 if (aligned != data)
1359 {
1360 _dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
1361 while (aligned != data)
1362 {
1363 _dbus_verbose (" ");
1364 ++aligned;
1365 }
1366 }
1367
1368 /* now print the bytes */
1369 i = 0;
1370 while (i < len)
1371 {
1372 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1373 {
1374 _dbus_verbose ("%4d\t%p: ",
1375 offset + i, &data[i]);
1376 }
1377
1378 if (data[i] >= 32 &&
1379 data[i] <= 126)
1380 _dbus_verbose (" '%c' ", data[i]);
1381 else
1382 _dbus_verbose ("0x%s%x ",
1383 data[i] <= 0xf ? "0" : "", data[i]);
1384
1385 ++i;
1386
1387 if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
1388 {
1389 if (i > 3)
1390 _dbus_verbose ("BE: %d LE: %d",
1393
1394 if (i > 7 &&
1395 _DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
1396 {
1397 _dbus_verbose (" u64: 0x%" DBUS_INT64_MODIFIER "x",
1398 *(dbus_uint64_t *) (void *) &data[i - 8]);
1399 _dbus_verbose (" dbl: %g", *(double *) (void *) &data[i - 8]);
1400 }
1401
1402 _dbus_verbose ("\n");
1403 }
1404 }
1405
1406 _dbus_verbose ("\n");
1407}
1408
1416void
1418 int start,
1419 int len)
1420{
1421 const char *d;
1422 int real_len;
1423
1424 real_len = _dbus_string_get_length (str);
1425
1426 _dbus_assert (start >= 0);
1427
1428 if (start > real_len)
1429 {
1430 _dbus_verbose (" [%d,%d) is not inside string of length %d\n",
1431 start, len, real_len);
1432 return;
1433 }
1434
1435 if ((start + len) > real_len)
1436 {
1437 _dbus_verbose (" [%d,%d) extends outside string of length %d\n",
1438 start, len, real_len);
1439 len = real_len - start;
1440 }
1441
1442 d = _dbus_string_get_const_data_len (str, start, len);
1443
1444 _dbus_verbose_bytes ((const unsigned char *) d, len, start);
1445}
1446
1447static int
1448map_type_char_to_type (int t)
1449{
1450 if (t == DBUS_STRUCT_BEGIN_CHAR)
1451 return DBUS_TYPE_STRUCT;
1452 else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
1453 return DBUS_TYPE_DICT_ENTRY;
1454 else
1455 {
1458 return t;
1459 }
1460}
1461
1472int
1474 int pos)
1475{
1476 return map_type_char_to_type (_dbus_string_get_byte (str, pos));
1477}
1478
1487int
1489 int pos)
1490{
1491 return map_type_char_to_type (str[pos]);
1492}
1493
1496#ifdef DBUS_ENABLE_EMBEDDED_TESTS
1497#include "dbus-test.h"
1498#include <stdio.h>
1499
1518void
1519_dbus_marshal_read_fixed_multi (const DBusString *str,
1520 int pos,
1521 int element_type,
1522 const void **value,
1523 int n_elements,
1524 int byte_order,
1525 int *new_pos)
1526{
1527 int array_len;
1528 int alignment;
1529
1530 _dbus_assert (dbus_type_is_fixed (element_type));
1531 _dbus_assert (dbus_type_is_basic (element_type));
1532
1533#if 0
1534 _dbus_verbose ("reading %d elements of %s\n",
1535 n_elements, _dbus_type_to_string (element_type));
1536#endif
1537
1538 alignment = _dbus_type_get_alignment (element_type);
1539
1540 pos = _DBUS_ALIGN_VALUE (pos, alignment);
1541
1542 array_len = n_elements * alignment;
1543
1544 *value = _dbus_string_get_const_data_len (str, pos, array_len);
1545 if (new_pos)
1546 *new_pos = pos + array_len;
1547}
1548
1549static void
1550swap_test_array (void *array,
1551 int len_bytes,
1552 int byte_order,
1553 int alignment)
1554{
1555 DBusString t;
1556
1557 if (alignment == 1)
1558 return;
1559
1560 _dbus_string_init_const_len (&t, array, len_bytes);
1561 swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
1562}
1563
1564#define MARSHAL_BASIC(typename, byte_order, literal) \
1565 do { \
1566 v_##typename = literal; \
1567 if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename, \
1568 &v_##typename, \
1569 byte_order, NULL)) \
1570 _dbus_test_fatal ("no memory"); \
1571 } while (0)
1572
1573#define DEMARSHAL_BASIC(typename, byte_order) \
1574 do { \
1575 _dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename, \
1576 byte_order, &pos); \
1577 } while (0)
1578
1579#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal) \
1580 do { \
1581 DEMARSHAL_BASIC (typename, byte_order); \
1582 if (literal != v_##typename) \
1583 { \
1584 _dbus_verbose_bytes_of_string (&str, dump_pos, \
1585 _dbus_string_get_length (&str) - dump_pos); \
1586 _dbus_test_fatal ("demarshaled wrong value"); \
1587 } \
1588 } while (0)
1589
1590#define MARSHAL_TEST(typename, byte_order, literal) \
1591 do { \
1592 MARSHAL_BASIC (typename, byte_order, literal); \
1593 dump_pos = pos; \
1594 DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal); \
1595 } while (0)
1596
1597#define MARSHAL_TEST_STRCMP(typename, byte_order, literal) \
1598 do { \
1599 MARSHAL_BASIC (typename, byte_order, literal); \
1600 dump_pos = pos; \
1601 DEMARSHAL_BASIC (typename, byte_order); \
1602 if (strcmp (literal, v_##typename) != 0) \
1603 { \
1604 _dbus_verbose_bytes_of_string (&str, dump_pos, \
1605 _dbus_string_get_length (&str) - dump_pos); \
1606 _dbus_warn ("literal '%s'\nvalue '%s'", literal, v_##typename); \
1607 _dbus_test_fatal ("demarshaled wrong value"); \
1608 } \
1609 } while (0)
1610
1611#define MARSHAL_FIXED_ARRAY(typename, byte_order, literal) \
1612 do { \
1613 int next; \
1614 v_UINT32 = sizeof(literal); \
1615 if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32, \
1616 byte_order, &next)) \
1617 _dbus_test_fatal ("no memory"); \
1618 v_ARRAY_##typename = literal; \
1619 if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename, \
1620 &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal), \
1621 byte_order, NULL)) \
1622 _dbus_test_fatal ("no memory"); \
1623 } while (0)
1624
1625#define DEMARSHAL_FIXED_ARRAY(typename, byte_order) \
1626 do { \
1627 int next; \
1628 alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename); \
1629 v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next); \
1630 _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, \
1631 (const void **) &v_ARRAY_##typename, \
1632 v_UINT32/alignment, \
1633 byte_order, NULL); \
1634 swap_test_array (v_ARRAY_##typename, v_UINT32, \
1635 byte_order, alignment); \
1636 } while (0)
1637
1638#define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal) \
1639 do { \
1640 DEMARSHAL_FIXED_ARRAY (typename, byte_order); \
1641 if (memcmp (literal, v_ARRAY_##typename, sizeof (literal)) != 0) \
1642 { \
1643 _dbus_verbose ("MARSHALED DATA\n"); \
1644 _dbus_verbose_bytes_of_string (&str, dump_pos, \
1645 _dbus_string_get_length (&str) - dump_pos); \
1646 _dbus_verbose ("LITERAL DATA\n"); \
1647 _dbus_verbose_bytes ((const unsigned char *) literal, sizeof (literal), 0); \
1648 _dbus_verbose ("READ DATA\n"); \
1649 _dbus_verbose_bytes ((const unsigned char *) v_ARRAY_##typename, sizeof (literal), 0); \
1650 _dbus_test_fatal ("demarshaled wrong fixed array value"); \
1651 } \
1652 } while (0)
1653
1654#define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal) \
1655 do { \
1656 MARSHAL_FIXED_ARRAY (typename, byte_order, literal); \
1657 dump_pos = pos; \
1658 DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal); \
1659 } while (0)
1660
1662_dbus_marshal_test (const char *test_data_dir _DBUS_GNUC_UNUSED)
1663{
1664 int alignment;
1665 DBusString str;
1666 int pos, dump_pos;
1667 unsigned char array1[5] = { 3, 4, 0, 1, 9 };
1668 dbus_int16_t array2[3] = { 124, 457, 780 };
1669 dbus_uint16_t array2u[3] = { 124, 457, 780 };
1670 dbus_int32_t array4[3] = { 123, 456, 789 };
1671 dbus_uint32_t array4u[3] = { 123, 456, 789 };
1672 dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
1673 DBUS_INT64_CONSTANT (0x456ffffffff),
1674 DBUS_INT64_CONSTANT (0x789ffffffff) };
1675 dbus_int64_t *v_ARRAY_INT64;
1676 unsigned char *v_ARRAY_BYTE;
1677 dbus_int16_t *v_ARRAY_INT16;
1678 dbus_uint16_t *v_ARRAY_UINT16;
1679 dbus_int32_t *v_ARRAY_INT32;
1680 dbus_uint32_t *v_ARRAY_UINT32;
1681 DBusString t;
1682 double v_DOUBLE;
1683 double t_DOUBLE;
1684 dbus_int16_t v_INT16;
1685 dbus_uint16_t v_UINT16;
1686 dbus_int32_t v_INT32;
1687 dbus_uint32_t v_UINT32;
1688 dbus_int64_t v_INT64;
1689 dbus_uint64_t v_UINT64;
1690 unsigned char v_BYTE;
1691 dbus_bool_t v_BOOLEAN;
1692 const char *v_STRING;
1693 const char *v_SIGNATURE;
1694 const char *v_OBJECT_PATH;
1695 int byte_order;
1696
1697 if (!_dbus_string_init (&str))
1698 _dbus_test_fatal ("failed to init string");
1699
1700 pos = 0;
1701
1702 /* Marshal doubles */
1703 MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
1704 DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
1705 t_DOUBLE = 3.14;
1706 if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1707 _dbus_test_fatal ("got wrong double value");
1708
1709 MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
1710 DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
1711 t_DOUBLE = 3.14;
1712 if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
1713 _dbus_test_fatal ("got wrong double value");
1714
1715 /* Marshal signed 16 integers */
1716 MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
1717 MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
1718
1719 /* Marshal unsigned 16 integers */
1720 MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
1721 MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
1722
1723 /* Marshal signed integers */
1724 MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
1725 MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
1726
1727 /* Marshal unsigned integers */
1728 MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
1729 MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
1730
1731 /* Marshal signed integers */
1732 MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1733 MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
1734
1735 /* Marshal unsigned integers */
1736 MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1737 MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
1738
1739 /* Marshal byte */
1740 MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
1741 MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
1742
1743 /* Marshal all possible bools! */
1744 MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
1745 MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
1746 MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
1747 MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
1748
1749 /* Marshal strings */
1750 MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
1751 MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
1752 MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
1753 MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
1754
1755 /* object paths */
1756 MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
1757 MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
1758
1759 /* signatures */
1760 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
1761 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
1762 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
1763 MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
1764
1765 /* Arrays */
1766 MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
1767 MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
1768 MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2u);
1769 MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2u);
1770
1771 MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
1772 MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
1773 MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4u);
1774 MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4u);
1775
1776 MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
1777 MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
1778
1779 MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
1780 MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
1781
1782#if 0
1783
1784 /*
1785 * FIXME restore the set/pack tests
1786 */
1787
1788 /* set/pack 64-bit integers */
1789 _dbus_string_set_length (&str, 8);
1790
1791 /* signed little */
1792 _dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
1793 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1794
1795 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1796 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1797 _dbus_string_get_const_data (&str)));
1798
1799 /* signed big */
1800 _dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
1801 0, DBUS_INT64_CONSTANT (-0x123456789abc7));
1802
1803 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1804 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1805 _dbus_string_get_const_data (&str)));
1806
1807 /* signed little pack */
1808 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1810 _dbus_string_get_data (&str));
1811
1812 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1813 _dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
1814 _dbus_string_get_const_data (&str)));
1815
1816 /* signed big pack */
1817 _dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
1819 _dbus_string_get_data (&str));
1820
1821 _dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
1822 _dbus_unpack_int64 (DBUS_BIG_ENDIAN,
1823 _dbus_string_get_const_data (&str)));
1824
1825 /* unsigned little */
1826 _dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
1827 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1828
1829 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1830 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1831 _dbus_string_get_const_data (&str)));
1832
1833 /* unsigned big */
1834 _dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
1835 0, DBUS_UINT64_CONSTANT (0x123456789abc7));
1836
1837 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1838 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1839 _dbus_string_get_const_data (&str)));
1840
1841 /* unsigned little pack */
1842 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1844 _dbus_string_get_data (&str));
1845
1846 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1847 _dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
1848 _dbus_string_get_const_data (&str)));
1849
1850 /* unsigned big pack */
1851 _dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
1853 _dbus_string_get_data (&str));
1854
1855 _dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
1856 _dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
1857 _dbus_string_get_const_data (&str)));
1858
1859 /* set/pack 32-bit integers */
1860 _dbus_string_set_length (&str, 4);
1861
1862 /* signed little */
1863 _dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
1864 0, -0x123456);
1865
1866 _dbus_assert (-0x123456 ==
1867 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1868 _dbus_string_get_const_data (&str)));
1869
1870 /* signed big */
1871 _dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
1872 0, -0x123456);
1873
1874 _dbus_assert (-0x123456 ==
1875 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1876 _dbus_string_get_const_data (&str)));
1877
1878 /* signed little pack */
1879 _dbus_pack_int32 (-0x123456,
1881 _dbus_string_get_data (&str));
1882
1883 _dbus_assert (-0x123456 ==
1884 _dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
1885 _dbus_string_get_const_data (&str)));
1886
1887 /* signed big pack */
1888 _dbus_pack_int32 (-0x123456,
1890 _dbus_string_get_data (&str));
1891
1892 _dbus_assert (-0x123456 ==
1893 _dbus_unpack_int32 (DBUS_BIG_ENDIAN,
1894 _dbus_string_get_const_data (&str)));
1895
1896 /* unsigned little */
1898 0, 0x123456,
1900
1901 _dbus_assert (0x123456 ==
1903 _dbus_string_get_const_data (&str)));
1904
1905 /* unsigned big */
1907 0, 0x123456,
1909
1910 _dbus_assert (0x123456 ==
1912 _dbus_string_get_const_data (&str)));
1913
1914 /* unsigned little pack */
1915 _dbus_pack_uint32 (0x123456,
1917 _dbus_string_get_data (&str));
1918
1919 _dbus_assert (0x123456 ==
1921 _dbus_string_get_const_data (&str)));
1922
1923 /* unsigned big pack */
1924 _dbus_pack_uint32 (0x123456,
1926 _dbus_string_get_data (&str));
1927
1928 _dbus_assert (0x123456 ==
1930 _dbus_string_get_const_data (&str)));
1931
1932#endif /* set/pack tests for integers */
1933
1934 /* Strings in-place set */
1935 byte_order = DBUS_LITTLE_ENDIAN;
1936 while (TRUE)
1937 {
1938 /* Init a string */
1939 _dbus_string_set_length (&str, 0);
1940
1941 /* reset pos for the macros */
1942 pos = 0;
1943
1944 MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
1945
1946 /* Set it to something longer */
1947 _dbus_string_init_const (&t, "Hello world foo");
1948
1949 v_STRING = _dbus_string_get_const_data (&t);
1951 &v_STRING, byte_order, NULL, NULL);
1952
1954 &v_STRING, byte_order,
1955 NULL);
1956 _dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
1957
1958 /* Set it to something shorter */
1959 _dbus_string_init_const (&t, "Hello");
1960
1961 v_STRING = _dbus_string_get_const_data (&t);
1963 &v_STRING, byte_order, NULL, NULL);
1965 &v_STRING, byte_order,
1966 NULL);
1967 _dbus_assert (strcmp (v_STRING, "Hello") == 0);
1968
1969 /* Do the other byte order */
1970 if (byte_order == DBUS_LITTLE_ENDIAN)
1971 byte_order = DBUS_BIG_ENDIAN;
1972 else
1973 break;
1974 }
1975
1976 /* Clean up */
1977 _dbus_string_free (&str);
1978
1979 return TRUE;
1980}
1981
1982#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_uint16_t _dbus_unpack_uint16(int byte_order, const unsigned char *data)
Unpacks a 16 bit unsigned integer from a data pointer.
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 4, or 8.
void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
void _dbus_pack_uint32(dbus_uint32_t value, int byte_order, unsigned char *data)
Packs a 32 bit unsigned integer into a data pointer.
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
dbus_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
dbus_bool_t _dbus_marshal_write_basic(DBusString *str, int insert_at, int type, const void *value, int byte_order, int *pos_after)
Marshals a basic-typed value.
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
int _dbus_first_type_in_signature_c_str(const char *str, int pos)
Similar to _dbus_first_type_in_signature, but operates on a C string buffer.
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
void _dbus_verbose_bytes(const unsigned char *data, int len, int offset)
If in verbose mode, print a block of binary data.
dbus_bool_t _dbus_marshal_set_basic(DBusString *str, int pos, int type, const void *value, int byte_order, int *old_end_pos, int *new_end_pos)
Sets an existing basic type value to a new value.
void _dbus_marshal_skip_array(const DBusString *str, int element_type, int byte_order, int *pos)
Skips an array, returning the next position.
dbus_bool_t _dbus_marshal_write_fixed_multi(DBusString *str, int insert_at, int element_type, const void *value, int n_elements, int byte_order, int *pos_after)
Marshals a block of values of fixed-length type all at once, as an optimization.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
void _dbus_swap_array(unsigned char *data, int n_elements, int alignment)
Swaps the elements of an array to the opposite byte order.
void _dbus_marshal_skip_basic(const DBusString *str, int type, int byte_order, int *pos)
Skips over a basic-typed value, reporting the following position.
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_MAXIMUM_SIGNATURE_LENGTH
This one is 255 so it fits in a byte.
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition: dbus-protocol.h:66
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition: dbus-protocol.h:74
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_MAXIMUM_ARRAY_LENGTH
Max length of a marshaled array in bytes (64M, 2^26) We use signed int for lengths so must be INT_MAX...
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition: dbus-protocol.h:82
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:53
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition: dbus-protocol.h:90
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition: dbus-protocol.h:98
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition: dbus-protocol.h:94
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition: dbus-protocol.h:78
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition: dbus-protocol.h:54
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
dbus_bool_t dbus_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:845
dbus_bool_t _dbus_string_insert_8_aligned(DBusString *str, int insert_at, const unsigned char octets[8])
Inserts 8 bytes aligned on an 8 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1051
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition: dbus-string.c:2164
dbus_bool_t _dbus_string_insert_alignment(DBusString *str, int *insert_at, int alignment)
Inserts padding at *insert_at such to align it to the given boundary.
Definition: dbus-string.c:1079
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:180
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:195
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1343
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:533
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:215
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
Definition: dbus-string.c:276
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1253
dbus_bool_t _dbus_string_insert_byte(DBusString *str, int i, unsigned char byte)
Inserts a single byte at the given position.
Definition: dbus-string.c:657
dbus_bool_t _dbus_string_insert_4_aligned(DBusString *str, int insert_at, const unsigned char octets[4])
Inserts 4 bytes aligned on a 4 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1027
dbus_bool_t _dbus_string_insert_2_aligned(DBusString *str, int insert_at, const unsigned char octets[2])
Inserts 2 bytes aligned on a 2 byte boundary with any alignment padding initialized to 0.
Definition: dbus-string.c:1003
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1435
dbus_bool_t _dbus_string_replace_len(const DBusString *source, int start, int len, DBusString *dest, int replace_at, int replace_len)
Replaces a segment of dest string with a segment of source string.
Definition: dbus-string.c:1464
#define _DBUS_DOUBLES_BITWISE_EQUAL(a, b)
On x86 there is an 80-bit FPU, and if you do "a == b" it may have a or b in an 80-bit register,...
Definition: dbus-sysdeps.h:632
_DBUS_GNUC_EXTENSION typedef unsigned long dbus_uint64_t
A 64-bit unsigned integer.
#define DBUS_UINT64_CONSTANT(val)
Declare a 64-bit unsigned integer constant.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
short dbus_int16_t
A 16-bit signed integer on all platforms.
#define DBUS_INT64_MODIFIER
A string literal for a length modifier that is appropriate to print the dbus_int64_t and dbus_uint64_...
unsigned short dbus_uint16_t
A 16-bit unsigned integer on all platforms.
#define DBUS_INT64_CONSTANT(val)
Declare a 64-bit signed integer constant.
int dbus_int32_t
A 32-bit signed integer on all platforms.
_DBUS_GNUC_EXTENSION typedef long dbus_int64_t
A 64-bit signed integer.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
An 8-byte struct you could use to access int64 without having int64 support.
Definition: dbus-types.h:143
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:159