summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2005-01-03 07:15:38 +0000
committerHavoc Pennington <hp@redhat.com>2005-01-03 07:15:38 +0000
commitc7e05f9ca4ff7ab0c8499b2059004dd38d2c8784 (patch)
tree999cb96a520bf5ceb5fea2ffbd1b924e316e562f
parentec8e14cfd591aa020b199161bacb01d90c6fa158 (diff)
finish off my TODO list for stuff needed to port dbus-message.c. Next
step is to do so.
-rw-r--r--dbus/dbus-marshal-basic.c308
-rw-r--r--dbus/dbus-marshal-basic.h13
-rw-r--r--dbus/dbus-marshal-recursive.c340
-rw-r--r--dbus/dbus-marshal-recursive.h17
4 files changed, 486 insertions, 192 deletions
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index 17e2964d..11ebfaf1 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -553,6 +553,57 @@ _dbus_marshal_read_basic (const DBusString *str,
*new_pos = pos;
}
+/**
+ * Reads an array of fixed-length basic values. Does not work for
+ * arrays of string or container types.
+ *
+ * This function returns the array 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
+ *
+ * @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 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,
+ int pos,
+ int element_type,
+ void *value,
+ int *n_elements,
+ int byte_order,
+ int *new_pos)
+{
+ dbus_uint32_t 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);
+
+ alignment = _dbus_type_get_alignment (element_type);
+
+ pos = _DBUS_ALIGN_VALUE (pos, 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;
+}
+
static dbus_bool_t
marshal_4_octets (DBusString *str,
int insert_at,
@@ -663,7 +714,7 @@ marshal_len_followed_by_bytes (int marshal_as,
str, pos))
goto oom;
-#if 1
+#if 0
/* too expensive */
_dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
str, pos));
@@ -779,82 +830,83 @@ static dbus_bool_t
marshal_1_octets_array (DBusString *str,
int insert_at,
const unsigned char *value,
- int len,
+ int n_elements,
int byte_order,
int *pos_after)
{
return marshal_len_followed_by_bytes (MARSHAL_AS_BYTE_ARRAY,
- str, insert_at, value, len,
+ str, insert_at, value, n_elements,
byte_order, pos_after);
}
-static dbus_bool_t
-marshal_4_octets_array (DBusString *str,
- int insert_at,
- const dbus_uint32_t *value,
- int len,
- int byte_order)
+static void
+swap_array (DBusString *str,
+ int array_start,
+ int n_elements,
+ int byte_order,
+ int alignment)
{
- int old_string_len;
- int array_start;
-
- _dbus_assert_not_reached ("FIXME insert_at");
-
- old_string_len = _dbus_string_get_length (str);
-
- if (!marshal_4_octets (str, insert_at, len*4, byte_order, NULL))
- goto error;
-
- array_start = _dbus_string_get_length (str);
-
- if (!_dbus_string_append_len (str, (const unsigned char*) value,
- len * 4))
- goto error;
+ _dbus_assert (_DBUS_ALIGN_VALUE (array_start, alignment) == (unsigned) array_start);
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
{
- const unsigned char *d;
- const unsigned char *end;
+ unsigned char *d;
+ unsigned char *end;
- d = _dbus_string_get_data (str) + array_start;
- end = d + len * 4;
- while (d != end)
+ /* we use const_data and cast it off so DBusString can be a const string
+ * for the unit tests. don't ask.
+ */
+ d = (unsigned char*) _dbus_string_get_const_data (str) + array_start;
+ end = d + n_elements * alignment;
+
+ if (alignment == 8)
{
- *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
- d += 4;
+ while (d != end)
+ {
+#ifdef DBUS_HAVE_INT64
+ *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
+#else
+ swap_8_bytes ((DBusBasicValue*) d);
+#endif
+ d += 8;
+ }
}
- }
-
- return TRUE;
-
- error:
- /* Restore previous length */
- _dbus_string_set_length (str, old_string_len);
+ else
+ {
+ _dbus_assert (alignment == 4);
- return FALSE;
+ while (d != end)
+ {
+ *((dbus_uint32_t*)d) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)d));
+ d += 4;
+ }
+ }
+ }
}
static dbus_bool_t
-marshal_8_octets_array (DBusString *str,
- int insert_at,
- const DBusBasicValue *value,
- int len,
- int byte_order)
+marshal_fixed_array (DBusString *str,
+ int insert_at,
+ const DBusBasicValue *value,
+ int n_elements,
+ int byte_order,
+ int alignment,
+ int *pos_after)
{
int old_string_len;
int array_start;
-
- _dbus_assert_not_reached ("FIXME insert_at");
+ DBusString t;
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, len*8, byte_order, NULL))
+ if (!marshal_4_octets (str, insert_at, n_elements * alignment,
+ byte_order, &array_start))
goto error;
- array_start = _dbus_string_get_length (str);
+ _dbus_verbose ("marshaled len %d at %d array start %d\n", n_elements * alignment, insert_at, array_start);
/* Note that we do alignment padding unconditionally
* even if the array is empty; this means that
@@ -862,62 +914,57 @@ marshal_8_octets_array (DBusString *str,
* in the array.
*/
- if (!_dbus_string_align_length (str, 8))
+ if (!_dbus_string_insert_alignment (str, &array_start, alignment))
goto error;
- if (!_dbus_string_append_len (str, (const unsigned char*) value,
- len * 8))
- goto error;
+ _dbus_string_init_const_len (&t,
+ (const unsigned char*) value,
+ n_elements * alignment);
- if (byte_order != DBUS_COMPILER_BYTE_ORDER)
- {
- const unsigned char *d;
- const unsigned char *end;
+ if (!_dbus_string_copy (&t, 0,
+ str, array_start))
+ goto error;
- d = _dbus_string_get_data (str) + array_start;
- end = d + len * 8;
- while (d != end)
- {
-#ifdef DBUS_HAVE_INT64
- *((dbus_uint64_t*)d) = DBUS_UINT64_SWAP_LE_BE (*((dbus_uint64_t*)d));
-#else
- swap_8_bytes ((DBusBasicValue*) d);
-#endif
- d += 8;
- }
- }
+ swap_array (str, array_start, n_elements, byte_order, alignment);
return TRUE;
error:
- /* Restore previous length */
- _dbus_string_set_length (str, old_string_len);
+ _dbus_string_delete (str, insert_at,
+ _dbus_string_get_length (str) - old_string_len);
return FALSE;
}
/**
- * Marshals a basic type array
+ * 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.
+ *
+ * The value argument should be the adddress of an
+ * array, so e.g. "const dbus_uint32_t**"
*
* @param str string to marshal to
* @param insert_at where to insert the value
* @param element_type type of array elements
- * @param value pointer to value
- * @param len length of value data in elements
+ * @param value address of an array to marshal
+ * @param len 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_basic_array (DBusString *str,
+_dbus_marshal_write_fixed_array (DBusString *str,
int insert_at,
int element_type,
const void *value,
- int len,
+ int n_elements,
int byte_order,
int *pos_after)
{
- /* FIXME use the insert_at arg and fill in pos_after */
+ const void* vp = *(const DBusBasicValue**)value;
+
+ _dbus_assert (_dbus_type_is_fixed (element_type));
switch (element_type)
{
@@ -925,29 +972,20 @@ _dbus_marshal_write_basic_array (DBusString *str,
/* FIXME: we canonicalize to 0 or 1 for the single boolean case
* should we here too ? */
case DBUS_TYPE_BYTE:
- return marshal_1_octets_array (str, insert_at, value, len, byte_order, pos_after);
+ return marshal_1_octets_array (str, insert_at, vp, n_elements, byte_order, pos_after);
break;
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
- return marshal_4_octets_array (str, insert_at, value, len, byte_order);
+ return marshal_fixed_array (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_8_octets_array (str, insert_at, value, len, byte_order);
- break;
-
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- _dbus_assert_not_reached ("handle string arrays");
- break;
-
- case DBUS_TYPE_SIGNATURE:
- _dbus_assert_not_reached ("handle signature");
+ return marshal_fixed_array (str, insert_at, vp, n_elements, byte_order, 8, pos_after);
break;
default:
- _dbus_assert_not_reached ("non basic type in array");
+ _dbus_assert_not_reached ("non fixed type in array write");
break;
}
@@ -1173,10 +1211,10 @@ _dbus_type_is_basic (int typecode)
* first byte of the old and new value would be in the same location,
* so alignment padding is not a factor.
*
- * @returns #TRUE if the type can occupy different lengths
+ * @returns #FALSE if the type can occupy different lengths
*/
dbus_bool_t
-_dbus_type_length_varies (int typecode)
+_dbus_type_is_fixed (int typecode)
{
switch (typecode)
{
@@ -1187,9 +1225,9 @@ _dbus_type_length_varies (int typecode)
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
case DBUS_TYPE_DOUBLE:
- return FALSE;
- default:
return TRUE;
+ default:
+ return FALSE;
}
}
@@ -1257,6 +1295,16 @@ _dbus_verbose_bytes (const unsigned char *data,
if (i > 7 &&
_DBUS_ALIGN_ADDRESS (&data[i], 8) == &data[i])
{
+#ifdef DBUS_HAVE_INT64
+ /* I think I probably mean "GNU libc printf" and not "GNUC"
+ * but we'll wait until someone complains. If you hit this,
+ * just turn off verbose mode as a workaround.
+ */
+#if __GNUC__
+ _dbus_verbose (" u64: 0x%llx",
+ *(dbus_uint64_t*)&data[i-8]);
+#endif
+#endif
_dbus_verbose (" dbl: %g",
*(double*)&data[i-8]);
}
@@ -1312,6 +1360,17 @@ _dbus_verbose_bytes_of_string (const DBusString *str,
#include "dbus-test.h"
#include <stdio.h>
+static void
+swap_test_array (void *array,
+ int len_bytes,
+ int byte_order,
+ int alignment)
+{
+ DBusString t;
+ _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; \
@@ -1324,7 +1383,7 @@ _dbus_verbose_bytes_of_string (const DBusString *str,
#define DEMARSHAL_BASIC(typename, byte_order) \
do { \
_dbus_marshal_read_basic (&str, pos, DBUS_TYPE_##typename, &v_##typename, \
- byte_order, &pos); \
+ byte_order, &pos); \
} while (0)
#define DEMARSHAL_BASIC_AND_CHECK(typename, byte_order, literal) \
@@ -1359,19 +1418,61 @@ _dbus_verbose_bytes_of_string (const DBusString *str,
} \
} while (0)
+#define MARSHAL_FIXED_ARRAY(typename, byte_order, literal) \
+ do { \
+ v_ARRAY_##typename = literal; \
+ if (!_dbus_marshal_write_fixed_array (&str, pos, DBUS_TYPE_##typename, \
+ &v_ARRAY_##typename, _DBUS_N_ELEMENTS(literal), \
+ byte_order, NULL)) \
+ _dbus_assert_not_reached ("no memory"); \
+ } while (0)
+
+#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])); \
+ } 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 ((char*)literal, sizeof (literal), 0); \
+ _dbus_verbose ("READ DATA\n"); \
+ _dbus_verbose_bytes ((char*)v_ARRAY_##typename, sizeof (literal), 0); \
+ _dbus_assert_not_reached ("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 (void)
{
DBusString str;
int pos, dump_pos;
-#if 0
- dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
+ int n_elements;
+ dbus_int32_t array4[3] = { 123, 456, 789 };
#ifdef DBUS_HAVE_INT64
- dbus_int64_t array3[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
+ dbus_int64_t array8[3] = { DBUS_INT64_CONSTANT (0x123ffffffff),
DBUS_INT64_CONSTANT (0x456ffffffff),
- DBUS_INT64_CONSTANT (0x789ffffffff) }, *array4;
-#endif
+ DBUS_INT64_CONSTANT (0x789ffffffff) };
+ dbus_int64_t *v_ARRAY_INT64;
#endif
+ dbus_int32_t *v_ARRAY_INT32;
+ double *v_ARRAY_DOUBLE;
DBusString t;
double v_DOUBLE;
double t_DOUBLE;
@@ -1448,6 +1549,15 @@ _dbus_marshal_test (void)
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_BIG_ENDIAN, "a(ii)");
MARSHAL_TEST_STRCMP (SIGNATURE, DBUS_LITTLE_ENDIAN, "a(ii)");
+ /* Arrays */
+ MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_BIG_ENDIAN, array4);
+ MARSHAL_TEST_FIXED_ARRAY (INT32, DBUS_LITTLE_ENDIAN, array4);
+
+#ifdef DBUS_HAVE_INT64
+ MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_BIG_ENDIAN, array8);
+ MARSHAL_TEST_FIXED_ARRAY (INT64, DBUS_LITTLE_ENDIAN, array8);
+#endif
+
#if 0
/*
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 529ada5d..bf75cbef 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -275,11 +275,11 @@ dbus_bool_t _dbus_marshal_write_basic (DBusString *str,
const void *value,
int byte_order,
int *pos_after);
-dbus_bool_t _dbus_marshal_write_basic_array (DBusString *str,
+dbus_bool_t _dbus_marshal_write_fixed_array (DBusString *str,
int insert_at,
int element_type,
const void *value,
- int len,
+ int n_elements,
int byte_order,
int *pos_after);
void _dbus_marshal_read_basic (const DBusString *str,
@@ -288,6 +288,13 @@ void _dbus_marshal_read_basic (const DBusString *str,
void *value,
int byte_order,
int *new_pos);
+void _dbus_marshal_read_fixed_array (const DBusString *str,
+ int pos,
+ int element_type,
+ void *value,
+ int *n_elements,
+ int byte_order,
+ int *new_pos);
void _dbus_marshal_skip_basic (const DBusString *str,
int type,
int byte_order,
@@ -308,7 +315,7 @@ dbus_bool_t _dbus_type_is_valid (int typecode);
int _dbus_type_get_alignment (int typecode);
dbus_bool_t _dbus_type_is_basic (int typecode);
dbus_bool_t _dbus_type_is_container (int typecode);
-dbus_bool_t _dbus_type_length_varies (int typecode);
+dbus_bool_t _dbus_type_is_fixed (int typecode);
diff --git a/dbus/dbus-marshal-recursive.c b/dbus/dbus-marshal-recursive.c
index 58cab0c2..a3ef0217 100644
--- a/dbus/dbus-marshal-recursive.c
+++ b/dbus/dbus-marshal-recursive.c
@@ -764,14 +764,60 @@ _dbus_type_reader_read_basic (const DBusTypeReader *reader,
#endif
}
-dbus_bool_t
-_dbus_type_reader_read_array_of_basic (const DBusTypeReader *reader,
- int type,
- void **array,
- int *array_len)
+/**
+ * Reads an array of fixed-length basic values. Does not work for
+ * arrays of string or container types.
+ *
+ * This function returns the array 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.
+ *
+ * @param reader the reader to read from
+ * @param value place to return the array
+ * @param n_elements place to return number of array elements
+ */
+void
+_dbus_type_reader_read_fixed_array (const DBusTypeReader *reader,
+ void *value,
+ int *n_elements)
{
+ int element_type;
+ int end_pos;
+ int remaining_len;
+ int alignment;
+
_dbus_assert (!reader->klass->types_only);
+ _dbus_assert (reader->klass == &array_reader_class);
+
+ element_type = first_type_in_signature (reader->type_str,
+ reader->type_pos);
+
+ _dbus_assert (element_type != DBUS_TYPE_INVALID); /* why we don't use get_current_type() */
+ _dbus_assert (_dbus_type_is_fixed (element_type));
+
+ alignment = _dbus_type_get_alignment (element_type);
+ end_pos = reader->u.array.start_pos + array_reader_get_array_len (reader);
+ remaining_len = end_pos - reader->value_pos;
+
+ if (remaining_len == 0)
+ *(const DBusBasicValue**) value = NULL;
+ else
+ *(const DBusBasicValue**) value =
+ (void*) _dbus_string_get_const_data_len (reader->value_str,
+ reader->value_pos,
+ remaining_len);
+
+ *n_elements = remaining_len / alignment;
+ _dbus_assert ((remaining_len % alignment) == 0);
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type reader %p read fixed array type_pos = %d value_pos = %d remaining sig '%s'\n",
+ reader, reader->type_pos, reader->value_pos,
+ _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+#endif
}
/**
@@ -925,7 +971,106 @@ _dbus_type_reader_get_signature (const DBusTypeReader *reader,
*len_p = find_len_of_complete_type (reader->type_str, reader->type_pos);
}
+typedef struct
+{
+ DBusString replacement;
+ int padding;
+} ReplacementBlock;
+
+static dbus_bool_t
+replacement_block_init (ReplacementBlock *block,
+ DBusTypeReader *reader)
+{
+ if (!_dbus_string_init (&block->replacement))
+ return FALSE;
+ /* ALIGN_OFFSET is the offset to add to get to an 8-boundary; so 8 -
+ * ALIGN_OFFSET is the padding to have the same align properties in
+ * our replacement string as we do at the position being replaced
+ */
+ block->padding = 8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8);
+ _dbus_assert (block->padding >= 0);
+
+ if (!_dbus_string_lengthen (&block->replacement, block->padding))
+ goto oom;
+
+ return TRUE;
+
+ oom:
+ _dbus_string_free (&block->replacement);
+ return FALSE;
+}
+
+static dbus_bool_t
+replacement_block_replace (ReplacementBlock *block,
+ DBusTypeReader *reader,
+ const DBusTypeReader *realign_root)
+{
+ DBusTypeWriter writer;
+ DBusTypeReader realign_reader;
+ DBusList *fixups;
+ int orig_len;
+
+ _dbus_assert (realign_root != NULL);
+
+ orig_len = _dbus_string_get_length (&block->replacement);
+
+ realign_reader = *realign_root;
+
+ _dbus_type_writer_init_values_only (&writer,
+ realign_reader.byte_order,
+ realign_reader.type_str,
+ realign_reader.type_pos,
+ &block->replacement,
+ _dbus_string_get_length (&block->replacement));
+
+ fixups = NULL;
+ if (!_dbus_type_writer_write_reader_partial (&writer,
+ &realign_reader,
+ reader,
+ block->padding,
+ _dbus_string_get_length (&block->replacement) - block->padding,
+ &fixups))
+ goto oom;
+
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose ("REPLACEMENT at padding %d len %d\n", padding,
+ _dbus_string_get_length (&block->replacement) - padding);
+ _dbus_verbose_bytes_of_string (&block->replacement, padding,
+ _dbus_string_get_length (&block->replacement) - padding);
+ _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d\n",
+ reader->value_pos, (int) (8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8)),
+ realign_reader.value_pos - reader->value_pos);
+ _dbus_verbose_bytes_of_string (reader->value_str,
+ reader->value_pos,
+ realign_reader.value_pos - reader->value_pos);
+#endif
+
+ /* Move the replacement into position
+ * (realign_reader should now be at the end of the block to be replaced)
+ */
+ if (!_dbus_string_replace_len (&block->replacement, block->padding,
+ _dbus_string_get_length (&block->replacement) - block->padding,
+ (DBusString*) reader->value_str,
+ reader->value_pos,
+ realign_reader.value_pos - reader->value_pos))
+ goto oom;
+
+ /* Process our fixups now that we can't have an OOM error */
+ apply_and_free_fixups (&fixups, reader);
+
+ return TRUE;
+
+ oom:
+ _dbus_string_set_length (&block->replacement, orig_len);
+ return FALSE;
+}
+
+static void
+replacement_block_free (ReplacementBlock *block)
+{
+ _dbus_string_free (&block->replacement);
+}
/* In the variable-length case, we have to fix alignment after we insert.
* The strategy is as follows:
@@ -957,92 +1102,37 @@ reader_set_basic_variable_length (DBusTypeReader *reader,
const DBusTypeReader *realign_root)
{
dbus_bool_t retval;
- DBusString replacement;
- int padding;
+ ReplacementBlock block;
DBusTypeWriter writer;
- DBusTypeReader realign_reader;
- DBusList *fixups;
_dbus_assert (realign_root != NULL);
retval = FALSE;
- if (!_dbus_string_init (&replacement))
+ if (!replacement_block_init (&block, reader))
return FALSE;
- /* ALIGN_OFFSET is the offset to add to get to an 8-boundary; so 8 -
- * ALIGN_OFFSET is the padding to have the same align properties in
- * our replacement string as we do at the position being replaced
- */
- padding = 8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8);
- _dbus_assert (padding >= 0);
-
- if (!_dbus_string_lengthen (&replacement, padding))
- goto out;
-
/* Write the new basic value */
_dbus_type_writer_init_values_only (&writer,
reader->byte_order,
reader->type_str,
reader->type_pos,
- &replacement,
- _dbus_string_get_length (&replacement));
+ &block.replacement,
+ _dbus_string_get_length (&block.replacement));
if (!_dbus_type_writer_write_basic (&writer, current_type, value))
goto out;
- /* Rewrite the values following the new basic value, which should
- * fix their alignment
- */
- realign_reader = *realign_root;
-
- _dbus_type_writer_init_values_only (&writer,
- realign_reader.byte_order,
- realign_reader.type_str,
- realign_reader.type_pos,
- &replacement,
- _dbus_string_get_length (&replacement));
-
- fixups = NULL;
- if (!_dbus_type_writer_write_reader_partial (&writer,
- &realign_reader,
- reader,
- padding,
- _dbus_string_get_length (&replacement) - padding,
- &fixups))
+ if (!replacement_block_replace (&block,
+ reader,
+ realign_root))
goto out;
-#if RECURSIVE_MARSHAL_TRACE
- _dbus_verbose ("REPLACEMENT at padding %d len %d\n", padding,
- _dbus_string_get_length (&replacement) - padding);
- _dbus_verbose_bytes_of_string (&replacement, padding,
- _dbus_string_get_length (&replacement) - padding);
- _dbus_verbose ("TO BE REPLACED at value_pos = %d (align pad %d) len %d\n",
- reader->value_pos, (int) (8 - _DBUS_ALIGN_OFFSET (reader->value_pos, 8)),
- realign_reader.value_pos - reader->value_pos);
- _dbus_verbose_bytes_of_string (reader->value_str,
- reader->value_pos,
- realign_reader.value_pos - reader->value_pos);
-#endif
-
- /* Move the replacement into position
- * (realign_reader should now be at the end of the block to be replaced)
- */
- if (!_dbus_string_replace_len (&replacement, padding,
- _dbus_string_get_length (&replacement) - padding,
- (DBusString*) reader->value_str,
- reader->value_pos,
- realign_reader.value_pos - reader->value_pos))
- goto out;
-
- /* Process our fixups now that we can't have an OOM error */
- apply_and_free_fixups (&fixups, reader);
-
retval = TRUE;
out:
- _dbus_string_free (&replacement);
+ replacement_block_free (&block);
return retval;
}
@@ -1060,10 +1150,10 @@ reader_set_basic_fixed_length (DBusTypeReader *reader,
}
/**
- * Sets a new value for the basic type pointed to by the reader,
- * leaving the reader valid to continue reading. Any other readers may
- * of course be invalidated if you set a variable-length type such as
- * a string.
+ * Sets a new value for the basic type value pointed to by the reader,
+ * leaving the reader valid to continue reading. Any other readers
+ * will be invalidated if you set a variable-length type such as a
+ * string.
*
* The provided realign_root is the reader to start from when
* realigning the data that follows the newly-set value. The reader
@@ -1084,6 +1174,10 @@ reader_set_basic_fixed_length (DBusTypeReader *reader,
* DBusTypeMark. But since DBusMessage is effectively that object for
* D-BUS it doesn't seem worth creating some random object.)
*
+ * @todo optimize this by only rewriting until the old and new values
+ * are at the same alignment. Frequently this should result in only
+ * replacing the value that's immediately at hand.
+ *
* @param reader reader indicating where to set a new value
* @param value address of the value to set
* @param realign_root realign from here
@@ -1096,6 +1190,8 @@ _dbus_type_reader_set_basic (DBusTypeReader *reader,
{
int current_type;
+ _dbus_assert (!reader->klass->types_only);
+
current_type = _dbus_type_reader_get_current_type (reader);
#if RECURSIVE_MARSHAL_TRACE
@@ -1109,20 +1205,64 @@ _dbus_type_reader_set_basic (DBusTypeReader *reader,
_dbus_assert (_dbus_type_is_basic (current_type));
- if (_dbus_type_length_varies (current_type))
+ if (_dbus_type_is_fixed (current_type))
{
- _dbus_assert (realign_root != NULL);
- return reader_set_basic_variable_length (reader, current_type,
- value, realign_root);
+ reader_set_basic_fixed_length (reader, current_type, value);
+ return TRUE;
}
else
{
- reader_set_basic_fixed_length (reader, current_type, value);
- return TRUE;
+ _dbus_assert (realign_root != NULL);
+ return reader_set_basic_variable_length (reader, current_type,
+ value, realign_root);
}
}
/**
+ * Recursively deletes any value pointed to by the reader, leaving the
+ * reader valid to continue reading. Any other readers will be
+ * invalidated.
+ *
+ * The provided realign_root is the reader to start from when
+ * realigning the data that follows the newly-set value.
+ * See _dbus_type_reader_set_basic() for more details on the
+ * realign_root paramter.
+ *
+ * @todo for now this does not delete the typecodes associated with
+ * the value, so this function should only be used for array elements.
+ *
+ * @param reader reader indicating where to delete a value
+ * @param realign_root realign from here
+ * @returns #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_type_reader_delete (DBusTypeReader *reader,
+ const DBusTypeReader *realign_root)
+{
+ dbus_bool_t retval;
+ ReplacementBlock block;
+
+ _dbus_assert (realign_root != NULL);
+ _dbus_assert (reader->klass == &array_reader_class);
+
+ retval = FALSE;
+
+ if (!replacement_block_init (&block, reader))
+ return FALSE;
+
+ if (!replacement_block_replace (&block,
+ reader,
+ realign_root))
+ goto out;
+
+ retval = TRUE;
+
+ out:
+ replacement_block_free (&block);
+ return retval;
+}
+
+/**
* Compares two readers, which must be iterating over the same value data.
* Returns #TRUE if the first parameter is further along than the second parameter.
*
@@ -1844,14 +1984,50 @@ _dbus_type_writer_write_basic (DBusTypeWriter *writer,
return retval;
}
+/**
+ * Writes an array of fixed-length basic values, i.e. those that
+ * are both _dbus_type_is_fixed() and _dbus_type_is_basic().
+ *
+ * The value parameter should be the address of said array of values,
+ * so e.g. if it's an array of double, pass in "const double**"
+ *
+ * @param writer the writer
+ * @param element_type type of stuff in the array
+ * @param value address of the array
+ * @param n_elements number of elements in the array
+ * @returns #FALSE if no memory
+ */
dbus_bool_t
-_dbus_type_writer_write_array (DBusTypeWriter *writer,
- int type,
- const void *array,
- int array_len)
+_dbus_type_writer_write_fixed_array (DBusTypeWriter *writer,
+ int element_type,
+ const void *value,
+ int n_elements)
{
+ _dbus_assert (writer->container_type == DBUS_TYPE_ARRAY);
+ _dbus_assert (_dbus_type_is_fixed (element_type));
+ _dbus_assert (writer->type_pos_is_expectation);
+
+ if (!write_or_verify_typecode (writer, element_type))
+ _dbus_assert_not_reached ("OOM should not happen if only verifying typecode");
+
+ if (writer->enabled)
+ {
+ if (!_dbus_marshal_write_fixed_array (writer->value_str,
+ writer->value_pos,
+ element_type,
+ value,
+ n_elements,
+ writer->byte_order,
+ &writer->value_pos))
+ return FALSE;
+ }
+#if RECURSIVE_MARSHAL_TRACE
+ _dbus_verbose (" type writer %p fixed array type_pos = %d value_pos = %d\n",
+ writer, writer->type_pos, writer->value_pos);
+#endif
+ return TRUE;
}
static void
diff --git a/dbus/dbus-marshal-recursive.h b/dbus/dbus-marshal-recursive.h
index 025c3e04..765ee56b 100644
--- a/dbus/dbus-marshal-recursive.h
+++ b/dbus/dbus-marshal-recursive.h
@@ -151,10 +151,9 @@ int _dbus_type_reader_get_current_type (const DBusTypeReader *
dbus_bool_t _dbus_type_reader_array_is_empty (const DBusTypeReader *reader);
void _dbus_type_reader_read_basic (const DBusTypeReader *reader,
void *value);
-dbus_bool_t _dbus_type_reader_read_array_of_basic (const DBusTypeReader *reader,
- int type,
- void **array,
- int *array_len);
+void _dbus_type_reader_read_fixed_array (const DBusTypeReader *reader,
+ void *value,
+ int *n_elements);
void _dbus_type_reader_recurse (DBusTypeReader *reader,
DBusTypeReader *subreader);
dbus_bool_t _dbus_type_reader_next (DBusTypeReader *reader);
@@ -166,6 +165,8 @@ void _dbus_type_reader_get_signature (const DBusTypeReader *
dbus_bool_t _dbus_type_reader_set_basic (DBusTypeReader *reader,
const void *value,
const DBusTypeReader *realign_root);
+dbus_bool_t _dbus_type_reader_delete (DBusTypeReader *reader,
+ const DBusTypeReader *realign_root);
dbus_bool_t _dbus_type_reader_greater_than (const DBusTypeReader *lhs,
const DBusTypeReader *rhs);
@@ -184,10 +185,10 @@ void _dbus_type_writer_init_values_only (DBusTypeWriter *write
dbus_bool_t _dbus_type_writer_write_basic (DBusTypeWriter *writer,
int type,
const void *value);
-dbus_bool_t _dbus_type_writer_write_array (DBusTypeWriter *writer,
- int type,
- const void *array,
- int array_len);
+dbus_bool_t _dbus_type_writer_write_fixed_array (DBusTypeWriter *writer,
+ int element_type,
+ const void *value,
+ int n_elements);
dbus_bool_t _dbus_type_writer_recurse (DBusTypeWriter *writer,
int container_type,
const DBusString *contained_type,