summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-marshal-basic.c
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2005-01-15 07:15:38 +0000
committerHavoc Pennington <hp@redhat.com>2005-01-15 07:15:38 +0000
commit9c3d566e95c9080f6040c64531b0ccae22bd5d74 (patch)
treed21a18baa5a5ee9855c8a00eb2c1985bc23ca65f /dbus/dbus-marshal-basic.c
parent6ec04e917c8b4d477e818aa65ebb5e1fd50e4395 (diff)
2005-01-15 Havoc Pennington <hp@redhat.com>
* Land the new message args API and type system. This patch is huge, but the public API change is not really large. The set of D-BUS types has changed somewhat, and the arg "getters" are more geared toward language bindings; they don't make a copy, etc. There are also some known issues. See these emails for details on this huge patch: http://lists.freedesktop.org/archives/dbus/2004-December/001836.html http://lists.freedesktop.org/archives/dbus/2005-January/001922.html * dbus/dbus-marshal-*: all the new stuff * dbus/dbus-message.c: basically rewritten * dbus/dbus-memory.c (check_guards): with "guards" enabled, init freed blocks to be all non-nul bytes so using freed memory is less likely to work right * dbus/dbus-internals.c (_dbus_test_oom_handling): add DBUS_FAIL_MALLOC=N environment variable, so you can do DBUS_FAIL_MALLOC=0 to skip the out-of-memory checking, or DBUS_FAIL_MALLOC=10 to make it really, really, really slow and thorough. * qt/message.cpp: port to the new message args API (operator<<): use str.utf8() rather than str.unicode() (pretty sure this is right from the Qt docs?) * glib/dbus-gvalue.c: port to the new message args API * bus/dispatch.c, bus/driver.c: port to the new message args API * dbus/dbus-string.c (_dbus_string_init_const_len): initialize the "locked" flag to TRUE and align_offset to 0; I guess we never looked at these anyhow, but seems cleaner. * dbus/dbus-string.h (_DBUS_STRING_ALLOCATION_PADDING): move allocation padding macro to this header; use it to implement (_DBUS_STRING_STATIC): ability to declare a static string. * dbus/dbus-message.c (_dbus_message_has_type_interface_member): change to return TRUE if the interface is not set. * dbus/dbus-string.[hc]: move the D-BUS specific validation stuff to dbus-marshal-validate.[hc] * dbus/dbus-marshal-basic.c (_dbus_type_to_string): move here from dbus-internals.c * dbus/Makefile.am: cut over from dbus-marshal.[hc] to dbus-marshal-*.[hc] * dbus/dbus-object-tree.c (_dbus_decompose_path): move this function here from dbus-marshal.c
Diffstat (limited to 'dbus/dbus-marshal-basic.c')
-rw-r--r--dbus/dbus-marshal-basic.c199
1 files changed, 145 insertions, 54 deletions
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index 11ebfaf1..7504019b 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -150,6 +150,7 @@ swap_8_octets (DBusBasicValue *value,
}
}
+#if 0
static DBusBasicValue
unpack_8_octets (int byte_order,
const unsigned char *data)
@@ -171,6 +172,7 @@ unpack_8_octets (int byte_order,
return r;
}
+#endif
/**
* Unpacks a 32 bit unsigned integer from a data pointer
@@ -404,10 +406,12 @@ _dbus_marshal_set_basic (DBusString *str,
break;
case DBUS_TYPE_STRING:
case DBUS_TYPE_OBJECT_PATH:
+ _dbus_assert (vp->str != NULL);
return set_string (str, pos, vp->str, 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,
old_end_pos, new_end_pos);
break;
@@ -429,6 +433,8 @@ read_4_octets (const DBusString *str,
if (new_pos)
*new_pos = pos + 4;
+ _dbus_assert (pos + 4 <= _dbus_string_get_length (str));
+
return unpack_4_octets (byte_order,
_dbus_string_get_const_data (str) + pos);
}
@@ -554,52 +560,52 @@ _dbus_marshal_read_basic (const DBusString *str,
}
/**
- * Reads an array of fixed-length basic values. Does not work for
- * arrays of string or container types.
+ * Reads a block of fixed-length basic values, as an optimization
+ * vs. reading each one individually into a new buffer.
*
- * This function returns the array in-place; it does not make a copy,
+ * This function returns the data in-place; it does not make a copy,
* and it does not swap the bytes.
*
* If you ask for #DBUS_TYPE_DOUBLE you will get a "const double*" back
* and the "value" argument should be a "const double**" and so on.
*
- * @todo last I checked only the test suite uses this function
- *
+ * @todo we aren't using this function (except in the test suite)
+ *
* @param str the string to read from
* @param pos position to read from
* @param element_type type of array elements
* @param value place to return the array
- * @param n_elements place to return number of array elements
+ * @param n_elements number of array elements to read
* @param byte_order the byte order, used to read the array length
* @param new_pos #NULL or location to store a position after the elements
*/
void
-_dbus_marshal_read_fixed_array (const DBusString *str,
+_dbus_marshal_read_fixed_multi (const DBusString *str,
int pos,
int element_type,
void *value,
- int *n_elements,
+ int n_elements,
int byte_order,
int *new_pos)
{
- dbus_uint32_t array_len;
+ int array_len;
int alignment;
_dbus_assert (_dbus_type_is_fixed (element_type));
_dbus_assert (_dbus_type_is_basic (element_type));
- pos = _DBUS_ALIGN_VALUE (pos, 4);
-
- array_len = _dbus_marshal_read_uint32 (str, pos, byte_order, &pos);
-
+#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;
*(const DBusBasicValue**) value = (void*) _dbus_string_get_const_data_len (str, pos, array_len);
-
- *n_elements = array_len / alignment;
-
if (new_pos)
*new_pos = pos + array_len;
}
@@ -682,16 +688,12 @@ marshal_len_followed_by_bytes (int marshal_as,
if (insert_at > _dbus_string_get_length (str))
_dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
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 */
- /* FIXME this is probably broken for byte arrays because
- * DBusString wants strings to be nul-terminated?
- * Maybe I planned on this when writing init_const_len though
- */
_dbus_string_init_const_len (&value_str, value, value_len);
pos = insert_at;
@@ -814,9 +816,11 @@ _dbus_marshal_write_basic (DBusString *str,
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);
break;
case DBUS_TYPE_SIGNATURE:
+ _dbus_assert (vp->str != NULL);
return marshal_signature (str, insert_at, vp->str, pos_after);
break;
default:
@@ -834,9 +838,23 @@ marshal_1_octets_array (DBusString *str,
int byte_order,
int *pos_after)
{
- return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
- str, insert_at, value, n_elements,
- byte_order, pos_after);
+ int pos;
+ DBusString value_str;
+
+ _dbus_string_init_const_len (&value_str, 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;
}
static void
@@ -885,7 +903,7 @@ swap_array (DBusString *str,
}
static dbus_bool_t
-marshal_fixed_array (DBusString *str,
+marshal_fixed_multi (DBusString *str,
int insert_at,
const DBusBasicValue *value,
int n_elements,
@@ -896,18 +914,15 @@ marshal_fixed_array (DBusString *str,
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);
- /* The array length is the length in bytes of the array,
- * *excluding* alignment padding.
- */
- if (!marshal_4_octets (str, insert_at, n_elements * alignment,
- byte_order, &array_start))
- goto error;
-
- _dbus_verbose ("marshaled len %d at %d array start %d\n", n_elements * alignment, insert_at, array_start);
-
+ 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
@@ -919,7 +934,7 @@ marshal_fixed_array (DBusString *str,
_dbus_string_init_const_len (&t,
(const unsigned char*) value,
- n_elements * alignment);
+ len_in_bytes);
if (!_dbus_string_copy (&t, 0,
str, array_start))
@@ -927,6 +942,9 @@ marshal_fixed_array (DBusString *str,
swap_array (str, array_start, n_elements, byte_order, alignment);
+ if (pos_after)
+ *pos_after = array_start + len_in_bytes;
+
return TRUE;
error:
@@ -937,9 +955,9 @@ marshal_fixed_array (DBusString *str,
}
/**
- * Marshals an array of values of fixed-length type.
- * _dbus_type_is_fixed() returns #TRUE for these types,
- * which are the basic types minus the string-like types.
+ * Marshals a block of values of fixed-length type all at once, as an
+ * optimization. _dbus_type_is_fixed() returns #TRUE for fixed-length
+ * types, which are the basic types minus the string-like types.
*
* The value argument should be the adddress of an
* array, so e.g. "const dbus_uint32_t**"
@@ -948,13 +966,13 @@ marshal_fixed_array (DBusString *str,
* @param insert_at where to insert the value
* @param element_type type of array elements
* @param value address of an array to marshal
- * @param len number of elements in the array
+ * @param n_elements number of elements in the array
* @param byte_order byte order
* @param pos_after #NULL or the position after the type
* @returns #TRUE on success
**/
dbus_bool_t
-_dbus_marshal_write_fixed_array (DBusString *str,
+_dbus_marshal_write_fixed_multi (DBusString *str,
int insert_at,
int element_type,
const void *value,
@@ -963,9 +981,15 @@ _dbus_marshal_write_fixed_array (DBusString *str,
int *pos_after)
{
const void* vp = *(const DBusBasicValue**)value;
-
+
_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_BOOLEAN:
@@ -976,12 +1000,12 @@ _dbus_marshal_write_fixed_array (DBusString *str,
break;
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
- return marshal_fixed_array (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
+ return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 4, pos_after);
break;
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
- return marshal_fixed_array (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
+ return marshal_fixed_multi (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
break;
default:
@@ -1008,6 +1032,9 @@ _dbus_marshal_skip_basic (const DBusString *str,
int byte_order,
int *pos)
{
+ _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+ byte_order == DBUS_BIG_ENDIAN);
+
switch (type)
{
case DBUS_TYPE_BYTE:
@@ -1031,7 +1058,7 @@ _dbus_marshal_skip_basic (const DBusString *str,
int len;
len = _dbus_marshal_read_uint32 (str, *pos, byte_order, pos);
-
+
*pos += len + 1; /* length plus nul */
}
break;
@@ -1232,6 +1259,50 @@ _dbus_type_is_fixed (int typecode)
}
/**
+ * Returns a string describing the given type.
+ *
+ * @param typecode the type to describe
+ * @returns a constant string describing the type
+ */
+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_INT32:
+ return "int32";
+ case DBUS_TYPE_UINT32:
+ return "uint32";
+ 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_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";
+ default:
+ return "unknown";
+ }
+}
+
+/**
* If in verbose mode, print a block of binary data.
*
* @todo right now it prints even if not in verbose mode
@@ -1367,6 +1438,10 @@ swap_test_array (void *array,
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);
}
@@ -1420,8 +1495,13 @@ swap_test_array (void *array,
#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_assert_not_reached ("no memory"); \
v_ARRAY_##typename = literal; \
- if (!_dbus_marshal_write_fixed_array (&str, pos, DBUS_TYPE_##typename, \
+ if (!_dbus_marshal_write_fixed_multi (&str, next, DBUS_TYPE_##typename, \
&v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal), \
byte_order, NULL)) \
_dbus_assert_not_reached ("no memory"); \
@@ -1429,10 +1509,14 @@ swap_test_array (void *array,
#define DEMARSHAL_FIXED_ARRAY(typename, byte_order) \
do { \
- _dbus_marshal_read_fixed_array (&str, pos, DBUS_TYPE_##typename, &v_ARRAY_##typename, \
- &n_elements, byte_order, &pos); \
- swap_test_array (v_ARRAY_##typename, n_elements * sizeof(v_ARRAY_##typename[0]), \
- byte_order, sizeof(v_ARRAY_##typename[0])); \
+ 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, \
+ 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) \
@@ -1461,9 +1545,10 @@ swap_test_array (void *array,
dbus_bool_t
_dbus_marshal_test (void)
{
+ int alignment;
DBusString str;
int pos, dump_pos;
- int n_elements;
+ unsigned char array1[5] = { 3, 4, 0, 1, 9 };
dbus_int32_t array4[3] = { 123, 456, 789 };
#ifdef DBUS_HAVE_INT64
dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
@@ -1471,6 +1556,7 @@ _dbus_marshal_test (void)
DBUS_INT64_CONSTANT (0x789ffffffff) };
dbus_int64_t *v_ARRAY_INT64;
#endif
+ unsigned char *v_ARRAY_BYTE;
dbus_int32_t *v_ARRAY_INT32;
double *v_ARRAY_DOUBLE;
DBusString t;
@@ -1553,6 +1639,9 @@ _dbus_marshal_test (void)
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
+ MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_BIG_ENDIAN, array1);
+ MARSHAL_TEST_FIXED_ARRAY (BYTE, DBUS_LITTLE_ENDIAN, array1);
+
#ifdef DBUS_HAVE_INT64
MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
@@ -1675,16 +1764,18 @@ _dbus_marshal_test (void)
_dbus_string_get_const_data (&str)));
/* unsigned little */
- _dbus_marshal_set_uint32 (&str, DBUS_LITTLE_ENDIAN,
- 0, 0x123456);
+ _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, DBUS_BIG_ENDIAN,
- 0, 0x123456);
+ _dbus_marshal_set_uint32 (&str,
+ 0, 0x123456,
+ DBUS_BIG_ENDIAN);
_dbus_assert (0x123456 ==
_dbus_unpack_uint32 (DBUS_BIG_ENDIAN,