summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog41
-rw-r--r--dbus/dbus-marshal.c588
-rw-r--r--dbus/dbus-marshal.h76
-rw-r--r--dbus/dbus-message-builder.c2
-rw-r--r--dbus/dbus-message.c122
-rw-r--r--dbus/dbus-message.h6
-rw-r--r--dbus/dbus-protocol.h1
-rw-r--r--dbus/dbus.h1
-rw-r--r--doc/dbus-specification.sgml7
-rw-r--r--test/data/invalid-messages/dict-with-nil-value.message12
-rw-r--r--test/data/invalid-messages/too-short-dict.message11
-rw-r--r--test/data/valid-messages/dict-simple.message11
-rw-r--r--test/data/valid-messages/dict.message29
13 files changed, 851 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 2020f1bf..36f27b9e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2003-03-10 Anders Carlsson <andersca@codefactory.se>
+
+ * dbus/dbus-marshal.c:
+ (_dbus_marshal_set_string):
+ Take a length argument so we can marshal the correct string
+ length.
+
+ (_dbus_marshal_dict), (_dbus_demarshal_dict),
+ (_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg),
+ (_dbus_marshal_test):
+ * dbus/dbus-marshal.h:
+ Add support for marshalling and demarshalling dicts.
+
+ * dbus/dbus-message-builder.c: (_dbus_message_data_load):
+ Add support for TYPE DICT.
+
+ * dbus/dbus-message.c: (set_string_field):
+ Adjust header padding.
+
+ (dbus_message_append_args_valist), (dbus_message_append_dict),
+ (dbus_message_get_args_valist), (dbus_message_iter_get_arg_type),
+ (dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer),
+ (check_message_handling), (check_have_valid_message):
+ * dbus/dbus-message.h:
+ Add functions for setting and getting dicts.
+
+ * dbus/dbus-protocol.h:
+ Add DBUS_TYPE_DICT.
+
+ * dbus/dbus.h:
+ Add dbus-dict.h
+
+ * doc/dbus-specification.sgml:
+ Add information about how dicts are marshalled.
+
+ * test/data/invalid-messages/dict-with-nil-value.message:
+ * test/data/invalid-messages/too-short-dict.message:
+ * test/data/valid-messages/dict-simple.message:
+ * test/data/valid-messages/dict.message:
+ Add sample messages containing dicts.
+
2003-03-08 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-dict.h: Add DBUS_END_DECLS.
diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c
index f78757fd..4c721f66 100644
--- a/dbus/dbus-marshal.c
+++ b/dbus/dbus-marshal.c
@@ -198,6 +198,7 @@ _dbus_marshal_set_uint32 (DBusString *str,
* @param offset the byte offset where string should be written
* @param byte_order the byte order to use
* @param value the value
+ * @param len the length to use
* @returns #TRUE on success
*
*/
@@ -205,10 +206,10 @@ dbus_bool_t
_dbus_marshal_set_string (DBusString *str,
int byte_order,
int offset,
- const DBusString *value)
+ const DBusString *value,
+ int len)
{
int old_len;
- int new_len;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
@@ -216,14 +217,12 @@ _dbus_marshal_set_string (DBusString *str,
old_len = _dbus_demarshal_uint32 (str, byte_order,
offset, NULL);
- new_len = _dbus_string_get_length (value);
-
- if (!_dbus_string_replace_len (value, 0, new_len,
+ if (!_dbus_string_replace_len (value, 0, len,
str, offset + 4, old_len))
return FALSE;
_dbus_marshal_set_uint32 (str, byte_order,
- offset, new_len);
+ offset, len);
return TRUE;
}
@@ -496,6 +495,193 @@ _dbus_marshal_string_array (DBusString *str,
return FALSE;
}
+
+/**
+ * Marshals a dict
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param dict the dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_dict (DBusString *str,
+ int byte_order,
+ DBusDict *dict)
+{
+ int old_string_len;
+ int i, len;
+ char **keys;
+
+ old_string_len = _dbus_string_get_length (str);
+
+ if (!dbus_dict_get_keys (dict, &keys, &len))
+ goto error;
+
+ if (len == 0)
+ return TRUE;
+
+ if (!_dbus_marshal_string_array (str, byte_order,
+ keys, len))
+ goto error;
+
+ for (i = 0; i < len; i++)
+ {
+ int value_type;
+
+ value_type = dbus_dict_get_value_type (dict, keys[i]);
+
+ if (!_dbus_string_append_byte (str, value_type))
+ goto error;
+
+ switch (dbus_dict_get_value_type (dict, keys[i]))
+ {
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t value;
+
+ if (!dbus_dict_get_boolean (dict, keys[i], &value))
+ goto error;
+
+ if (!_dbus_string_append_byte (str, (value != FALSE)))
+ goto error;
+
+ break;
+ }
+
+ case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t value;
+
+ if (!dbus_dict_get_int32 (dict, keys[i], &value))
+ goto error;
+
+ if (!_dbus_marshal_int32 (str, byte_order, value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ dbus_uint32_t value;
+
+ if (!dbus_dict_get_uint32 (dict, keys[i], &value))
+ goto error;
+
+ if (!_dbus_marshal_uint32 (str, byte_order, value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_DOUBLE:
+ {
+ double value;
+
+ if (!dbus_dict_get_double (dict, keys[i], &value))
+ goto error;
+
+ if (!_dbus_marshal_double (str, byte_order, value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_INT32_ARRAY:
+ {
+ const dbus_int32_t *value;
+ int len;
+
+ if (!dbus_dict_get_int32_array (dict, keys[i], &value, &len))
+ goto error;
+
+ if (!_dbus_marshal_int32_array (str, byte_order, value, len))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_STRING:
+ {
+ const char *value;
+
+ if (!dbus_dict_get_string (dict, keys[i], &value))
+ goto error;
+
+ if (!_dbus_marshal_string (str, byte_order, value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_BOOLEAN_ARRAY:
+ {
+ const unsigned char *value;
+ int len;
+
+ if (!dbus_dict_get_boolean_array (dict, keys[i], &value, &len))
+ goto error;
+
+ if (!_dbus_marshal_byte_array (str, byte_order, value, len))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_UINT32_ARRAY:
+ {
+ const dbus_uint32_t *value;
+ int len;
+
+ if (!dbus_dict_get_uint32_array (dict, keys[i], &value, &len))
+ goto error;
+
+ if (!_dbus_marshal_uint32_array (str, byte_order, value, len))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_DOUBLE_ARRAY:
+ {
+ const double *value;
+ int len;
+
+ if (!dbus_dict_get_double_array (dict, keys[i], &value, &len))
+ goto error;
+
+ if (!_dbus_marshal_double_array (str, byte_order, value, len))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_STRING_ARRAY:
+ {
+ const char **value;
+ int len;
+
+ if (!dbus_dict_get_string_array (dict, keys[i], &value, &len))
+ goto error;
+
+ if (!_dbus_marshal_string_array (str, byte_order, value, len))
+ goto error;
+
+ break;
+ }
+ default:
+ _dbus_warn ("unknwon value type %d\n", dbus_dict_get_value_type (dict, keys[i]));
+ _dbus_assert_not_reached ("unknown value type in dict");
+ }
+ }
+
+ dbus_free_string_array (keys);
+
+ return TRUE;
+
+ error:
+
+ dbus_free_string_array (keys);
+
+ /* Restore previous length */
+ _dbus_string_set_length (str, old_string_len);
+
+ return FALSE;
+}
+
+
/**
* Demarshals a double.
*
@@ -848,6 +1034,212 @@ _dbus_demarshal_string_array (const DBusString *str,
return NULL;
}
+/**
+ * Demarshals a dict
+ *
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position in the string
+ * @returns the demarshalled dict
+ */
+DBusDict *
+_dbus_demarshal_dict (const DBusString *str,
+ int byte_order,
+ int pos,
+ int *new_pos)
+{
+ char **keys;
+ int i, len;
+ DBusDict *dict;
+
+ dict = dbus_dict_new ();
+ if (!dict)
+ return NULL;
+
+ keys = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len);
+
+ if (!keys)
+ goto error;
+
+ for (i = 0; i < len; i++)
+ {
+ int value_type;
+
+ switch ((value_type = _dbus_string_get_byte (str, pos ++)))
+ {
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t value;
+
+ value = _dbus_string_get_byte (str, pos ++);
+
+ if (!dbus_dict_set_boolean (dict, keys[i], value))
+ goto error;
+ break;
+ }
+ case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t value;
+
+ value = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
+
+ if (!dbus_dict_set_int32 (dict, keys[i], value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ dbus_uint32_t value;
+
+ value = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+
+ if (!dbus_dict_set_uint32 (dict, keys[i], value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_DOUBLE:
+ {
+ double value;
+
+ value = _dbus_demarshal_double (str, byte_order, pos, &pos);
+
+ if (!dbus_dict_set_double (dict, keys[i], value))
+ goto error;
+
+ break;
+ }
+ case DBUS_TYPE_STRING:
+ {
+ char *value;
+
+ value = _dbus_demarshal_string (str, byte_order, pos, &pos);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_string (dict, keys[i], value))
+ {
+ dbus_free (value);
+ goto error;
+ }
+
+ dbus_free (value);
+
+ break;
+ }
+ case DBUS_TYPE_BOOLEAN_ARRAY:
+ {
+ unsigned char *value;
+ int len;
+
+ value = _dbus_demarshal_byte_array (str, byte_order, pos, &pos, &len);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_boolean_array (dict, keys[i], value, len))
+ {
+ dbus_free (value);
+ goto error;
+ }
+
+ dbus_free (value);
+ break;
+ }
+ case DBUS_TYPE_INT32_ARRAY:
+ {
+ dbus_int32_t *value;
+ int len;
+
+ value = _dbus_demarshal_int32_array (str, byte_order, pos, &pos, &len);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_int32_array (dict, keys[i], value, len))
+ {
+ dbus_free (value);
+ goto error;
+ }
+
+ dbus_free (value);
+ break;
+ }
+ case DBUS_TYPE_UINT32_ARRAY:
+ {
+ dbus_uint32_t *value;
+ int len;
+
+ value = _dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &len);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_uint32_array (dict, keys[i], value, len))
+ {
+ dbus_free (value);
+ goto error;
+ }
+
+ dbus_free (value);
+ break;
+ }
+ case DBUS_TYPE_DOUBLE_ARRAY:
+ {
+ double *value;
+ int len;
+
+ value = _dbus_demarshal_double_array (str, byte_order, pos, &pos, &len);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_double_array (dict, keys[i], value, len))
+ {
+ dbus_free (value);
+ goto error;
+ }
+
+ dbus_free (value);
+ break;
+ }
+ case DBUS_TYPE_STRING_ARRAY:
+ {
+ char **value;
+ int len;
+
+ value = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len);
+
+ if (!value)
+ goto error;
+
+ if (!dbus_dict_set_string_array (dict, keys[i], value, len))
+ {
+ dbus_free_string_array (value);
+ goto error;
+ }
+
+ dbus_free_string_array (value);
+ break;
+ }
+ default:
+ _dbus_warn ("unknown value type %d\n", value_type);
+ _dbus_assert_not_reached ("unknown value arg");
+ }
+ }
+
+ dbus_free_string_array (keys);
+ return dict;
+
+ error:
+ dbus_free_string_array (keys);
+ dbus_dict_unref (dict);
+ return NULL;
+}
+
/**
* Returns the position right after the end of an argument. PERFORMS
* NO VALIDATION WHATSOEVER. The message must have been previously
@@ -980,7 +1372,34 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
*end_pos = pos;
}
break;
-
+
+ case DBUS_TYPE_DICT:
+ {
+ int len, i;
+
+ /* Demarshal the length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+
+ for (i = 0; i < len; i++)
+ {
+ int str_len;
+
+ /* Demarshal string length */
+ str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ pos += str_len + 1;
+ }
+
+ /* Now check the values */
+ for (i = 0; i < len; i++)
+ {
+ if (!_dbus_marshal_get_arg_end_pos (str, byte_order, pos, &pos))
+ return FALSE;
+ }
+
+ *end_pos = pos;
+
+ break;
+ }
default:
_dbus_warn ("Unknown message arg type %d\n", *data);
_dbus_assert_not_reached ("Unknown message argument type\n");
@@ -1289,7 +1708,53 @@ _dbus_marshal_validate_arg (const DBusString *str,
*end_pos = pos;
}
break;
-
+
+ case DBUS_TYPE_DICT:
+ {
+ int len;
+ int i;
+
+ len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ if (len < 0)
+ return FALSE;
+
+ for (i = 0; i < len; i++)
+ {
+ int str_len;
+
+ str_len = demarshal_and_validate_len (str, byte_order,
+ pos, &pos);
+ if (str_len < 0)
+ return FALSE;
+
+ if (!validate_string (str, pos, str_len, &pos))
+ return FALSE;
+ }
+
+ /* Now validate each argument */
+ for (i = 0; i < len; i++)
+ {
+ if (pos >= _dbus_string_get_length (str))
+ {
+ _dbus_verbose ("not enough values in dict\n");
+ return FALSE;
+ }
+
+ if (_dbus_string_get_byte (str, pos) == DBUS_TYPE_NIL)
+ {
+ _dbus_verbose ("can't have NIL values in dicts\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_validate_arg (str, byte_order, pos, &pos))
+ return FALSE;
+ }
+
+ *end_pos = pos;
+
+ break;
+ }
+
default:
_dbus_verbose ("Unknown message arg type %d\n", *data);
return FALSE;
@@ -1426,7 +1891,23 @@ _dbus_marshal_test (void)
DBusString str;
char *tmp1, *tmp2;
dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
- int pos = 0, len;
+ int pos = 0, i, len;
+ dbus_bool_t our_bool;
+ dbus_int32_t our_int;
+ dbus_uint32_t our_uint;
+ double our_double;
+ const char *our_string;
+ const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE };
+ const unsigned char *our_boolean_array;
+ const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e };
+ const dbus_int32_t *our_int32_array;
+ const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff };
+ const dbus_uint32_t *our_uint32_array;
+ const double double_array[] = { 3.14159, 1.2345, 6.7890 };
+ const double *our_double_array;
+ const char *string_array[] = { "This", "Is", "A", "Test" };
+ const char **our_string_array;
+ DBusDict *dict;
if (!_dbus_string_init (&str, _DBUS_INT_MAX))
_dbus_assert_not_reached ("failed to init string");
@@ -1491,7 +1972,96 @@ _dbus_marshal_test (void)
dbus_free (array2);
+ /* Marshal dicts */
+ dict = dbus_dict_new ();
+ if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL)
+ _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry");
+
+ if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
+ _dbus_assert_not_reached ("could not add boolean value");
+
+ if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
+ _dbus_assert_not_reached ("could not add int32 value");
+
+ if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
+ _dbus_assert_not_reached ("could not add uint32 value");
+
+ if (!dbus_dict_set_double (dict, "double", 3.14159))
+ _dbus_assert_not_reached ("could not add double value");
+
+ if (!dbus_dict_set_string (dict, "string", "test string"))
+ _dbus_assert_not_reached ("could not add string value");
+
+ if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
+ _dbus_assert_not_reached ("could not add boolean array");
+
+ if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
+ _dbus_assert_not_reached ("could not add int32 array");
+
+ if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
+ _dbus_assert_not_reached ("could not add uint32 array");
+
+ if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
+ _dbus_assert_not_reached ("could not add double array");
+
+ if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
+ _dbus_assert_not_reached ("could not add string array");
+
+ if (!_dbus_marshal_dict (&str, DBUS_BIG_ENDIAN, dict))
+ _dbus_assert_not_reached ("could not marshal dict");
+
+ dbus_dict_unref (dict);
+
+ dict = _dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos);
+
+ if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
+ !our_bool)
+ _dbus_assert_not_reached ("could not get boolean value");
+
+ if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
+ _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
+
+ if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
+ _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
+
+ if (!dbus_dict_get_double (dict, "double", &our_double)
+ || our_double != 3.14159)
+ _dbus_assert_not_reached ("could not get double value or double values differ");
+
+ if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
+ _dbus_assert_not_reached ("could not get string value or string values differ");
+
+ if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
+ len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
+ _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
+
+ if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
+ len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
+ _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
+
+ if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
+ len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
+ _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
+
+ if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
+ len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
+ _dbus_assert_not_reached ("could not get double array value or double array values differ");
+
+ if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
+ _dbus_assert_not_reached ("could not get string array value");
+
+ if (len != 4)
+ _dbus_assert_not_reached ("string array lengths differ");
+
+ for (i = 0; i < len; i++)
+ {
+ if (strcmp (our_string_array[i], string_array[i]) != 0)
+ _dbus_assert_not_reached ("string array fields differ");
+ }
+
+ dbus_dict_unref (dict);
+
_dbus_string_free (&str);
diff --git a/dbus/dbus-marshal.h b/dbus/dbus-marshal.h
index cedca6b8..156ad09f 100644
--- a/dbus/dbus-marshal.h
+++ b/dbus/dbus-marshal.h
@@ -25,6 +25,7 @@
#define DBUS_MARSHAL_H
#include <config.h>
+#include <dbus/dbus-dict.h>
#include <dbus/dbus-protocol.h>
#include <dbus/dbus-types.h>
#include <dbus/dbus-string.h>
@@ -88,7 +89,8 @@ void _dbus_marshal_set_uint32 (DBusString *str,
dbus_bool_t _dbus_marshal_set_string (DBusString *str,
int byte_order,
int offset,
- const DBusString *value);
+ const DBusString *value,
+ int len);
dbus_bool_t _dbus_marshal_int32 (DBusString *str,
@@ -123,48 +125,56 @@ dbus_bool_t _dbus_marshal_string_array (DBusString *str,
int byte_order,
const char **value,
int len);
+dbus_bool_t _dbus_marshal_dict (DBusString *str,
+ int byte_order,
+ DBusDict *dict);
double _dbus_demarshal_double (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos);
+ int byte_order,
+ int pos,
+ int *new_pos);
dbus_int32_t _dbus_demarshal_int32 (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos);
+ int byte_order,
+ int pos,
+ int *new_pos);
dbus_uint32_t _dbus_demarshal_uint32 (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos);
+ int byte_order,
+ int pos,
+ int *new_pos);
char * _dbus_demarshal_string (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos);
+ int byte_order,
+ int pos,
+ int *new_pos);
unsigned char *_dbus_demarshal_byte_array (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- int *array_len);
+ int byte_order,
+ int pos,
+ int *new_pos,
+ int *array_len);
dbus_int32_t * _dbus_demarshal_int32_array (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- int *array_len);
+ int byte_order,
+ int pos,
+ int *new_pos,
+ int *array_len);
dbus_uint32_t *_dbus_demarshal_uint32_array (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- int *array_len);
+ int byte_order,
+ int pos,
+ int *new_pos,
+ int *array_len);
double * _dbus_demarshal_double_array (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- int *array_len);
+ int byte_order,
+ int pos,
+ int *new_pos,
+ int *array_len);
char ** _dbus_demarshal_string_array (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- int *array_len);
+ int byte_order,
+ int pos,
+ int *new_pos,
+ int *array_len);
+DBusDict * _dbus_demarshal_dict (const DBusString *str,
+ int byte_order,
+ int pos,
+ int *new_pos);
+
dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str,
diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c
index 3501da9a..54b5de70 100644
--- a/dbus/dbus-message-builder.c
+++ b/dbus/dbus-message-builder.c
@@ -648,6 +648,8 @@ _dbus_message_data_load (DBusString *dest,
code = DBUS_TYPE_DOUBLE;
else if (_dbus_string_starts_with_c_str (&line, "STRING"))
code = DBUS_TYPE_STRING;
+ else if (_dbus_string_starts_with_c_str (&line, "DICT"))
+ code = DBUS_TYPE_DICT;
else
{
const char *s;
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index db1b94bf..a25480cb 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -493,15 +493,21 @@ set_string_field (DBusMessage *message,
DBusString v;
int old_len;
int new_len;
+ int len;
+
+ clear_header_padding (message);
old_len = _dbus_string_get_length (&message->header);
+ len = strlen (value);
+
_dbus_string_init_const_len (&v, value,
- strlen (value) + 1); /* include nul */
+ len + 1); /* include nul */
if (!_dbus_marshal_set_string (&message->header,
message->byte_order,
- offset, &v))
- return FALSE;
+ offset, &v,
+ len))
+ goto failed;
new_len = _dbus_string_get_length (&message->header);
@@ -509,7 +515,19 @@ set_string_field (DBusMessage *message,
offset,
new_len - old_len);
+ if (!append_header_padding (message))
+ goto failed;
+
return TRUE;
+
+ failed:
+ /* this must succeed because it was allocated on function entry and
+ * DBusString doesn't ever realloc smaller
+ */
+ if (!append_header_padding (message))
+ _dbus_assert_not_reached ("failed to reappend header padding");
+
+ return FALSE;
}
}
@@ -1162,7 +1180,15 @@ dbus_message_append_args_valist (DBusMessage *message,
goto enomem;
}
break;
-
+ case DBUS_TYPE_DICT:
+ {
+ DBusDict *dict;
+
+ dict = va_arg (var_args, DBusDict *);
+
+ if (!dbus_message_append_dict (message, dict))
+ goto enomem;
+ }
default:
_dbus_warn ("Unknown field type %d\n", type);
}
@@ -1485,6 +1511,31 @@ dbus_message_append_string_array (DBusMessage *message,
}
/**
+ * Appends a dict to the message.
+ *
+ * @param message the message
+ * @param dict the dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_dict (DBusMessage *message,
+ DBusDict *dict)
+{
+ _dbus_assert (!message->locked);
+
+ if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT))
+ return FALSE;
+
+ if (!_dbus_marshal_dict (&message->body, message->byte_order, dict))
+ {
+ _dbus_string_shorten (&message->body, 1);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* Gets arguments from a message given a variable argument list.
* The variable argument list should contain the type of the
* argumen followed by a pointer to where the value should be
@@ -1696,6 +1747,16 @@ dbus_message_get_args_valist (DBusMessage *message,
return DBUS_RESULT_NO_MEMORY;
break;
}
+ case DBUS_TYPE_DICT:
+ {
+ DBusDict **dict;
+
+ dict = va_arg (var_args, DBusDict **);
+
+ if (!dbus_message_iter_get_dict (iter, dict))
+ return DBUS_RESULT_NO_MEMORY;
+ break;
+ }
default:
_dbus_warn ("Unknown field type %d\n", spec_type);
}
@@ -1850,7 +1911,7 @@ dbus_message_iter_get_arg_type (DBusMessageIter *iter)
_dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
- if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
return *data;
return DBUS_TYPE_INVALID;
@@ -2062,7 +2123,7 @@ dbus_message_iter_get_double_array (DBusMessageIter *iter,
* @param iter the iterator
* @param value return location for array values
* @param len return location for length of byte array
- * @returns the byte array
+ * @returns #TRUE on success
*/
dbus_bool_t
dbus_message_iter_get_byte_array (DBusMessageIter *iter,
@@ -2093,7 +2154,7 @@ dbus_message_iter_get_byte_array (DBusMessageIter *iter,
* @param iter the iterator
* @param value return location for string values
* @param len return location for length of byte array
- * @returns the byte array
+ * @returns #TRUE on success
*/
dbus_bool_t
dbus_message_iter_get_string_array (DBusMessageIter *iter,
@@ -2112,6 +2173,30 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter,
}
/**
+ * Returns the dict that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a dict prior to using this function.
+ *
+ * @param iter the iterator
+ * @param dict return location for dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_dict (DBusMessageIter *iter,
+ DBusDict **dict)
+{
+ _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT);
+
+ *dict = _dbus_demarshal_dict (&iter->message->body, iter->message->byte_order,
+ iter->pos + 1, NULL);
+
+ if (!*dict)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+/**
* Sets the message sender.
*
* @param message the message
@@ -2630,9 +2715,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
*/
header_len = header_len_unsigned;
body_len = body_len_unsigned;
-
+
if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
{
+
_dbus_verbose ("header length %d is not aligned to 8 bytes\n",
header_len);
loader->corrupted = TRUE;
@@ -2654,8 +2740,8 @@ _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
int next_arg;
#if 0
- _dbus_verbose_bytes_of_string (&loader->data, 0, header_len);
-#endif
+ _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
+#endif
if (!decode_header_data (&loader->data, header_len, byte_order,
fields, &header_padding))
{
@@ -2899,7 +2985,7 @@ check_message_handling (DBusMessage *message)
/* If we implement message_set_arg (message, n, value)
* then we would want to test it here
*/
-
+
iter = dbus_message_get_args_iter (message);
while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
{
@@ -2967,7 +3053,18 @@ check_message_handling (DBusMessage *message)
dbus_free_string_array (values);
}
break;
-
+
+ case DBUS_TYPE_DICT:
+ {
+ DBusDict *dict;
+
+ if (!dbus_message_iter_get_dict (iter, &dict))
+ return FALSE;
+
+ dbus_dict_unref (dict);
+ }
+ break;
+
default:
break;
}
@@ -3025,6 +3122,7 @@ check_have_valid_message (DBusMessageLoader *loader)
failed:
if (message)
dbus_message_unref (message);
+
return retval;
}
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index bb2b620e..4ea63060 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -28,6 +28,7 @@
#define DBUS_MESSAGE_H
#include <dbus/dbus-macros.h>
+#include <dbus/dbus-dict.h>
#include <dbus/dbus-types.h>
#include <stdarg.h>
@@ -94,7 +95,8 @@ dbus_bool_t dbus_message_append_byte_array (DBusMessage *message,
dbus_bool_t dbus_message_append_string_array (DBusMessage *message,
const char **value,
int len);
-
+dbus_bool_t dbus_message_append_dict (DBusMessage *message,
+ DBusDict *dict);
DBusMessageIter *dbus_message_get_args_iter (DBusMessage *message);
DBusResultCode dbus_message_get_args (DBusMessage *message,
@@ -134,6 +136,8 @@ dbus_bool_t dbus_message_iter_get_byte_array (DBusMessageIter *iter,
dbus_bool_t dbus_message_iter_get_string_array (DBusMessageIter *iter,
char ***value,
int *len);
+dbus_bool_t dbus_message_iter_get_dict (DBusMessageIter *iter,
+ DBusDict **dict);
DBUS_END_DECLS;
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index 1a6fcb80..e0b0c985 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -53,6 +53,7 @@ extern "C" {
#define DBUS_TYPE_DOUBLE_ARRAY 10
#define DBUS_TYPE_BYTE_ARRAY 11
#define DBUS_TYPE_STRING_ARRAY 12
+#define DBUS_TYPE_DICT 13
/* Header flags */
#define DBUS_HEADER_FLAG_ERROR 0x1
diff --git a/dbus/dbus.h b/dbus/dbus.h
index 025ccbb2..1128d362 100644
--- a/dbus/dbus.h
+++ b/dbus/dbus.h
@@ -29,6 +29,7 @@
#include <dbus/dbus-address.h>
#include <dbus/dbus-bus.h>
#include <dbus/dbus-connection.h>
+#include <dbus/dbus-dict.h>
#include <dbus/dbus-errors.h>
#include <dbus/dbus-macros.h>
#include <dbus/dbus-message.h>
diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml
index 0845d806..dba70baf 100644
--- a/doc/dbus-specification.sgml
+++ b/doc/dbus-specification.sgml
@@ -406,7 +406,12 @@
<entry>UINT32 giving the number of values in the array,
followed by the given number of STRING values.
</entry>
- </row>
+ </row><row>
+ <entry>DICT</entry>
+ <entry>STRING_ARRAY with the keys, followed by the given
+ number of values encoded as type code as a byte followed by the encoded value.
+ </entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
diff --git a/test/data/invalid-messages/dict-with-nil-value.message b/test/data/invalid-messages/dict-with-nil-value.message
new file mode 100644
index 00000000..8f899605
--- /dev/null
+++ b/test/data/invalid-messages/dict-with-nil-value.message
@@ -0,0 +1,12 @@
+# Message with lots of different argument types
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'nil', 'uint32' }
+TYPE NIL
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Body
diff --git a/test/data/invalid-messages/too-short-dict.message b/test/data/invalid-messages/too-short-dict.message
new file mode 100644
index 00000000..6df40b33
--- /dev/null
+++ b/test/data/invalid-messages/too-short-dict.message
@@ -0,0 +1,11 @@
+# Message with lots of different argument types
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'int32', 'uint32' }
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Body
diff --git a/test/data/valid-messages/dict-simple.message b/test/data/valid-messages/dict-simple.message
new file mode 100644
index 00000000..0b9d0186
--- /dev/null
+++ b/test/data/valid-messages/dict-simple.message
@@ -0,0 +1,11 @@
+# A simple dict
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'int32' }
+TYPE INT32
+INT32 0x12345678
+END_LENGTH Body
diff --git a/test/data/valid-messages/dict.message b/test/data/valid-messages/dict.message
new file mode 100644
index 00000000..0532e682
--- /dev/null
+++ b/test/data/valid-messages/dict.message
@@ -0,0 +1,29 @@
+# Dict with different values
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'boolean', 'int32', 'uint32', 'double', 'string', 'boolean_array', 'int32_array', 'uint32_array', 'double_array', 'string_array' }
+TYPE BOOLEAN
+BYTE 1
+TYPE INT32
+INT32 0x12345678
+TYPE UINT32
+UINT32 0x8765432
+TYPE DOUBLE
+DOUBLE 3.141592653589
+TYPE STRING
+STRING 'This is a string'
+TYPE BOOLEAN_ARRAY
+BOOLEAN_ARRAY { true, false, false, true, false }
+TYPE INT32_ARRAY
+INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
+TYPE UINT32_ARRAY
+UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
+TYPE DOUBLE_ARRAY
+DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
+TYPE STRING_ARRAY
+STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+END_LENGTH Body