dbus-marshal-basic.c
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-marshal-basic.c Marshalling routines for basic (primitive) types
*
* Copyright (C) 2002 CodeFactory AB
* Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
*
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
#include "dbus-internals.h"
#include "dbus-marshal-basic.h"
#include "dbus-signature.h"
#include <dbus/dbus-test-tap.h>
#include <string.h>
#define _DBUS_ASSERT_ALIGNMENT(type, op, val) \
_DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (type) op val)
#define _DBUS_ASSERT_CMP_ALIGNMENT(left, op, right) \
_DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (left) op _DBUS_ALIGNOF (right))
/* True by definition, but just for completeness... */
_DBUS_STATIC_ASSERT (sizeof (char) == 1);
_DBUS_ASSERT_ALIGNMENT (char, ==, 1);
_DBUS_STATIC_ASSERT (sizeof (dbus_int16_t) == 2);
_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
* pointer, so we don't assert about it */
_DBUS_STATIC_ASSERT (sizeof (DBus8ByteStruct) == 8);
_DBUS_ASSERT_ALIGNMENT (DBus8ByteStruct, <=, 8);
static void
pack_2_octets (dbus_uint16_t value,
int byte_order,
void *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
if ((byte_order) == DBUS_LITTLE_ENDIAN)
*((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_LE (value);
else
*((dbus_uint16_t*)(data)) = DBUS_UINT16_TO_BE (value);
}
static void
pack_4_octets (dbus_uint32_t value,
int byte_order,
void *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
if ((byte_order) == DBUS_LITTLE_ENDIAN)
*((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_LE (value);
else
*((dbus_uint32_t*)(data)) = DBUS_UINT32_TO_BE (value);
}
static void
pack_8_octets (dbus_uint64_t value,
int byte_order,
void *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 8) == data);
if ((byte_order) == DBUS_LITTLE_ENDIAN)
*((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_LE (value);
else
*((dbus_uint64_t*)(data)) = DBUS_UINT64_TO_BE (value);
}
void
_dbus_pack_uint32 (dbus_uint32_t value,
int byte_order,
unsigned char *data)
{
pack_4_octets (value, byte_order, data);
}
static void
swap_8_octets (dbus_uint64_t *value,
int byte_order)
{
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
{
*value = DBUS_UINT64_SWAP_LE_BE (*value);
}
}
#ifndef _dbus_unpack_uint16
dbus_uint16_t
_dbus_unpack_uint16 (int byte_order,
const unsigned char *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 2) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_UINT16_FROM_LE (*(dbus_uint16_t *) (void *) data);
else
return DBUS_UINT16_FROM_BE (*(dbus_uint16_t *) (void *) data);
}
#endif /* _dbus_unpack_uint16 */
#ifndef _dbus_unpack_uint32
dbus_uint32_t
_dbus_unpack_uint32 (int byte_order,
const unsigned char *data)
{
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, 4) == data);
if (byte_order == DBUS_LITTLE_ENDIAN)
return DBUS_UINT32_FROM_LE (*(dbus_uint32_t *) (void *) data);
else
return DBUS_UINT32_FROM_BE (*(dbus_uint32_t *) (void *) data);
}
#endif /* _dbus_unpack_uint32 */
static void
set_2_octets (DBusString *str,
int offset,
dbus_uint16_t value,
int byte_order)
{
char *data;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
data = _dbus_string_get_data_len (str, offset, 2);
pack_2_octets (value, byte_order, (unsigned char *) data);
}
static void
set_4_octets (DBusString *str,
int offset,
dbus_uint32_t value,
int byte_order)
{
char *data;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
data = _dbus_string_get_data_len (str, offset, 4);
pack_4_octets (value, byte_order, (unsigned char *) data);
}
static void
set_8_octets (DBusString *str,
int offset,
dbus_uint64_t value,
int byte_order)
{
char *data;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
data = _dbus_string_get_data_len (str, offset, 8);
pack_8_octets (value, byte_order, (unsigned char *) data);
}
void
_dbus_marshal_set_uint32 (DBusString *str,
int pos,
dbus_uint32_t value,
int byte_order)
{
set_4_octets (str, pos, value, byte_order);
}
static dbus_bool_t
set_string (DBusString *str,
int pos,
const char *value,
int byte_order,
int *old_end_pos,
int *new_end_pos)
{
int old_len, new_len;
DBusString dstr;
_dbus_string_init_const (&dstr, value);
_dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned) pos);
old_len = _dbus_unpack_uint32 (byte_order,
_dbus_string_get_const_udata_len (str, pos, 4));
new_len = _dbus_string_get_length (&dstr);
if (!_dbus_string_replace_len (&dstr, 0, new_len,
str, pos + 4, old_len))
return FALSE;
_dbus_marshal_set_uint32 (str, pos, new_len, byte_order);
if (old_end_pos)
*old_end_pos = pos + 4 + old_len + 1;
if (new_end_pos)
*new_end_pos = pos + 4 + new_len + 1;
return TRUE;
}
static dbus_bool_t
set_signature (DBusString *str,
int pos,
const char *value,
int byte_order,
int *old_end_pos,
int *new_end_pos)
{
int old_len, new_len;
DBusString dstr;
_dbus_string_init_const (&dstr, value);
old_len = _dbus_string_get_byte (str, pos);
new_len = _dbus_string_get_length (&dstr);
if (!_dbus_string_replace_len (&dstr, 0, new_len,
str, pos + 1, old_len))
return FALSE;
_dbus_string_set_byte (str, pos, new_len);
if (old_end_pos)
*old_end_pos = pos + 1 + old_len + 1;
if (new_end_pos)
*new_end_pos = pos + 1 + new_len + 1;
return TRUE;
}
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)
{
/* 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:
u8_p = value;
_dbus_string_set_byte (str, pos, *u8_p);
if (old_end_pos)
*old_end_pos = pos + 1;
if (new_end_pos)
*new_end_pos = pos + 1;
return TRUE;
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
u16_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 2);
set_2_octets (str, pos, *u16_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 2;
if (new_end_pos)
*new_end_pos = pos + 2;
return TRUE;
break;
case DBUS_TYPE_BOOLEAN:
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, *u32_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 4;
if (new_end_pos)
*new_end_pos = pos + 4;
return TRUE;
break;
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, *u64_p, byte_order);
if (old_end_pos)
*old_end_pos = pos + 8;
if (new_end_pos)
*new_end_pos = pos + 8;
return TRUE;
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
string_p = value;
pos = _DBUS_ALIGN_VALUE (pos, 4);
_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:
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:
_dbus_assert_not_reached ("not a basic type");
return FALSE;
break;
}
}
dbus_uint32_t
_dbus_marshal_read_uint32 (const DBusString *str,
int pos,
int byte_order,
int *new_pos)
{
pos = _DBUS_ALIGN_VALUE (pos, 4);
if (new_pos)
*new_pos = pos + 4;
_dbus_assert (pos + 4 <= _dbus_string_get_length (str));
return _dbus_unpack_uint32 (byte_order,
_dbus_string_get_const_udata (str) + pos);
}
void
_dbus_marshal_read_basic (const DBusString *str,
int pos,
int type,
void *value,
int byte_order,
int *new_pos)
{
const char *str_data;
_dbus_assert (dbus_type_is_basic (type));
str_data = _dbus_string_get_const_data (str);
/* Below we volatile types to avoid aliasing issues;
* see http://bugs.freedesktop.org/show_bug.cgi?id=20137
*/
switch (type)
{
case DBUS_TYPE_BYTE:
{
volatile unsigned char *vp = value;
*vp = (unsigned char) _dbus_string_get_byte (str, pos);
(pos)++;
}
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
{
volatile dbus_uint16_t *vp = value;
pos = _DBUS_ALIGN_VALUE (pos, 2);
*vp = *(dbus_uint16_t *) (void *) (str_data + pos);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
*vp = DBUS_UINT16_SWAP_LE_BE (*vp);
pos += 2;
}
break;
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_BOOLEAN:
case DBUS_TYPE_UNIX_FD:
{
volatile dbus_uint32_t *vp = value;
pos = _DBUS_ALIGN_VALUE (pos, 4);
*vp = *(dbus_uint32_t *) (void *) (str_data + pos);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
*vp = DBUS_UINT32_SWAP_LE_BE (*vp);
pos += 4;
}
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
{
volatile dbus_uint64_t *vp = value;
pos = _DBUS_ALIGN_VALUE (pos, 8);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
*vp = DBUS_UINT64_SWAP_LE_BE (
*(dbus_uint64_t *) (void *) (str_data + pos));
else
*vp = *(dbus_uint64_t *) (void *) (str_data + pos);
pos += 8;
}
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
{
int len;
volatile char **vp = value;
len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
*vp = (char*) str_data + pos;
pos += len + 1; /* length plus nul */
}
break;
case DBUS_TYPE_SIGNATURE:
{
int len;
volatile char **vp = value;
len = _dbus_string_get_byte (str, pos);
pos += 1;
*vp = (char*) str_data + pos;
pos += len + 1; /* length plus nul */
}
break;
default:
_dbus_warn_check_failed ("type %s %d not a basic type",
_dbus_type_to_string (type), type);
_dbus_assert_not_reached ("not a basic type");
break;
}
if (new_pos)
*new_pos = pos;
}
static dbus_bool_t
marshal_2_octets (DBusString *str,
int insert_at,
dbus_uint16_t value,
int byte_order,
int *pos_after)
{
dbus_bool_t retval;
int orig_len;
_DBUS_STATIC_ASSERT (sizeof (value) == 2);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
value = DBUS_UINT16_SWAP_LE_BE (value);
orig_len = _dbus_string_get_length (str);
retval = _dbus_string_insert_2_aligned (str, insert_at,
(const unsigned char *)&value);
if (pos_after)
{
*pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
_dbus_assert (*pos_after <= _dbus_string_get_length (str));
}
return retval;
}
static dbus_bool_t
marshal_4_octets (DBusString *str,
int insert_at,
dbus_uint32_t value,
int byte_order,
int *pos_after)
{
dbus_bool_t retval;
int orig_len;
_DBUS_STATIC_ASSERT (sizeof (value) == 4);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
value = DBUS_UINT32_SWAP_LE_BE (value);
orig_len = _dbus_string_get_length (str);
retval = _dbus_string_insert_4_aligned (str, insert_at,
(const unsigned char *)&value);
if (pos_after)
{
*pos_after = insert_at + (_dbus_string_get_length (str) - orig_len);
_dbus_assert (*pos_after <= _dbus_string_get_length (str));
}
return retval;
}
static dbus_bool_t
marshal_8_octets (DBusString *str,
int insert_at,
dbus_uint64_t value,
int byte_order,
int *pos_after)
{
dbus_bool_t retval;
int orig_len;
_DBUS_STATIC_ASSERT (sizeof (value) == 8);
swap_8_octets (&value, byte_order);
orig_len = _dbus_string_get_length (str);
retval = _dbus_string_insert_8_aligned (str, insert_at,
(const unsigned char *)&value);
if (pos_after)
*pos_after = insert_at + _dbus_string_get_length (str) - orig_len;
return retval;
}
enum
{
MARSHAL_AS_STRING,
MARSHAL_AS_SIGNATURE,
MARSHAL_AS_BYTE_ARRAY
};
static dbus_bool_t
marshal_len_followed_by_bytes (int marshal_as,
DBusString *str,
int insert_at,
const unsigned char *value,
int data_len, /* doesn't include nul if any */
int byte_order,
int *pos_after)
{
int pos;
DBusString value_str;
int value_len;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
if (insert_at > _dbus_string_get_length (str))
_dbus_warn ("insert_at = %d string len = %d data_len = %d",
insert_at, _dbus_string_get_length (str), data_len);
if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
value_len = data_len;
else
value_len = data_len + 1; /* value has a nul */
_dbus_string_init_const_len (&value_str, (const char *) value, value_len);
pos = insert_at;
if (marshal_as == MARSHAL_AS_SIGNATURE)
{
_dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
_dbus_assert (data_len <= 255); /* same as max sig len right now */
if (!_dbus_string_insert_byte (str, pos, data_len))
goto oom;
pos += 1;
}
else
{
if (!marshal_4_octets (str, pos, data_len,
byte_order, &pos))
goto oom;
}
if (!_dbus_string_copy_len (&value_str, 0, value_len,
str, pos))
goto oom;
#if 0
/* too expensive */
_dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
str, pos));
_dbus_verbose_bytes_of_string (str, pos, value_len);
#endif
pos += value_len;
if (pos_after)
*pos_after = pos;
return TRUE;
oom:
/* Delete what we've inserted */
_dbus_string_delete (str, insert_at, pos - insert_at);
return FALSE;
}
static dbus_bool_t
marshal_string (DBusString *str,
int insert_at,
const char *value,
int byte_order,
int *pos_after)
{
return marshal_len_followed_by_bytes (MARSHAL_AS_STRING,
str, insert_at, (const unsigned char *) value,
strlen (value),
byte_order, pos_after);
}
static dbus_bool_t
marshal_signature (DBusString *str,
int insert_at,
const char *value,
int *pos_after)
{
return marshal_len_followed_by_bytes (MARSHAL_AS_SIGNATURE,
str, insert_at, (const unsigned char *) value,
strlen (value),
DBUS_COMPILER_BYTE_ORDER, /* irrelevant */
pos_after);
}
dbus_bool_t
_dbus_marshal_write_basic (DBusString *str,
int insert_at,
int type,
const void *value,
int byte_order,
int *pos_after)
{
/* 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));
switch (type)
{
case DBUS_TYPE_BYTE:
u8_p = value;
if (!_dbus_string_insert_byte (str, insert_at, *u8_p))
return FALSE;
if (pos_after)
*pos_after = insert_at + 1;
return TRUE;
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
u16_p = value;
return marshal_2_octets (str, insert_at, *u16_p,
byte_order, pos_after);
break;
case DBUS_TYPE_BOOLEAN:
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:
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:
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:
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:
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");
return FALSE;
break;
}
}
static dbus_bool_t
marshal_1_octets_array (DBusString *str,
int insert_at,
const unsigned char *value,
int n_elements,
int byte_order,
int *pos_after)
{
int pos;
DBusString value_str;
_dbus_string_init_const_len (&value_str, (const char *) value, n_elements);
pos = insert_at;
if (!_dbus_string_copy_len (&value_str, 0, n_elements,
str, pos))
return FALSE;
pos += n_elements;
if (pos_after)
*pos_after = pos;
return TRUE;
}
void
_dbus_swap_array (unsigned char *data,
int n_elements,
int alignment)
{
void *d;
void *end;
_dbus_assert (_DBUS_ALIGN_ADDRESS (data, alignment) == data);
/* we use const_data and cast it off so DBusString can be a const string
* for the unit tests. don't ask.
*/
d = data;
end = data + (n_elements * alignment);
if (alignment == 8)
{
while (d != end)
{
*((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
d = ((unsigned char *) d) + 8;
}
}
else if (alignment == 4)
{
while (d != end)
{
*((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
d = ((unsigned char *) d) + 4;
}
}
else
{
_dbus_assert (alignment == 2);
while (d != end)
{
*((dbus_uint16_t*)d) = DBUS_UINT16_SWAP_LE_BE (*((dbus_uint16_t*)d));
d = ((unsigned char *) d) + 2;
}
}
}
static void
swap_array (DBusString *str,
int array_start,
int n_elements,
int byte_order,
int alignment)
{
_dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
{
/* we use const_data and cast it off so DBusString can be a const string
* for the unit tests. don't ask.
*/
_dbus_swap_array ((unsigned char*) (_dbus_string_get_const_data (str) + array_start),
n_elements, alignment);
}
}
static dbus_bool_t
marshal_fixed_multi (DBusString *str,
int insert_at,
const void *value,
int n_elements,
int byte_order,
int alignment,
int *pos_after)
{
int old_string_len;
int array_start;
DBusString t;
int len_in_bytes;
_dbus_assert (n_elements <= DBUS_MAXIMUM_ARRAY_LENGTH / alignment);
old_string_len = _dbus_string_get_length (str);
len_in_bytes = n_elements * alignment;
array_start = insert_at;
/* Note that we do alignment padding unconditionally
* even if the array is empty; this means that
* padding + len is always equal to the number of bytes
* in the array.
*/
if (!_dbus_string_insert_alignment (str, &array_start, alignment))
goto error;
_dbus_string_init_const_len (&t,
(const char *) value,
len_in_bytes);
if (!_dbus_string_copy (&t, 0,
str, array_start))
goto error;
swap_array (str, array_start, n_elements, byte_order, alignment);
if (pos_after)
*pos_after = array_start + len_in_bytes;
return TRUE;
error:
_dbus_string_delete (str, insert_at,
_dbus_string_get_length (str) - old_string_len);
return FALSE;
}
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)
{
/* 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);
#if 0
_dbus_verbose ("writing %d elements of %s\n",
n_elements, _dbus_type_to_string (element_type));
#endif
switch (element_type)
{
case DBUS_TYPE_BYTE:
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:
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:
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:
u64_pp = value;
return marshal_fixed_multi (str, insert_at, *u64_pp, n_elements, byte_order, 8, pos_after);
break;
default:
_dbus_assert_not_reached ("non fixed type in array write");
break;
}
return FALSE;
}
void
_dbus_marshal_skip_basic (const DBusString *str,
int type,
int byte_order,
int *pos)
{
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
switch (type)
{
case DBUS_TYPE_BYTE:
(*pos)++;
break;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
/* Advance to the next suitably-aligned position >= *pos */
*pos = _DBUS_ALIGN_VALUE (*pos, 2);
*pos += 2;
break;
case DBUS_TYPE_BOOLEAN:
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_UNIX_FD:
*pos = _DBUS_ALIGN_VALUE (*pos, 4);
*pos += 4;
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
*pos = _DBUS_ALIGN_VALUE (*pos, 8);
*pos += 8;
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
{
int len;
/* Let len be the number of bytes of string data, and advance
* *pos to just after the length */
len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
*pos += len + 1; /* length plus nul */
}
break;
case DBUS_TYPE_SIGNATURE:
{
int len;
len = _dbus_string_get_byte (str, *pos);
*pos += len + 2; /* length byte plus length plus nul */
}
break;
default:
_dbus_warn ("type %s not a basic type",
_dbus_type_to_string (type));
_dbus_assert_not_reached ("not a basic type");
break;
}
/* We had better still be in-bounds at this point (pointing either into
* the content of the string, or 1 past the logical length of the string) */
_dbus_assert (*pos <= _dbus_string_get_length (str));
}
void
_dbus_marshal_skip_array (const DBusString *str,
int element_type,
int byte_order,
int *pos)
{
dbus_uint32_t array_len;
int i;
int alignment;
/* Advance to the next 4-byte-aligned position >= *pos */
i = _DBUS_ALIGN_VALUE (*pos, 4);
/* Let array_len be the number of bytes of array data, and advance
* i to just after the length */
array_len = _dbus_marshal_read_uint32 (str, i, byte_order, &i);
/* If the element type is more strictly-aligned than the length,
* advance i to the next suitably-aligned position
* (in other words, skip the padding) */
alignment = _dbus_type_get_alignment (element_type);
i = _DBUS_ALIGN_VALUE (i, alignment);
/* Skip the actual array data */
*pos = i + array_len;
/* We had better still be in-bounds at this point (pointing either into
* the content of the string, or 1 past the logical length of the string) */
_dbus_assert (*pos <= _dbus_string_get_length (str));
}
int
_dbus_type_get_alignment (int typecode)
{
switch (typecode)
{
case DBUS_TYPE_BYTE:
case DBUS_TYPE_VARIANT:
case DBUS_TYPE_SIGNATURE:
return 1;
case DBUS_TYPE_INT16:
case DBUS_TYPE_UINT16:
return 2;
case DBUS_TYPE_BOOLEAN:
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_UNIX_FD:
/* this stuff is 4 since it starts with a length */
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_ARRAY:
return 4;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
/* struct is 8 since it could contain an 8-aligned item
* and it's simpler to just always align structs to 8;
* we want the amount of padding in a struct of a given
* type to be predictable, not location-dependent.
* DICT_ENTRY is always the same as struct.
*/
case DBUS_TYPE_STRUCT:
case DBUS_TYPE_DICT_ENTRY:
return 8;
default:
_dbus_assert_not_reached ("unknown typecode in _dbus_type_get_alignment()");
return 0;
}
}
const char *
_dbus_type_to_string (int typecode)
{
switch (typecode)
{
case DBUS_TYPE_INVALID:
return "invalid";
case DBUS_TYPE_BOOLEAN:
return "boolean";
case DBUS_TYPE_BYTE:
return "byte";
case DBUS_TYPE_INT16:
return "int16";
case DBUS_TYPE_UINT16:
return "uint16";
case DBUS_TYPE_INT32:
return "int32";
case DBUS_TYPE_UINT32:
return "uint32";
case DBUS_TYPE_INT64:
return "int64";
case DBUS_TYPE_UINT64:
return "uint64";
case DBUS_TYPE_DOUBLE:
return "double";
case DBUS_TYPE_STRING:
return "string";
case DBUS_TYPE_OBJECT_PATH:
return "object_path";
case DBUS_TYPE_SIGNATURE:
return "signature";
case DBUS_TYPE_STRUCT:
return "struct";
case DBUS_TYPE_DICT_ENTRY:
return "dict_entry";
case DBUS_TYPE_ARRAY:
return "array";
case DBUS_TYPE_VARIANT:
return "variant";
case DBUS_STRUCT_BEGIN_CHAR:
return "begin_struct";
case DBUS_STRUCT_END_CHAR:
return "end_struct";
case DBUS_DICT_ENTRY_BEGIN_CHAR:
return "begin_dict_entry";
case DBUS_DICT_ENTRY_END_CHAR:
return "end_dict_entry";
case DBUS_TYPE_UNIX_FD:
return "unix_fd";
default:
return "unknown";
}
}
void
_dbus_verbose_bytes (const unsigned char *data,
int len,
int offset)
{
int i;
const unsigned char *aligned;
_dbus_assert (len >= 0);
if (!_dbus_is_verbose())
return;
/* Print blanks on first row if appropriate */
aligned = _DBUS_ALIGN_ADDRESS (data, 4);
if (aligned > data)
aligned -= 4;
_dbus_assert (aligned <= data);
if (aligned != data)
{
_dbus_verbose ("%4ld\t%p: ", - (long)(data - aligned), aligned);
while (aligned != data)
{
_dbus_verbose (" ");
++aligned;
}
}
/* now print the bytes */
i = 0;
while (i < len)
{
if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
_dbus_verbose ("%4d\t%p: ",
offset + i, &data[i]);
}
if (data[i] >= 32 &&
data[i] <= 126)
_dbus_verbose (" '%c' ", data[i]);
else
_dbus_verbose ("0x%s%x ",
data[i] <= 0xf ? "0" : "", data[i]);
++i;
if (_DBUS_ALIGN_ADDRESS (&data[i], 4) == &data[i])
{
if (i > 3)
_dbus_verbose ("BE: %d LE: %d",
_dbus_unpack_uint32 (DBUS_BIG_ENDIAN, &data[i-4]),
_dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN, &data[i-4]));
if (i > 7 &&
_DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
{
_dbus_verbose (" u64: 0x%" DBUS_INT64_MODIFIER "x",
*(dbus_uint64_t *) (void *) &data[i - 8]);
_dbus_verbose (" dbl: %g", *(double *) (void *) &data[i - 8]);
}
_dbus_verbose ("\n");
}
}
_dbus_verbose ("\n");
}
void
_dbus_verbose_bytes_of_string (const DBusString *str,
int start,
int len)
{
const char *d;
int real_len;
real_len = _dbus_string_get_length (str);
_dbus_assert (start >= 0);
if (start > real_len)
{
_dbus_verbose (" [%d,%d) is not inside string of length %d\n",
start, len, real_len);
return;
}
if ((start + len) > real_len)
{
_dbus_verbose (" [%d,%d) extends outside string of length %d\n",
start, len, real_len);
len = real_len - start;
}
d = _dbus_string_get_const_data_len (str, start, len);
_dbus_verbose_bytes ((const unsigned char *) d, len, start);
}
static int
map_type_char_to_type (int t)
{
if (t == DBUS_STRUCT_BEGIN_CHAR)
return DBUS_TYPE_STRUCT;
else if (t == DBUS_DICT_ENTRY_BEGIN_CHAR)
return DBUS_TYPE_DICT_ENTRY;
else
{
_dbus_assert (t != DBUS_STRUCT_END_CHAR);
_dbus_assert (t != DBUS_DICT_ENTRY_END_CHAR);
return t;
}
}
int
_dbus_first_type_in_signature (const DBusString *str,
int pos)
{
return map_type_char_to_type (_dbus_string_get_byte (str, pos));
}
int
_dbus_first_type_in_signature_c_str (const char *str,
int pos)
{
return map_type_char_to_type (str[pos]);
}
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
#include "dbus-test.h"
#include <stdio.h>
void
_dbus_marshal_read_fixed_multi (const DBusString *str,
int pos,
int element_type,
const void **value,
int n_elements,
int byte_order,
int *new_pos)
{
int array_len;
int alignment;
_dbus_assert (dbus_type_is_fixed (element_type));
_dbus_assert (dbus_type_is_basic (element_type));
#if 0
_dbus_verbose ("reading %d elements of %s\n",
n_elements, _dbus_type_to_string (element_type));
#endif
alignment = _dbus_type_get_alignment (element_type);
pos = _DBUS_ALIGN_VALUE (pos, alignment);
array_len = n_elements * alignment;
*value = _dbus_string_get_const_data_len (str, pos, array_len);
if (new_pos)
*new_pos = pos + array_len;
}
static void
swap_test_array (void *array,
int len_bytes,
int byte_order,
int alignment)
{
DBusString t;
if (alignment == 1)
return;
_dbus_string_init_const_len (&t, array, len_bytes);
swap_array (&t, 0, len_bytes / alignment, byte_order, alignment);
}
#define MARSHAL_BASIC(typename, byte_order, literal) \
do { \
v_##typename = literal; \
if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_##typename, \
&v_##typename, \
byte_order, NULL)) \
_dbus_test_fatal ("no memory"); \
} while (0)
#define DEMARSHAL_BASIC(typename, byte_order) \
do { \
_dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename, \
byte_order, &pos); \
} while (0)
#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal) \
do { \
DEMARSHAL_BASIC (typename, byte_order); \
if (literal != v_##typename) \
{ \
_dbus_verbose_bytes_of_string (&str, dump_pos, \
_dbus_string_get_length (&str) - dump_pos); \
_dbus_test_fatal ("demarshaled wrong value"); \
} \
} while (0)
#define MARSHAL_TEST(typename, byte_order, literal) \
do { \
MARSHAL_BASIC (typename, byte_order, literal); \
dump_pos = pos; \
DEMARSHAL_BASIC_AND_CHECK (typename, byte_order, literal); \
} while (0)
#define MARSHAL_TEST_STRCMP(typename, byte_order, literal) \
do { \
MARSHAL_BASIC (typename, byte_order, literal); \
dump_pos = pos; \
DEMARSHAL_BASIC (typename, byte_order); \
if (strcmp (literal, v_##typename) != 0) \
{ \
_dbus_verbose_bytes_of_string (&str, dump_pos, \
_dbus_string_get_length (&str) - dump_pos); \
_dbus_warn ("literal '%s'\nvalue '%s'", literal, v_##typename); \
_dbus_test_fatal ("demarshaled wrong value"); \
} \
} while (0)
#define MARSHAL_FIXED_ARRAY(typename, byte_order, literal) \
do { \
int next; \
v_UINT32 = sizeof(literal); \
if (!_dbus_marshal_write_basic (&str, pos, DBUS_TYPE_UINT32, &v_UINT32, \
byte_order, &next)) \
_dbus_test_fatal ("no memory"); \
v_ARRAY_##typename = literal; \
if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename, \
&v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal), \
byte_order, NULL)) \
_dbus_test_fatal ("no memory"); \
} while (0)
#define DEMARSHAL_FIXED_ARRAY(typename, byte_order) \
do { \
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, \
(const void **) &v_ARRAY_##typename, \
v_UINT32/alignment, \
byte_order, NULL); \
swap_test_array (v_ARRAY_##typename, v_UINT32, \
byte_order, alignment); \
} while (0)
#define DEMARSHAL_FIXED_ARRAY_AND_CHECK(typename, byte_order, literal) \
do { \
DEMARSHAL_FIXED_ARRAY (typename, byte_order); \
if (memcmp (literal, v_ARRAY_##typename, sizeof (literal)) != 0) \
{ \
_dbus_verbose ("MARSHALED DATA\n"); \
_dbus_verbose_bytes_of_string (&str, dump_pos, \
_dbus_string_get_length (&str) - dump_pos); \
_dbus_verbose ("LITERAL DATA\n"); \
_dbus_verbose_bytes ((const unsigned char *) literal, sizeof (literal), 0); \
_dbus_verbose ("READ DATA\n"); \
_dbus_verbose_bytes ((const unsigned char *) v_ARRAY_##typename, sizeof (literal), 0); \
_dbus_test_fatal ("demarshaled wrong fixed array value"); \
} \
} while (0)
#define MARSHAL_TEST_FIXED_ARRAY(typename, byte_order, literal) \
do { \
MARSHAL_FIXED_ARRAY (typename, byte_order, literal); \
dump_pos = pos; \
DEMARSHAL_FIXED_ARRAY_AND_CHECK (typename, byte_order, literal); \
} while (0)
dbus_bool_t
_dbus_marshal_test (const char *test_data_dir _DBUS_GNUC_UNUSED)
{
int alignment;
DBusString str;
int pos, dump_pos;
unsigned char array1[5] = { 3, 4, 0, 1, 9 };
dbus_int16_t array2[3] = { 124, 457, 780 };
dbus_uint16_t array2u[3] = { 124, 457, 780 };
dbus_int32_t array4[3] = { 123, 456, 789 };
dbus_uint32_t array4u[3] = { 123, 456, 789 };
dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
DBUS_INT64_CONSTANT (0x456ffffffff),
DBUS_INT64_CONSTANT (0x789ffffffff) };
dbus_int64_t *v_ARRAY_INT64;
unsigned char *v_ARRAY_BYTE;
dbus_int16_t *v_ARRAY_INT16;
dbus_uint16_t *v_ARRAY_UINT16;
dbus_int32_t *v_ARRAY_INT32;
dbus_uint32_t *v_ARRAY_UINT32;
DBusString t;
double v_DOUBLE;
double t_DOUBLE;
dbus_int16_t v_INT16;
dbus_uint16_t v_UINT16;
dbus_int32_t v_INT32;
dbus_uint32_t v_UINT32;
dbus_int64_t v_INT64;
dbus_uint64_t v_UINT64;
unsigned char v_BYTE;
dbus_bool_t v_BOOLEAN;
const char *v_STRING;
const char *v_SIGNATURE;
const char *v_OBJECT_PATH;
int byte_order;
if (!_dbus_string_init (&str))
_dbus_test_fatal ("failed to init string");
pos = 0;
/* Marshal doubles */
MARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN, 3.14);
DEMARSHAL_BASIC (DOUBLE, DBUS_BIG_ENDIAN);
t_DOUBLE = 3.14;
if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
_dbus_test_fatal ("got wrong double value");
MARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN, 3.14);
DEMARSHAL_BASIC (DOUBLE, DBUS_LITTLE_ENDIAN);
t_DOUBLE = 3.14;
if (!_DBUS_DOUBLES_BITWISE_EQUAL (t_DOUBLE, v_DOUBLE))
_dbus_test_fatal ("got wrong double value");
/* Marshal signed 16 integers */
MARSHAL_TEST (INT16, DBUS_BIG_ENDIAN, -12345);
MARSHAL_TEST (INT16, DBUS_LITTLE_ENDIAN, -12345);
/* Marshal unsigned 16 integers */
MARSHAL_TEST (UINT16, DBUS_BIG_ENDIAN, 0x1234);
MARSHAL_TEST (UINT16, DBUS_LITTLE_ENDIAN, 0x1234);
/* Marshal signed integers */
MARSHAL_TEST (INT32, DBUS_BIG_ENDIAN, -12345678);
MARSHAL_TEST (INT32, DBUS_LITTLE_ENDIAN, -12345678);
/* Marshal unsigned integers */
MARSHAL_TEST (UINT32, DBUS_BIG_ENDIAN, 0x12345678);
MARSHAL_TEST (UINT32, DBUS_LITTLE_ENDIAN, 0x12345678);
/* Marshal signed integers */
MARSHAL_TEST (INT64, DBUS_BIG_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
MARSHAL_TEST (INT64, DBUS_LITTLE_ENDIAN, DBUS_INT64_CONSTANT (-0x123456789abc7));
/* Marshal unsigned integers */
MARSHAL_TEST (UINT64, DBUS_BIG_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
MARSHAL_TEST (UINT64, DBUS_LITTLE_ENDIAN, DBUS_UINT64_CONSTANT (0x123456789abc7));
/* Marshal byte */
MARSHAL_TEST (BYTE, DBUS_BIG_ENDIAN, 5);
MARSHAL_TEST (BYTE, DBUS_LITTLE_ENDIAN, 5);
/* Marshal all possible bools! */
MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, FALSE);
MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, FALSE);
MARSHAL_TEST (BOOLEAN, DBUS_BIG_ENDIAN, TRUE);
MARSHAL_TEST (BOOLEAN, DBUS_LITTLE_ENDIAN, TRUE);
/* Marshal strings */
MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "");
MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "");
MARSHAL_TEST_STRCMP (STRING, DBUS_BIG_ENDIAN, "This is the dbus test string");
MARSHAL_TEST_STRCMP (STRING, DBUS_LITTLE_ENDIAN, "This is the dbus test string");
/* object paths */
MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_BIG_ENDIAN, "/a/b/c");
MARSHAL_TEST_STRCMP (OBJECT_PATH, DBUS_LITTLE_ENDIAN, "/a/b/c");
/* signatures */
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "");
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "");
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
/* Arrays */
MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_BIG_ENDIAN, array2);
MARSHAL_TEST_FIXED_ARRAY (INT16, DBUS_LITTLE_ENDIAN, array2);
MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_BIG_ENDIAN, array2u);
MARSHAL_TEST_FIXED_ARRAY (UINT16, DBUS_LITTLE_ENDIAN, array2u);
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_BIG_ENDIAN, array4u);
MARSHAL_TEST_FIXED_ARRAY (UINT32, DBUS_LITTLE_ENDIAN, array4u);
MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
#if 0
/*
* FIXME restore the set/pack tests
*/
/* set/pack 64-bit integers */
_dbus_string_set_length (&str, 8);
/* signed little */
_dbus_marshal_set_int64 (&str, DBUS_LITTLE_ENDIAN,
0, DBUS_INT64_CONSTANT (-0x123456789abc7));
_dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
_dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed big */
_dbus_marshal_set_int64 (&str, DBUS_BIG_ENDIAN,
0, DBUS_INT64_CONSTANT (-0x123456789abc7));
_dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
_dbus_unpack_int64 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed little pack */
_dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
DBUS_LITTLE_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
_dbus_unpack_int64 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed big pack */
_dbus_pack_int64 (DBUS_INT64_CONSTANT (-0x123456789abc7),
DBUS_BIG_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (DBUS_INT64_CONSTANT (-0x123456789abc7) ==
_dbus_unpack_int64 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned little */
_dbus_marshal_set_uint64 (&str, DBUS_LITTLE_ENDIAN,
0, DBUS_UINT64_CONSTANT (0x123456789abc7));
_dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
_dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned big */
_dbus_marshal_set_uint64 (&str, DBUS_BIG_ENDIAN,
0, DBUS_UINT64_CONSTANT (0x123456789abc7));
_dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
_dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned little pack */
_dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
DBUS_LITTLE_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
_dbus_unpack_uint64 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned big pack */
_dbus_pack_uint64 (DBUS_UINT64_CONSTANT (0x123456789abc7),
DBUS_BIG_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (DBUS_UINT64_CONSTANT (0x123456789abc7) ==
_dbus_unpack_uint64 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* set/pack 32-bit integers */
_dbus_string_set_length (&str, 4);
/* signed little */
_dbus_marshal_set_int32 (&str, DBUS_LITTLE_ENDIAN,
0, -0x123456);
_dbus_assert (-0x123456 ==
_dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed big */
_dbus_marshal_set_int32 (&str, DBUS_BIG_ENDIAN,
0, -0x123456);
_dbus_assert (-0x123456 ==
_dbus_unpack_int32 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed little pack */
_dbus_pack_int32 (-0x123456,
DBUS_LITTLE_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (-0x123456 ==
_dbus_unpack_int32 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* signed big pack */
_dbus_pack_int32 (-0x123456,
DBUS_BIG_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (-0x123456 ==
_dbus_unpack_int32 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned little */
_dbus_marshal_set_uint32 (&str,
0, 0x123456,
DBUS_LITTLE_ENDIAN);
_dbus_assert (0x123456 ==
_dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned big */
_dbus_marshal_set_uint32 (&str,
0, 0x123456,
DBUS_BIG_ENDIAN);
_dbus_assert (0x123456 ==
_dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned little pack */
_dbus_pack_uint32 (0x123456,
DBUS_LITTLE_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (0x123456 ==
_dbus_unpack_uint32 (DBUS_LITTLE_ENDIAN,
_dbus_string_get_const_data (&str)));
/* unsigned big pack */
_dbus_pack_uint32 (0x123456,
DBUS_BIG_ENDIAN,
_dbus_string_get_data (&str));
_dbus_assert (0x123456 ==
_dbus_unpack_uint32 (DBUS_BIG_ENDIAN,
_dbus_string_get_const_data (&str)));
#endif /* set/pack tests for integers */
/* Strings in-place set */
byte_order = DBUS_LITTLE_ENDIAN;
while (TRUE)
{
/* Init a string */
_dbus_string_set_length (&str, 0);
/* reset pos for the macros */
pos = 0;
MARSHAL_TEST_STRCMP (STRING, byte_order, "Hello world");
/* Set it to something longer */
_dbus_string_init_const (&t, "Hello world foo");
v_STRING = _dbus_string_get_const_data (&t);
_dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
&v_STRING, byte_order, NULL, NULL);
_dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
&v_STRING, byte_order,
NULL);
_dbus_assert (strcmp (v_STRING, "Hello world foo") == 0);
/* Set it to something shorter */
_dbus_string_init_const (&t, "Hello");
v_STRING = _dbus_string_get_const_data (&t);
_dbus_marshal_set_basic (&str, 0, DBUS_TYPE_STRING,
&v_STRING, byte_order, NULL, NULL);
_dbus_marshal_read_basic (&str, 0, DBUS_TYPE_STRING,
&v_STRING, byte_order,
NULL);
_dbus_assert (strcmp (v_STRING, "Hello") == 0);
/* Do the other byte order */
if (byte_order == DBUS_LITTLE_ENDIAN)
byte_order = DBUS_BIG_ENDIAN;
else
break;
}
/* Clean up */
_dbus_string_free (&str);
return TRUE;
}
#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition dbus-internals.h:164
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
_dbus_warn_check_failed
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...
Definition dbus-internals.c:310
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition dbus-internals.c:278
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:51
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
_dbus_unpack_uint16
dbus_uint16_t _dbus_unpack_uint16(int byte_order, const unsigned char *data)
Unpacks a 16 bit unsigned integer from a data pointer.
Definition dbus-marshal-basic.c:168
_dbus_type_get_alignment
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 2, 4, or 8.
Definition dbus-marshal-basic.c:1244
_dbus_verbose_bytes_of_string
void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
Definition dbus-marshal-basic.c:1428
_dbus_pack_uint32
void _dbus_pack_uint32(dbus_uint32_t value, int byte_order, unsigned char *data)
Packs a 32 bit unsigned integer into a data pointer.
Definition dbus-marshal-basic.c:142
_dbus_marshal_set_uint32
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 ...
Definition dbus-marshal-basic.c:260
_dbus_unpack_uint32
dbus_uint32_t _dbus_unpack_uint32(int byte_order, const unsigned char *data)
Unpacks a 32 bit unsigned integer from a data pointer.
Definition dbus-marshal-basic.c:189
_dbus_marshal_write_basic
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.
Definition dbus-marshal-basic.c:817
_dbus_first_type_in_signature
int _dbus_first_type_in_signature(const DBusString *str, int pos)
Get the first type in the signature.
Definition dbus-marshal-basic.c:1484
_dbus_first_type_in_signature_c_str
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.
Definition dbus-marshal-basic.c:1499
_dbus_marshal_read_uint32
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.
Definition dbus-marshal-basic.c:476
_dbus_verbose_bytes
void _dbus_verbose_bytes(const unsigned char *data, int len, int offset)
If in verbose mode, print a block of binary data.
Definition dbus-marshal-basic.c:1351
_dbus_marshal_set_basic
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.
Definition dbus-marshal-basic.c:377
_dbus_marshal_skip_array
void _dbus_marshal_skip_array(const DBusString *str, int element_type, int byte_order, int *pos)
Skips an array, returning the next position.
Definition dbus-marshal-basic.c:1205
_dbus_marshal_write_fixed_multi
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.
Definition dbus-marshal-basic.c:1059
_dbus_type_to_string
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
Definition dbus-marshal-basic.c:1290
_dbus_marshal_read_basic
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.
Definition dbus-marshal-basic.c:514
_dbus_swap_array
void _dbus_swap_array(unsigned char *data, int n_elements, int alignment)
Swaps the elements of an array to the opposite byte order.
Definition dbus-marshal-basic.c:927
_dbus_marshal_skip_basic
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.
Definition dbus-marshal-basic.c:1130
DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
Definition dbus-protocol.h:112
DBUS_MAXIMUM_SIGNATURE_LENGTH
#define DBUS_MAXIMUM_SIGNATURE_LENGTH
This one is 255 so it fits in a byte.
Definition dbus-protocol.h:183
DBUS_DICT_ENTRY_END_CHAR
#define DBUS_DICT_ENTRY_END_CHAR
Code marking the end of a dict entry type in a type signature.
Definition dbus-protocol.h:170
DBUS_TYPE_OBJECT_PATH
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
Definition dbus-protocol.h:108
DBUS_TYPE_BYTE
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition dbus-protocol.h:68
DBUS_TYPE_INT16
#define DBUS_TYPE_INT16
Type code marking a 16-bit signed integer.
Definition dbus-protocol.h:76
DBUS_TYPE_VARIANT
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
Definition dbus-protocol.h:126
DBUS_MAXIMUM_ARRAY_LENGTH
#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...
Definition dbus-protocol.h:205
DBUS_TYPE_INT32
#define DBUS_TYPE_INT32
Type code marking a 32-bit signed integer.
Definition dbus-protocol.h:84
DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
Definition dbus-protocol.h:116
DBUS_TYPE_BOOLEAN
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition dbus-protocol.h:72
DBUS_STRUCT_BEGIN_CHAR
#define DBUS_STRUCT_BEGIN_CHAR
Code marking the start of a struct type in a type signature.
Definition dbus-protocol.h:158
DBUS_TYPE_STRING
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
Definition dbus-protocol.h:104
DBUS_TYPE_ARRAY
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
Definition dbus-protocol.h:122
DBUS_TYPE_INVALID
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition dbus-protocol.h:62
DBUS_LITTLE_ENDIAN
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition dbus-protocol.h:55
DBUS_TYPE_INT64
#define DBUS_TYPE_INT64
Type code marking a 64-bit signed integer.
Definition dbus-protocol.h:92
DBUS_TYPE_DOUBLE
#define DBUS_TYPE_DOUBLE
Type code marking an 8-byte double in IEEE 754 format.
Definition dbus-protocol.h:100
DBUS_TYPE_UINT64
#define DBUS_TYPE_UINT64
Type code marking a 64-bit unsigned integer.
Definition dbus-protocol.h:96
DBUS_TYPE_DICT_ENTRY
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
Definition dbus-protocol.h:145
DBUS_DICT_ENTRY_BEGIN_CHAR
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
Definition dbus-protocol.h:166
DBUS_TYPE_UINT16
#define DBUS_TYPE_UINT16
Type code marking a 16-bit unsigned integer.
Definition dbus-protocol.h:80
DBUS_TYPE_STRUCT
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
Definition dbus-protocol.h:138
DBUS_STRUCT_END_CHAR
#define DBUS_STRUCT_END_CHAR
Code marking the end of a struct type in a type signature.
Definition dbus-protocol.h:162
DBUS_BIG_ENDIAN
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition dbus-protocol.h:56
DBUS_TYPE_UINT32
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition dbus-protocol.h:88
dbus_type_is_basic
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...
Definition dbus-signature.c:324
dbus_type_is_fixed
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.
Definition dbus-signature.c:355
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition dbus-string.c:847
_dbus_string_insert_8_aligned
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:1053
_dbus_string_equal_substring
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:2166
_dbus_string_insert_alignment
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:1081
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition dbus-string.c:182
_dbus_string_init_const
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition dbus-string.c:197
_dbus_string_copy
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:1345
_dbus_string_get_data_len
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:535
_dbus_string_init_const_len
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition dbus-string.c:217
_dbus_string_free
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:278
_dbus_string_delete
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:1255
_dbus_string_insert_byte
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:659
_dbus_string_insert_4_aligned
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:1029
_dbus_string_insert_2_aligned
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:1005
_dbus_string_copy_len
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:1437
_dbus_string_replace_len
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:1466
_DBUS_DOUBLES_BITWISE_EQUAL
#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:654
dbus_uint16_t
unsigned short dbus_uint16_t
A 16-bit unsigned integer on all platforms.
Definition dbus-arch-deps.h:48
DBUS_UINT64_CONSTANT
#define DBUS_UINT64_CONSTANT(val)
Declare a 64-bit unsigned integer constant.
Definition dbus-arch-deps.h:42
dbus_int64_t
_DBUS_GNUC_EXTENSION typedef long dbus_int64_t
A 64-bit signed integer.
Definition dbus-arch-deps.h:37
dbus_uint32_t
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
Definition dbus-arch-deps.h:45
dbus_int32_t
int dbus_int32_t
A 32-bit signed integer on all platforms.
Definition dbus-arch-deps.h:44
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
DBUS_INT64_MODIFIER
#define DBUS_INT64_MODIFIER
A string literal for a length modifier that is appropriate to print the dbus_int64_t and dbus_uint64_...
Definition dbus-arch-deps.h:39
dbus_uint64_t
_DBUS_GNUC_EXTENSION typedef unsigned long dbus_uint64_t
A 64-bit unsigned integer.
Definition dbus-arch-deps.h:38
DBUS_INT64_CONSTANT
#define DBUS_INT64_CONSTANT(val)
Declare a 64-bit signed integer constant.
Definition dbus-arch-deps.h:41
dbus_int16_t
short dbus_int16_t
A 16-bit signed integer on all platforms.
Definition dbus-arch-deps.h:47
DBus8ByteStruct
An 8-byte struct you could use to access int64 without having int64 support.
Definition dbus-types.h:145
DBusString
Definition dbus-string.h:47
DBusBasicValue
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition dbus-types.h:161