* @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
*
*/
_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);
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;
}
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.
*
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
*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");
*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;
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");
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);
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);
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;
}
}
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);
}
}
/**
+ * 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
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);
}
_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;
* @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,
* @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,
}
/**
+ * 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
*/
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;
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))
{
/* 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)
{
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;
}
failed:
if (message)
dbus_message_unref (message);
+
return retval;
}