summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-marshal.c
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@codefactory.se>2003-03-10 00:13:55 +0000
committerAnders Carlsson <andersca@codefactory.se>2003-03-10 00:13:55 +0000
commit799a3ff443f5357ae7857ebe989a7f92f7bd84df (patch)
tree5217028097693381989fa0a1480e0ac863cba58a /dbus/dbus-marshal.c
parent1458fb145fdfe7e7ca11c88f8e2f117d90a906d8 (diff)
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.
Diffstat (limited to 'dbus/dbus-marshal.c')
-rw-r--r--dbus/dbus-marshal.c588
1 files changed, 579 insertions, 9 deletions
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);