#if defined(__GNUC__) && (__GNUC__ >= 4)
# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
_DBUS_STATIC_ASSERT (__extension__ __alignof__ (type) op val)
+# define _DBUS_ASSERT_CMP_ALIGNMENT(left, op, right) \
+ _DBUS_STATIC_ASSERT (__extension__ __alignof__ (left) op __extension__ __alignof__ (right))
#else
/* not gcc, so probably no alignof operator: just use a no-op statement
* that's valid in the same contexts */
# define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
_DBUS_STATIC_ASSERT (TRUE)
+# define _DBUS_ASSERT_CMP_ALIGNMENT(left, op, right) \
+ _DBUS_STATIC_ASSERT (TRUE)
#endif
/* True by definition, but just for completeness... */
_DBUS_ASSERT_ALIGNMENT (dbus_int16_t, <=, 2);
_DBUS_STATIC_ASSERT (sizeof (dbus_uint16_t) == 2);
_DBUS_ASSERT_ALIGNMENT (dbus_uint16_t, <=, 2);
+_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint16_t, ==, dbus_int16_t);
_DBUS_STATIC_ASSERT (sizeof (dbus_int32_t) == 4);
_DBUS_ASSERT_ALIGNMENT (dbus_int32_t, <=, 4);
_DBUS_STATIC_ASSERT (sizeof (dbus_uint32_t) == 4);
_DBUS_ASSERT_ALIGNMENT (dbus_uint32_t, <=, 4);
+_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint32_t, ==, dbus_int32_t);
_DBUS_STATIC_ASSERT (sizeof (dbus_bool_t) == 4);
_DBUS_ASSERT_ALIGNMENT (dbus_bool_t, <=, 4);
+_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint32_t, ==, dbus_bool_t);
_DBUS_STATIC_ASSERT (sizeof (double) == 8);
_DBUS_ASSERT_ALIGNMENT (double, <=, 8);
+/* Doubles might sometimes be more strictly aligned than int64, but we
+ * assume they are no less strictly aligned. This means every (double *)
+ * has enough alignment to be treated as though it was a
+ * (dbus_uint64_t *). */
+_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint64_t, <=, double);
_DBUS_STATIC_ASSERT (sizeof (dbus_int64_t) == 8);
_DBUS_ASSERT_ALIGNMENT (dbus_int64_t, <=, 8);
_DBUS_STATIC_ASSERT (sizeof (dbus_uint64_t) == 8);
_DBUS_ASSERT_ALIGNMENT (dbus_uint64_t, <=, 8);
+_DBUS_ASSERT_CMP_ALIGNMENT (dbus_uint64_t, ==, dbus_int64_t);
_DBUS_STATIC_ASSERT (sizeof (DBusBasicValue) >= 8);
/* The alignment of a DBusBasicValue might conceivably be > 8 because of the
}
static void
-pack_8_octets (DBusBasicValue value,
+pack_8_octets (dbus_uint64_t value,
int byte_order,
unsigned char *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
if ((byte_order) == DBUS_LITTLE_ENDIAN)
- *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value.u64);
+ *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value);
else
- *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value.u64);
+ *((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value);
}
/**
}
static void
-swap_8_octets (DBusBasicValue *value,
+swap_8_octets (dbus_uint64_t *value,
int byte_order)
{
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
{
- value->u64 = DBUS_UINT64_SWAP_LE_BE (value->u64);
+ *value = DBUS_UINT64_SWAP_LE_BE (*value);
}
}
static void
set_8_octets (DBusString *str,
int offset,
- DBusBasicValue value,
+ dbus_uint64_t value,
int byte_order)
{
char *data;
int *old_end_pos,
int *new_end_pos)
{
- const DBusBasicValue *vp;
-
- vp = value;
+ /* Static assertions near the top of this file assert that signed and
+ * unsigned 16- and 32-bit quantities have the same alignment, and that
+ * doubles have alignment at least as strict as unsigned int64, so we
+ * don't have to distinguish further: every (double *)
+ * has strong enough alignment to be treated as though it was a
+ * (dbus_uint64_t *). Going via a (void *) means the compiler should
+ * know that pointers can alias each other. */
+ const unsigned char *u8_p;
+ const dbus_uint16_t *u16_p;
+ const dbus_uint32_t *u32_p;
+ const dbus_uint64_t *u64_p;
+ const char * const *string_p;
switch (type)
{
case DBUS_TYPE_BYTE:
- _dbus_string_set_byte (str, pos, vp->byt);
+ u8_p = value;
+ _dbus_string_set_byte (str, pos, *u8_p);
if (old_end_pos)
*old_end_pos = pos + 1;
if (new_end_pos)
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
+ u16_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 2);
- set_2_octets (str, pos, vp->u16, byte_order);
+ set_2_octets (str, pos, *u16_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 2;
if (new_end_pos)
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_UNIX_FD:
+ u32_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 4);
- set_4_octets (str, pos, vp->u32, byte_order);
+ set_4_octets (str, pos, *u32_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 4;
if (new_end_pos)
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
+ u64_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 8);
- set_8_octets (str, pos, *vp, byte_order);
+ set_8_octets (str, pos, *u64_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 8;
if (new_end_pos)
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
+ string_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 4);
- _dbus_assert (vp->str != NULL);
- return set_string (str, pos, vp->str, byte_order,
+ _dbus_assert (*string_p != NULL);
+ return set_string (str, pos, *string_p, byte_order,
old_end_pos, new_end_pos);
break;
case DBUS_TYPE_SIGNATURE:
- _dbus_assert (vp->str != NULL);
- return set_signature (str, pos, vp->str, byte_order,
+ string_p = value;
+ _dbus_assert (*string_p != NULL);
+ return set_signature (str, pos, *string_p, byte_order,
old_end_pos, new_end_pos);
break;
default:
static dbus_bool_t
marshal_8_octets (DBusString *str,
int insert_at,
- DBusBasicValue value,
+ dbus_uint64_t value,
int byte_order,
int *pos_after)
{
int byte_order,
int *pos_after)
{
- const DBusBasicValue *vp;
+ /* Static assertions near the top of this file assert that signed and
+ * unsigned 16- and 32-bit quantities have the same alignment, and that
+ * doubles have alignment at least as strict as unsigned int64, so we
+ * don't have to distinguish further: every (double *)
+ * has strong enough alignment to be treated as though it was a
+ * (dbus_uint64_t *). Going via a (void *) means the compiler should
+ * know that pointers can alias each other. */
+ const unsigned char *u8_p;
+ const dbus_uint16_t *u16_p;
+ const dbus_uint32_t *u32_p;
+ const dbus_uint64_t *u64_p;
+ const char * const *string_p;
_dbus_assert (dbus_type_is_basic (type));
- vp = value;
-
switch (type)
{
case DBUS_TYPE_BYTE:
- if (!_dbus_string_insert_byte (str, insert_at, vp->byt))
+ u8_p = value;
+ if (!_dbus_string_insert_byte (str, insert_at, *u8_p))
return FALSE;
if (pos_after)
*pos_after = insert_at + 1;
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
- return marshal_2_octets (str, insert_at, vp->u16,
+ u16_p = value;
+ return marshal_2_octets (str, insert_at, *u16_p,
byte_order, pos_after);
break;
case DBUS_TYPE_BOOLEAN:
- return marshal_4_octets (str, insert_at, vp->u32 != FALSE,
+ u32_p = value;
+ return marshal_4_octets (str, insert_at, (*u32_p != FALSE),
byte_order, pos_after);
break;
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_UNIX_FD:
- return marshal_4_octets (str, insert_at, vp->u32,
+ u32_p = value;
+ return marshal_4_octets (str, insert_at, *u32_p,
byte_order, pos_after);
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
- return marshal_8_octets (str, insert_at, *vp, byte_order, pos_after);
+ u64_p = value;
+ return marshal_8_octets (str, insert_at, *u64_p, byte_order, pos_after);
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
- _dbus_assert (vp->str != NULL);
- return marshal_string (str, insert_at, vp->str, byte_order, pos_after);
+ string_p = value;
+ _dbus_assert (*string_p != NULL);
+ return marshal_string (str, insert_at, *string_p, byte_order, pos_after);
break;
case DBUS_TYPE_SIGNATURE:
- _dbus_assert (vp->str != NULL);
- return marshal_signature (str, insert_at, vp->str, pos_after);
+ string_p = value;
+ _dbus_assert (*string_p != NULL);
+ return marshal_signature (str, insert_at, *string_p, pos_after);
break;
default:
_dbus_assert_not_reached ("not a basic type");
static dbus_bool_t
marshal_fixed_multi (DBusString *str,
int insert_at,
- const DBusBasicValue *value,
+ const void *value,
int n_elements,
int byte_order,
int alignment,
int byte_order,
int *pos_after)
{
- const void* vp = *(const DBusBasicValue**)value;
-
+ /* Static assertions near the top of this file assert that signed and
+ * unsigned 16- and 32-bit quantities have the same alignment, and that
+ * doubles have alignment at least as strict as unsigned int64, so we
+ * don't have to distinguish further: every (double *)
+ * has strong enough alignment to be treated as though it was a
+ * (dbus_uint64_t *). Going via a (void *) means the compiler should
+ * know that pointers can alias each other. */
+ const unsigned char * const *u8_pp;
+ const dbus_uint16_t * const *u16_pp;
+ const dbus_uint32_t * const *u32_pp;
+ const dbus_uint64_t * const *u64_pp;
+
_dbus_assert (dbus_type_is_fixed (element_type));
_dbus_assert (n_elements >= 0);
switch (element_type)
{
case DBUS_TYPE_BYTE:
- return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
+ u8_pp = value;
+ return marshal_1_octets_array (str, insert_at, *u8_pp, n_elements, byte_order, pos_after);
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
- return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 2, pos_after);
+ u16_pp = value;
+ return marshal_fixed_multi (str, insert_at, *u16_pp, n_elements, byte_order, 2, pos_after);
case DBUS_TYPE_BOOLEAN:
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_UNIX_FD:
- return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
+ u32_pp = value;
+ return marshal_fixed_multi (str, insert_at, *u32_pp, n_elements, byte_order, 4, pos_after);
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
- return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
+ u64_pp = value;
+ return marshal_fixed_multi (str, insert_at, *u64_pp, n_elements, byte_order, 8, pos_after);
break;
default:
_dbus_marshal_read_fixed_multi (const DBusString *str,
int pos,
int element_type,
- void *value,
+ const void **value,
int n_elements,
int byte_order,
int *new_pos)
array_len = n_elements * alignment;
- *(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
+ *value = _dbus_string_get_const_data_len (str, pos, array_len);
if (new_pos)
*new_pos = pos + array_len;
}
int next; \
alignment = _dbus_type_get_alignment (DBUS_TYPE_##typename); \
v_UINT32 = _dbus_marshal_read_uint32 (&str, dump_pos, byte_order, &next); \
- _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, &v_ARRAY_##typename, \
+ _dbus_marshal_read_fixed_multi (&str, next, DBUS_TYPE_##typename, \
+ (const void **) &v_ARRAY_##typename, \
v_UINT32/alignment, \
byte_order, NULL); \
swap_test_array (v_ARRAY_##typename, v_UINT32, \