summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog74
-rw-r--r--bus/driver.c5
-rw-r--r--dbus/Makefile.am2
-rw-r--r--dbus/dbus-dict.c1139
-rw-r--r--dbus/dbus-dict.h133
-rw-r--r--dbus/dbus-internals.c18
-rw-r--r--dbus/dbus-marshal.c958
-rw-r--r--dbus/dbus-marshal.h15
-rw-r--r--dbus/dbus-message-builder.c181
-rw-r--r--dbus/dbus-message.c2542
-rw-r--r--dbus/dbus-message.h186
-rw-r--r--dbus/dbus-protocol.h25
-rw-r--r--dbus/dbus-string.c4
-rw-r--r--dbus/dbus-sysdeps.c188
-rw-r--r--dbus/dbus-test-main.c4
-rw-r--r--dbus/dbus-test.c6
-rw-r--r--dbus/dbus.h1
-rw-r--r--doc/dbus-specification.sgml89
-rw-r--r--glib/test-thread-client.c9
-rw-r--r--glib/test-thread-server.c23
-rw-r--r--test/data/incomplete-messages/missing-body.message4
-rw-r--r--test/data/invalid-messages/bad-boolean-array.message6
-rw-r--r--test/data/invalid-messages/bad-boolean.message3
-rw-r--r--test/data/invalid-messages/boolean-array-length-too-long.message-rawbin27 -> 27 bytes
-rw-r--r--test/data/invalid-messages/boolean-has-no-value.message-rawbin102 -> 102 bytes
-rw-r--r--test/data/invalid-messages/dict-with-nil-value.message12
-rw-r--r--test/data/invalid-messages/too-short-dict.message6
-rw-r--r--test/data/valid-messages/dict-simple.message5
-rw-r--r--test/data/valid-messages/dict.message29
-rw-r--r--test/data/valid-messages/emptiness.message47
-rw-r--r--test/data/valid-messages/lots-of-arguments.message48
-rw-r--r--test/data/valid-messages/no-padding.message3
-rw-r--r--test/data/valid-messages/recursive-types.message65
-rw-r--r--test/test-service.c5
34 files changed, 2753 insertions, 3082 deletions
diff --git a/ChangeLog b/ChangeLog
index d7542dc3..ec91b569 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,77 @@
+2003-04-08 Alexander Larsson <alexl@redhat.com>
+
+ Implemented recursive types, named types and new-style iters
+
+ * bus/driver.c:
+ * glib/test-thread-client.c: (thread_func):
+ * glib/test-thread-server.c: (handle_test_message):
+ * test/test-service.c: (handle_echo):
+ Update to new api
+
+ * dbus/Makefile.am:
+ * dbus/dbus-dict.c:
+ * dbus/dbus-dict.h:
+ * dbus/dbus.h
+ Remove DBusDict
+
+ * dbus/dbus-internals.c: (_dbus_type_to_string):
+ Update for new types.
+
+ * dbus/dbus-marshal.[ch]:
+ Implement recursive types and the new marshalling format.
+ Remove hardcoded dict marshalling.
+ Marshal named types.
+
+ * dbus/dbus-message-builder.c:
+ Add BYTE_ARRAY.
+ Remove references to old types
+
+ * dbus/dbus-message.[ch]:
+ New non-refcounted iter API that supports recursive iters.
+ Use iters for appending, including support for recursive
+ iters.
+ Add byte and named type support.
+ Update everything to new marshalling formats.
+ Add tests for new API.
+
+ * dbus/dbus-protocol.h:
+ Remove old array types.
+ Add types: BYTE, ARRAY, DICT, NAMED
+
+ * dbus/dbus-string.c:
+ * dbus/dbus-sysdeps.c:
+ Make parse_double locale safe.
+
+ * dbus/dbus-test-main.c:
+ Call setlocale.
+
+ * dbus/dbus-test.c:
+ Kill dict test
+
+ * doc/dbus-specification.sgml:
+ Update spec
+
+ * test/data/incomplete-messages/missing-body.message:
+ * test/data/invalid-messages/bad-boolean.message:
+ * test/data/invalid-messages/bad-boolean-array.message:
+ * test/data/invalid-messages/boolean-array-length-too-long.message-raw:
+ * test/data/invalid-messages/boolean-has-no-value.message-raw:
+ * test/data/invalid-messages/too-short-dict.message:
+ * test/data/valid-messages/dict-simple.message:
+ * test/data/valid-messages/dict.message:
+ * test/data/valid-messages/emptiness.message:
+ * test/data/valid-messages/lots-of-arguments.message:
+ * test/data/valid-messages/no-padding.message:
+ * test/data/valid-messages/recursive-types.message:
+ Add missing NAME fields
+ Fix up dicts & arrays
+
+ * test/data/invalid-messages/dict-with-nil-value.message:
+ Removed, this is not invalid anymore.
+
+ * test/data/valid-messages/recursive-types.message:
+ Add new test for deeply recursive types.
+
2003-04-07 Havoc Pennington <hp@pobox.com>
* bus/driver.c (bus_driver_handle_acquire_service): return an
diff --git a/bus/driver.c b/bus/driver.c
index 814e32a6..ba31f3e7 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -405,7 +405,7 @@ bus_driver_handle_list_services (DBusConnection *connection,
}
if (!dbus_message_append_args (reply,
- DBUS_TYPE_STRING_ARRAY, services, len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, services, len,
0))
{
dbus_free_string_array (services);
@@ -450,8 +450,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection,
registry = bus_connection_get_registry (connection);
- if (!dbus_message_get_args (message,
- error,
+ if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_UINT32, &flags,
0))
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 957227e8..d99ff1c1 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -11,7 +11,6 @@ dbusinclude_HEADERS= \
dbus-address.h \
dbus-bus.h \
dbus-connection.h \
- dbus-dict.h \
dbus-errors.h \
dbus-macros.h \
dbus-memory.h \
@@ -33,7 +32,6 @@ DBUS_LIB_SOURCES= \
dbus-bus.c \
dbus-connection.c \
dbus-connection-internal.h \
- dbus-dict.c \
dbus-errors.c \
dbus-keyring.c \
dbus-keyring.h \
diff --git a/dbus/dbus-dict.c b/dbus/dbus-dict.c
deleted file mode 100644
index e19f9a65..00000000
--- a/dbus/dbus-dict.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu" -*- */
-/* dbus-dict.h Dict object for key-value data.
- *
- * Copyright (C) 2003 CodeFactory AB
- *
- * Licensed under the Academic Free License version 1.2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include "dbus-dict.h"
-#include "dbus-hash.h"
-#include "dbus-internals.h"
-#include "dbus-protocol.h"
-
-/**
- * @defgroup DBusDict DBusDict
- * @ingroup DBus
- * @brief key/value data structure.
- *
- * A DBusDict is a data structure that can store and lookup different
- * values by name.
- *
- * @{
- */
-
-struct DBusDict
-{
- int refcount;
-
- DBusHashTable *table;
-};
-
-typedef struct
-{
- int type;
- union {
- dbus_bool_t boolean_value;
- dbus_int32_t int32_value;
- dbus_uint32_t uint32_value;
- double double_value;
- char *string_value;
- struct {
- unsigned char *value;
- int len;
- } byte_array;
- struct {
- dbus_int32_t *value;
- int len;
- } int32_array;
- struct {
- dbus_uint32_t *value;
- int len;
- } uint32_array;
- struct {
- double *value;
- int len;
- } double_array;
- struct {
- char **value;
- int len;
- } string_array;
- } v;
-} DBusDictEntry;
-
-static void
-dbus_dict_entry_free (DBusDictEntry *entry)
-{
- if (!entry)
- return;
-
- switch (entry->type)
- {
- case DBUS_TYPE_INVALID:
- case DBUS_TYPE_BOOLEAN:
- case DBUS_TYPE_INT32:
- case DBUS_TYPE_UINT32:
- case DBUS_TYPE_DOUBLE:
- break;
- case DBUS_TYPE_STRING:
- dbus_free (entry->v.string_value);
- break;
- case DBUS_TYPE_BYTE_ARRAY:
- case DBUS_TYPE_BOOLEAN_ARRAY:
- dbus_free (entry->v.byte_array.value);
- break;
- case DBUS_TYPE_INT32_ARRAY:
- dbus_free (entry->v.int32_array.value);
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- dbus_free (entry->v.uint32_array.value);
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- dbus_free (entry->v.uint32_array.value);
- break;
- case DBUS_TYPE_STRING_ARRAY:
- dbus_free_string_array (entry->v.string_array.value);
- break;
- default:
- _dbus_assert_not_reached ("Unknown or invalid dict entry type\n");
- }
-
- dbus_free (entry);
-}
-
-/**
- * Constructs a new DBusDict. Returns #NULL if memory can't be
- * allocated.
- *
- * @returns a new DBusDict or #NULL.
- */
-DBusDict *
-dbus_dict_new (void)
-{
- DBusDict *dict;
-
- dict = dbus_new0 (DBusDict, 1);
-
- if (!dict)
- return NULL;
-
- dict->table = _dbus_hash_table_new (DBUS_HASH_STRING, dbus_free, (DBusFreeFunction)dbus_dict_entry_free);
-
- if (!dict->table)
- {
- dbus_free (dict);
- return NULL;
- }
-
- dict->refcount = 1;
-
- return dict;
-}
-
-/**
- * Increments the reference count of a DBusDict.
- *
- * @param dict the dict.
- * @see dbus_dict_unref
- */
-void
-dbus_dict_ref (DBusDict *dict)
-{
- dict->refcount += 1;
-
- _dbus_assert (dict->refcount > 1);
-}
-
-/**
- * Decrements the reference count of a DBusDict
- *
- * @param dict the dict
- * @see dbus_dict_ref
- */
-void
-dbus_dict_unref (DBusDict *dict)
-{
- dict->refcount -= 1;
-
- _dbus_assert (dict->refcount >= 0);
-
- if (dict->refcount == 0)
- {
- _dbus_hash_table_unref (dict->table);
- dbus_free (dict);
- }
-}
-
-/**
- * Checks if the dict contains the specified key.
- *
- * @param dict the dict.
- * @param key the key
- * @returns #TRUE if the dict contains the specified key.
- */
-dbus_bool_t
-dbus_dict_contains (DBusDict *dict,
- const char *key)
-{
- return (_dbus_hash_table_lookup_string (dict->table, key) != NULL);
-}
-
-/**
- * Removes the dict entry for the given key. If no dict entry for the
- * key exists, this function does nothing.
- *
- * @param dict the dict
- * @param key the key
- * @returns #TRUE if the entry existed
- */
-dbus_bool_t
-dbus_dict_remove (DBusDict *dict,
- const char *key)
-{
- return _dbus_hash_table_remove_string (dict->table, key);
-}
-
-/**
- * Returns the type of the value in the dict entry specified by the key.
- *
- * @param dict the dict
- * @param key the key
- * @returns the value type or DBUS_TYPE_NIL if the key wasn't found.
- */
-int
-dbus_dict_get_value_type (DBusDict *dict,
- const char *key)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry)
- return DBUS_TYPE_NIL;
- else
- return entry->type;
-}
-
-/**
- * Returns the keys in the dict as a string array.
- *
- * @param dict the dict
- * @param keys return location for string array
- * @param len return location for string array length
- * ®returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_get_keys (DBusDict *dict,
- char ***keys,
- int *len)
-{
- int size, i;
- char **tmp;
- char *key;
- DBusHashIter iter;
-
- size = _dbus_hash_table_get_n_entries (dict->table);
- *len = size;
-
- if (size == 0)
- {
- *keys = NULL;
- return TRUE;
- }
-
- tmp = dbus_new0 (char *, size + 1);
- if (!tmp)
- return FALSE;
-
-
- i = 0;
- _dbus_hash_iter_init (dict->table, &iter);
-
- while (_dbus_hash_iter_next (&iter))
- {
- key = _dbus_strdup (_dbus_hash_iter_get_string_key (&iter));
-
- if (!key)
- {
- dbus_free_string_array (tmp);
- return FALSE;
- }
-
- tmp[i] = key;
- i++;
- }
-
- *keys = tmp;
-
- return TRUE;
-}
-
-static dbus_bool_t
-insert_entry (DBusDict *dict,
- const char *key,
- DBusDictEntry **entry)
-{
- char *tmp;
-
- tmp = _dbus_strdup (key);
-
- if (!tmp)
- return FALSE;
-
- *entry = dbus_new0 (DBusDictEntry, 1);
-
- if (!*entry)
- {
- dbus_free (tmp);
- return FALSE;
- }
-
- if (!_dbus_hash_table_insert_string (dict->table, tmp, *entry))
- {
- dbus_free (tmp);
- dbus_dict_entry_free (*entry);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Adds a boolean value to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BOOLEAN;
- entry->v.boolean_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit signed integer value to the dict. If a value with the
- * same key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_INT32;
- entry->v.int32_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit unsigned integer value to the dict. If a value with
- * the same key already exists, then it will be replaced by the new
- * value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_UINT32;
- entry->v.uint32_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit double value to the dict. If a value with the same
- * key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_double (DBusDict *dict,
- const char *key,
- double value)
-{
- DBusDictEntry *entry;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_DOUBLE;
- entry->v.double_value = value;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a string to the dict. If a value with the same key already
- * exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_string (DBusDict *dict,
- const char *key,
- const char *value)
-{
- DBusDictEntry *entry;
- char *tmp;
-
- tmp = _dbus_strdup (value);
-
- if (!tmp)
- return FALSE;
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_STRING;
- entry->v.string_value = tmp;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a boolean array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len)
-{
- DBusDictEntry *entry;
- unsigned char *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_malloc (len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len);
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BOOLEAN_ARRAY;
- entry->v.byte_array.value = tmp;
- entry->v.byte_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit signed integer array to the dict. If a value with the
- * same key already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t *value,
- int len)
-{
- DBusDictEntry *entry;
- dbus_int32_t *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (dbus_int32_t, len);
-
- if (!tmp)
- return FALSE;
- }
-
- memcpy (tmp, value, len * sizeof (dbus_int32_t));
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_INT32_ARRAY;
- entry->v.int32_array.value = tmp;
- entry->v.int32_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a 32 bit unsigned integer array to the dict. If a value with
- * the same key already exists, then it will be replaced by the new
- * value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t *value,
- int len)
-{
- DBusDictEntry *entry;
- dbus_uint32_t *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (dbus_uint32_t, len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len * sizeof (dbus_uint32_t));
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_UINT32_ARRAY;
- entry->v.uint32_array.value = tmp;
- entry->v.int32_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a double array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_double_array (DBusDict *dict,
- const char *key,
- const double *value,
- int len)
-{
- DBusDictEntry *entry;
- double *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_new (double, len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len * sizeof (double));
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_DOUBLE_ARRAY;
- entry->v.double_array.value = tmp;
- entry->v.double_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Adds a byte array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len)
-{
- DBusDictEntry *entry;
- unsigned char *tmp;
-
- if (len == 0)
- tmp = NULL;
- else
- {
- tmp = dbus_malloc (len);
-
- if (!tmp)
- return FALSE;
-
- memcpy (tmp, value, len);
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_BYTE_ARRAY;
- entry->v.byte_array.value = tmp;
- entry->v.byte_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-/**
- * Adds a string array to the dict. If a value with the same key
- * already exists, then it will be replaced by the new value.
- *
- * @param dict the dict
- * @param key the key
- * @param value the value
- * @param len the array length
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_dict_set_string_array (DBusDict *dict,
- const char *key,
- const char **value,
- int len)
-{
- DBusDictEntry *entry;
- char **tmp;
- int i;
-
- tmp = dbus_new0 (char *, len + 1);
- if (!tmp)
- return FALSE;
-
- tmp[len] = NULL;
-
- for (i = 0; i < len; i++)
- {
- tmp[i] = _dbus_strdup (value[i]);
- if (!tmp[i])
- {
- dbus_free_string_array (tmp);
- return FALSE;
- }
- }
-
- if (insert_entry (dict, key, &entry))
- {
- entry->type = DBUS_TYPE_STRING_ARRAY;
- entry->v.string_array.value = tmp;
- entry->v.string_array.len = len;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/**
- * Gets a boolean value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BOOLEAN)
- return FALSE;
-
- *value = entry->v.boolean_value;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit signed integer value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_INT32)
- return FALSE;
-
- *value = entry->v.int32_value;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit unsigned integer value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_UINT32)
- return FALSE;
-
- *value = entry->v.uint32_value;
-
- return TRUE;
-}
-
-/**
- * Gets a double value from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_double (DBusDict *dict,
- const char *key,
- double *value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_DOUBLE)
- return FALSE;
-
- *value = entry->v.double_value;
-
- return TRUE;
-}
-
-/**
- * Gets a string from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_string (DBusDict *dict,
- const char *key,
- const char **value)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_STRING)
- return FALSE;
-
- *value = entry->v.string_value;
-
- return TRUE;
-}
-
-/**
- * Gets a boolean array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BOOLEAN_ARRAY)
- return FALSE;
-
- *value = entry->v.byte_array.value;
- *len = entry->v.byte_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit signed integer array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_INT32_ARRAY)
- return FALSE;
-
- *value = entry->v.int32_array.value;
- *len = entry->v.int32_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a 32 bit unsigned integer array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_UINT32_ARRAY)
- return FALSE;
-
- *value = entry->v.uint32_array.value;
- *len = entry->v.uint32_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a double array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_double_array (DBusDict *dict,
- const char *key,
- const double **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_DOUBLE_ARRAY)
- return FALSE;
-
- *value = entry->v.double_array.value;
- *len = entry->v.double_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a byte array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_BYTE_ARRAY)
- return FALSE;
-
- *value = entry->v.byte_array.value;
- *len = entry->v.byte_array.len;
-
- return TRUE;
-}
-
-/**
- * Gets a string array from a dict using a key.
- *
- * @param dict the dict
- * @param key the key
- * @param value return location for the value
- * @param len return location for the array length
- * @returns #TRUE if the key exists and the value is of the correct
- * type
- */
-dbus_bool_t
-dbus_dict_get_string_array (DBusDict *dict,
- const char *key,
- const char ***value,
- int *len)
-{
- DBusDictEntry *entry;
-
- entry = _dbus_hash_table_lookup_string (dict->table, key);
-
- if (!entry || entry->type != DBUS_TYPE_STRING_ARRAY)
- return FALSE;
-
- *value = (const char **)entry->v.string_array.value;
- *len = entry->v.string_array.len;
-
- return TRUE;
-}
-
-/** @} */
-
-#ifdef DBUS_BUILD_TESTS
-#include "dbus-test.h"
-
-dbus_bool_t
-_dbus_dict_test (void)
-{
- DBusDict *dict;
- 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;
- int i, len;
-
- /* We don't test much here since the hash table tests cover a great
- deal of the functionality. */
-
- 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_get_boolean (dict, "boolean", &our_bool) ||
- !our_bool)
- _dbus_assert_not_reached ("could not get boolean value");
-
- if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
- _dbus_assert_not_reached ("could not add int32 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_set_uint32 (dict, "uint32", 0x87654321))
- _dbus_assert_not_reached ("could not add uint32 value");
-
- 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_set_double (dict, "double", 3.14159))
- _dbus_assert_not_reached ("could not add double value");
-
- 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_set_string (dict, "string", "test string"))
- _dbus_assert_not_reached ("could not add string value");
-
- 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_set_boolean_array (dict, "boolean_array", boolean_array, 4))
- _dbus_assert_not_reached ("could not add boolean array");
-
- 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_set_int32_array (dict, "int32_array", int32_array, 5))
- _dbus_assert_not_reached ("could not add int32 array");
-
- 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_set_uint32_array (dict, "uint32_array", uint32_array, 5))
- _dbus_assert_not_reached ("could not add uint32 array");
-
- 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_set_double_array (dict, "double_array", double_array, 3))
- _dbus_assert_not_reached ("could not add double array");
-
- 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_set_string_array (dict, "string_array", string_array, 4))
- _dbus_assert_not_reached ("could not add string array");
-
- 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);
-
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-dict.h b/dbus/dbus-dict.h
deleted file mode 100644
index b3b6eb90..00000000
--- a/dbus/dbus-dict.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu" -*- */
-/* dbus-dict.h Dict object for key-value data.
- *
- * Copyright (C) 2003 CodeFactory AB
- *
- * Licensed under the Academic Free License version 1.2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#if !defined (DBUS_INSIDE_DBUS_H) && !defined (DBUS_COMPILATION)
-#error "Only <dbus/dbus.h> can be included directly, this file may disappear or change contents."
-#endif
-
-#ifndef DBUS_DICT_H
-#define DBUS_DICT_H
-
-#include <dbus/dbus-macros.h>
-#include <dbus/dbus-types.h>
-
-DBUS_BEGIN_DECLS;
-
-typedef struct DBusDict DBusDict;
-
-DBusDict * dbus_dict_new (void);
-void dbus_dict_ref (DBusDict *dict);
-void dbus_dict_unref (DBusDict *dict);
-dbus_bool_t dbus_dict_contains (DBusDict *dict,
- const char *key);
-dbus_bool_t dbus_dict_remove (DBusDict *dict,
- const char *key);
-int dbus_dict_get_value_type (DBusDict *dict,
- const char *key);
-dbus_bool_t dbus_dict_get_keys (DBusDict *dict,
- char ***keys,
- int *len);
-
-dbus_bool_t dbus_dict_set_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t value);
-dbus_bool_t dbus_dict_set_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t value);
-dbus_bool_t dbus_dict_set_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t value);
-dbus_bool_t dbus_dict_set_double (DBusDict *dict,
- const char *key,
- double value);
-dbus_bool_t dbus_dict_set_string (DBusDict *dict,
- const char *key,
- const char *value);
-dbus_bool_t dbus_dict_set_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len);
-dbus_bool_t dbus_dict_set_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t *value,
- int len);
-dbus_bool_t dbus_dict_set_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t *value,
- int len);
-dbus_bool_t dbus_dict_set_double_array (DBusDict *dict,
- const char *key,
- const double *value,
- int len);
-dbus_bool_t dbus_dict_set_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char *value,
- int len);
-dbus_bool_t dbus_dict_set_string_array (DBusDict *dict,
- const char *key,
- const char **value,
- int len);
-
-dbus_bool_t dbus_dict_get_boolean (DBusDict *dict,
- const char *key,
- dbus_bool_t *value);
-dbus_bool_t dbus_dict_get_int32 (DBusDict *dict,
- const char *key,
- dbus_int32_t *value);
-dbus_bool_t dbus_dict_get_uint32 (DBusDict *dict,
- const char *key,
- dbus_uint32_t *value);
-dbus_bool_t dbus_dict_get_double (DBusDict *dict,
- const char *key,
- double *value);
-dbus_bool_t dbus_dict_get_string (DBusDict *dict,
- const char *key,
- const char **value);
-dbus_bool_t dbus_dict_get_boolean_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len);
-dbus_bool_t dbus_dict_get_int32_array (DBusDict *dict,
- const char *key,
- const dbus_int32_t **value,
- int *len);
-dbus_bool_t dbus_dict_get_uint32_array (DBusDict *dict,
- const char *key,
- const dbus_uint32_t **value,
- int *len);
-dbus_bool_t dbus_dict_get_double_array (DBusDict *dict,
- const char *key,
- const double **value,
- int *len);
-dbus_bool_t dbus_dict_get_byte_array (DBusDict *dict,
- const char *key,
- unsigned const char **value,
- int *len);
-dbus_bool_t dbus_dict_get_string_array (DBusDict *dict,
- const char *key,
- const char ***value,
- int *len);
-
-
-DBUS_END_DECLS
-
-#endif /* DBUS_DICT_H */
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 8d803977..de98c1fc 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -328,18 +328,12 @@ _dbus_type_to_string (int type)
return "double";
case DBUS_TYPE_STRING:
return "string";
- case DBUS_TYPE_BOOLEAN_ARRAY:
- return "boolean array";
- case DBUS_TYPE_INT32_ARRAY:
- return "int32 array";
- case DBUS_TYPE_UINT32_ARRAY:
- return "uint32 array";
- case DBUS_TYPE_DOUBLE_ARRAY:
- return "double array";
- case DBUS_TYPE_BYTE_ARRAY:
- return "byte array";
- case DBUS_TYPE_STRING_ARRAY:
- return "string array";
+ case DBUS_TYPE_NAMED:
+ return "named";
+ case DBUS_TYPE_ARRAY:
+ return "array";
+ case DBUS_TYPE_DICT:
+ return "dict";
default:
return "unknown";
}
diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c
index 2222ad9b..a5cea383 100644
--- a/dbus/dbus-marshal.c
+++ b/dbus/dbus-marshal.c
@@ -298,6 +298,9 @@ _dbus_marshal_uint32 (DBusString *str,
/**
* Marshals a UTF-8 string
*
+ * @todo: If the string append fails we need to restore
+ * the old length. (also for other marshallers)
+ *
* @param str the string to append the marshalled value to
* @param byte_order the byte order to use
* @param value the string
@@ -377,7 +380,7 @@ _dbus_marshal_int32_array (DBusString *str,
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_int32_t)))
goto error;
for (i = 0; i < len; i++)
@@ -412,7 +415,7 @@ _dbus_marshal_uint32_array (DBusString *str,
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ if (!_dbus_marshal_uint32 (str, byte_order, len * sizeof (dbus_uint32_t)))
goto error;
for (i = 0; i < len; i++)
@@ -443,17 +446,25 @@ _dbus_marshal_double_array (DBusString *str,
const double *value,
int len)
{
- int i, old_string_len;
+ int i, old_string_len, array_start;
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ /* Set the length to 0 temporarily */
+ if (!_dbus_marshal_uint32 (str, byte_order, 0))
goto error;
-
+
+ array_start = _dbus_string_get_length (str);
+
for (i = 0; i < len; i++)
if (!_dbus_marshal_double (str, byte_order, value[i]))
goto error;
+ /* Write the length now that we know it */
+ _dbus_marshal_set_uint32 (str, byte_order,
+ _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
+ _dbus_string_get_length (str) - array_start);
+
return TRUE;
error:
@@ -478,17 +489,25 @@ _dbus_marshal_string_array (DBusString *str,
const char **value,
int len)
{
- int i, old_string_len;
+ int i, old_string_len, array_start;
old_string_len = _dbus_string_get_length (str);
- if (!_dbus_marshal_uint32 (str, byte_order, len))
+ /* Set the length to 0 temporarily */
+ if (!_dbus_marshal_uint32 (str, byte_order, 0))
goto error;
+ array_start = _dbus_string_get_length (str);
+
for (i = 0; i < len; i++)
if (!_dbus_marshal_string (str, byte_order, value[i]))
goto error;
+ /* Write the length now that we know it */
+ _dbus_marshal_set_uint32 (str, byte_order,
+ _DBUS_ALIGN_VALUE (old_string_len, sizeof(dbus_uint32_t)),
+ _dbus_string_get_length (str) - array_start);
+
return TRUE;
error:
@@ -500,192 +519,6 @@ _dbus_marshal_string_array (DBusString *str,
/**
- * 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,
- (const char **)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, (const char **)value, len))
- goto error;
-
- break;
- }
- default:
- _dbus_warn ("unkown 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.
*
* @param str the string containing the data
@@ -807,7 +640,7 @@ _dbus_demarshal_string (const DBusString *str,
if (!retval)
return NULL;
- data = _dbus_string_get_const_data_len (str, pos, len);
+ data = _dbus_string_get_const_data_len (str, pos, len + 1);
if (!data)
return NULL;
@@ -906,7 +739,7 @@ _dbus_demarshal_int32_array (const DBusString *str,
int len, i;
dbus_int32_t *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (dbus_int32_t);
if (len == 0)
{
@@ -958,7 +791,7 @@ _dbus_demarshal_uint32_array (const DBusString *str,
int len, i;
dbus_uint32_t *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (dbus_uint32_t);
if (len == 0)
{
@@ -1010,7 +843,7 @@ _dbus_demarshal_double_array (const DBusString *str,
int len, i;
double *retval;
- len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos) / sizeof (double);
if (len == 0)
{
@@ -1106,219 +939,6 @@ _dbus_demarshal_string_array (const DBusString *str,
return FALSE;
}
-/**
- * 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
- * @param dict the dict
- * @returns #TRUE on success.
- */
-dbus_bool_t
-_dbus_demarshal_dict (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- DBusDict **dict)
-{
- char **keys;
- int i, len;
-
- *dict = dbus_dict_new ();
- if (!*dict)
- return FALSE;
-
- if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &keys, &len))
- 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;
-
- if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
- 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;
-
- if (!_dbus_demarshal_int32_array (str, byte_order, pos, &pos, &value, &len))
- 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;
-
- if (!_dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &value, &len))
- 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;
-
- if (!_dbus_demarshal_double_array (str, byte_order, pos, &pos, &value, &len))
- 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_BYTE_ARRAY:
- {
- unsigned char *value;
- int len;
-
- if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_byte_array (*dict, keys[i], value, len))
- {
- dbus_free (value);
- goto error;
- }
-
- dbus_free (value);
- break;
- }
- case DBUS_TYPE_STRING_ARRAY:
- {
- char **value;
- int len;
-
- if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &value, &len))
- goto error;
-
- if (!dbus_dict_set_string_array (*dict, keys[i], (const char **)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 TRUE;
-
- error:
- dbus_free_string_array (keys);
- dbus_dict_unref (*dict);
-
- return FALSE;
-}
-
/**
* Returns the position right after the end of an argument. PERFORMS
* NO VALIDATION WHATSOEVER. The message must have been previously
@@ -1326,6 +946,7 @@ _dbus_demarshal_dict (const DBusString *str,
*
* @param str a string
* @param byte_order the byte order to use
+ * @param type the type of the argument
* @param pos the pos where the arg starts
* @param end_pos pointer where the position right
* after the end position will follow
@@ -1334,153 +955,97 @@ _dbus_demarshal_dict (const DBusString *str,
dbus_bool_t
_dbus_marshal_get_arg_end_pos (const DBusString *str,
int byte_order,
+ int type,
int pos,
int *end_pos)
{
- const char *data;
-
if (pos >= _dbus_string_get_length (str))
return FALSE;
- data = _dbus_string_get_const_data_len (str, pos, 1);
-
- switch (*data)
+ switch (type)
{
case DBUS_TYPE_INVALID:
return FALSE;
break;
case DBUS_TYPE_NIL:
- *end_pos = pos + 1;
+ *end_pos = pos;
break;
- case DBUS_TYPE_BOOLEAN:
- *end_pos = pos + 2;
+ case DBUS_TYPE_BYTE:
+ *end_pos = pos + 1;
break;
+ case DBUS_TYPE_BOOLEAN:
+ *end_pos = pos + 1;
+ break;
+
case DBUS_TYPE_INT32:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_int32_t)) + sizeof (dbus_int32_t);
break;
case DBUS_TYPE_UINT32:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t)) + sizeof (dbus_uint32_t);
break;
case DBUS_TYPE_DOUBLE:
- *end_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (double)) + sizeof (double);
+ *end_pos = _DBUS_ALIGN_VALUE (pos, sizeof (double)) + sizeof (double);
break;
case DBUS_TYPE_STRING:
{
int len;
-
+
/* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
*end_pos = pos + len + 1;
}
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
- case DBUS_TYPE_BYTE_ARRAY:
+ case DBUS_TYPE_NAMED:
{
int len;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
- *end_pos = pos + len;
- }
- break;
+ /* Demarshal the string length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- case DBUS_TYPE_INT32_ARRAY:
- {
- int len, new_pos;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
-
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_int32_t))
- + (len * sizeof (dbus_int32_t));
- }
- break;
-
- case DBUS_TYPE_UINT32_ARRAY:
- {
- int len, new_pos;
-
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
-
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (dbus_uint32_t))
- + (len * sizeof (dbus_uint32_t));
- }
- break;
-
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- int len, new_pos;
+ *end_pos = pos + len + 1;
- /* Demarshal the length */
- len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &new_pos);
+ /* Demarshal the data length */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- *end_pos = _DBUS_ALIGN_VALUE (new_pos, sizeof (double))
- + (len * sizeof (double));
+ *end_pos = pos + len;
}
break;
- case DBUS_TYPE_STRING_ARRAY:
+ case DBUS_TYPE_ARRAY:
{
- 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;
- }
+ int len;
- *end_pos = pos;
+ /* Demarshal the length (element type is at pos + 0 */
+ len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+
+ *end_pos = pos + len;
}
break;
case DBUS_TYPE_DICT:
{
- int len, i;
+ int len;
/* 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;
+ len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
- break;
+ *end_pos = pos + len;
}
+ break;
+
default:
- _dbus_warn ("Unknown message arg type %d\n", *data);
+ _dbus_warn ("Unknown message arg type %d\n", type);
_dbus_assert_not_reached ("Unknown message argument type\n");
return FALSE;
}
@@ -1530,8 +1095,8 @@ demarshal_and_validate_len (const DBusString *str,
len = _dbus_demarshal_uint32 (str, byte_order, align_4, new_pos);
- /* note that the len may be a number of doubles, so we need it to be
- * at least SIZE_T_MAX / 8, but make it smaller just to keep things
+ /* note that the len is the number of bytes, so we need it to be
+ * at least SIZE_T_MAX, but make it smaller just to keep things
* sane. We end up using ints for most sizes to avoid unsigned mess
* so limit to maximum 32-bit signed int divided by at least 8, more
* for a bit of paranoia margin. INT_MAX/32 is about 65 megabytes.
@@ -1576,9 +1141,45 @@ validate_string (const DBusString *str,
return TRUE;
}
+/**
+ * Validates and returns a typecode at a specific position
+ * in the message
+ *
+ * @param str a string
+ * @param type the type of the argument
+ * @param pos the pos where the typecode starts
+ * @param end_pos pointer where the position right
+ * after the end position will follow
+ * @returns #TRUE if the type is valid.
+ */
+dbus_bool_t
+_dbus_marshal_validate_type (const DBusString *str,
+ int pos,
+ int *type,
+ int *end_pos)
+{
+ const char *data;
+
+ if (pos >= _dbus_string_get_length (str))
+ return FALSE;
+
+ data = _dbus_string_get_const_data_len (str, pos, 1);
+
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ {
+ *type = *data;
+ *end_pos = pos + 1;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
/**
- * Validates an argument, checking that it is well-formed, for example
- * no ludicrous length fields, strings are nul-terminated, etc.
+ * Validates an argument of a specific type, checking that it
+ * is well-formed, for example no ludicrous length fields, strings
+ * are nul-terminated, etc.
* Returns the end position of the argument in end_pos, and
* returns #TRUE if a valid arg begins at "pos"
*
@@ -1586,7 +1187,8 @@ validate_string (const DBusString *str,
*
* @param str a string
* @param byte_order the byte order to use
- * @param pos the pos where the arg starts (offset of its typecode)
+ * @param type the type of the argument
+ * @param pos the pos where the arg starts
* @param end_pos pointer where the position right
* after the end position will follow
* @returns #TRUE if the arg is valid.
@@ -1594,37 +1196,44 @@ validate_string (const DBusString *str,
dbus_bool_t
_dbus_marshal_validate_arg (const DBusString *str,
int byte_order,
+ int type,
int pos,
int *end_pos)
{
- const char *data;
-
- if (pos >= _dbus_string_get_length (str))
+ if (pos > _dbus_string_get_length (str))
return FALSE;
- data = _dbus_string_get_const_data_len (str, pos, 1);
-
- switch (*data)
+ switch (type)
{
case DBUS_TYPE_INVALID:
return FALSE;
break;
case DBUS_TYPE_NIL:
- *end_pos = pos + 1;
+ *end_pos = pos;
break;
+ case DBUS_TYPE_BYTE:
+ if (1 > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("no room for boolean value\n");
+ return FALSE;
+ }
+
+ *end_pos = pos + 1;
+ break;
+
case DBUS_TYPE_BOOLEAN:
{
unsigned char c;
- if (2 > _dbus_string_get_length (str) - pos)
+ if (1 > _dbus_string_get_length (str) - pos)
{
_dbus_verbose ("no room for boolean value\n");
return FALSE;
}
- c = _dbus_string_get_byte (str, pos + 1);
+ c = _dbus_string_get_byte (str, pos);
if (c != 0 && c != 1)
{
@@ -1632,16 +1241,16 @@ _dbus_marshal_validate_arg (const DBusString *str,
return FALSE;
}
- *end_pos = pos + 2;
+ *end_pos = pos + 1;
break;
}
case DBUS_TYPE_INT32:
case DBUS_TYPE_UINT32:
{
- int align_4 = _DBUS_ALIGN_VALUE (pos + 1, 4);
+ int align_4 = _DBUS_ALIGN_VALUE (pos, 4);
- if (!_dbus_string_validate_nul (str, pos + 1,
- align_4 - pos - 1))
+ if (!_dbus_string_validate_nul (str, pos,
+ align_4 - pos))
{
_dbus_verbose ("int32/uint32 alignment padding not initialized to nul\n");
return FALSE;
@@ -1653,12 +1262,12 @@ _dbus_marshal_validate_arg (const DBusString *str,
case DBUS_TYPE_DOUBLE:
{
- int align_8 = _DBUS_ALIGN_VALUE (pos + 1, 8);
+ int align_8 = _DBUS_ALIGN_VALUE (pos, 8);
_dbus_verbose_bytes_of_string (str, pos, (align_8 + 8 - pos));
- if (!_dbus_string_validate_nul (str, pos + 1,
- align_8 - pos - 1))
+ if (!_dbus_string_validate_nul (str, pos,
+ align_8 - pos))
{
_dbus_verbose ("double alignment padding not initialized to nul\n");
return FALSE;
@@ -1675,7 +1284,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
/* Demarshal the length, which does NOT include
* nul termination
*/
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
@@ -1684,163 +1293,118 @@ _dbus_marshal_validate_arg (const DBusString *str,
}
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
+ case DBUS_TYPE_NAMED:
{
- int len, i;
+ int len;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ /* Demarshal the string length, which does NOT include
+ * nul termination
+ */
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- if (len > _dbus_string_get_length (str) - pos)
- {
- _dbus_verbose ("boolean array length outside length of the message\n");
- return FALSE;
- }
-
- i = 0;
- while (i < len)
- {
- unsigned char c = _dbus_string_get_byte (str, pos + i);
-
- if (c != 0 && c != 1)
- {
- _dbus_verbose ("boolean value must be either 0 or 1, not %d (pos %d)\n", c, pos);
- return FALSE;
- }
-
- i++;
- }
- *end_pos = pos + len;
- break;
- }
- case DBUS_TYPE_BYTE_ARRAY:
- {
- int len;
+ if (!validate_string (str, pos, len, &pos))
+ return FALSE;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ /* Validate data */
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
-
+
*end_pos = pos + len;
}
break;
-
- case DBUS_TYPE_INT32_ARRAY:
- case DBUS_TYPE_UINT32_ARRAY:
+
+ case DBUS_TYPE_ARRAY:
{
int len;
+ int end;
+ int array_type;
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ if (!_dbus_marshal_validate_type (str, pos, &array_type, &pos))
+ {
+ _dbus_verbose ("invalid array type\n");
+ return FALSE;
+ }
+
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- _dbus_assert (_DBUS_ALIGN_VALUE (pos, 4) == (unsigned int) pos);
-
- *end_pos = pos + len * 4;
+ if (len > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("array length outside length of the message\n");
+ return FALSE;
+ }
+
+ end = pos + len;
+
+ while (pos < end)
+ {
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ array_type, pos, &pos))
+ return FALSE;
+ }
+
+ if (pos > end)
+ {
+ _dbus_verbose ("array contents exceeds array length\n");
+ return FALSE;
+ }
+
+ *end_pos = pos;
}
break;
- case DBUS_TYPE_DOUBLE_ARRAY:
+ case DBUS_TYPE_DICT:
{
+ int dict_type;
int len;
- int align_8;
-
- len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+ int end;
+
+ len = demarshal_and_validate_len (str, byte_order, pos, &pos);
if (len < 0)
return FALSE;
- if (len == 0)
- *end_pos = pos;
- else
+ if (len > _dbus_string_get_length (str) - pos)
+ {
+ _dbus_verbose ("dict length outside length of the message\n");
+ return FALSE;
+ }
+
+ end = pos + len;
+
+ while (pos < end)
{
- align_8 = _DBUS_ALIGN_VALUE (pos, 8);
- if (!_dbus_string_validate_nul (str, pos,
- align_8 - pos))
+ /* Validate name */
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ DBUS_TYPE_STRING, pos, &pos))
+ return FALSE;
+
+ if (!_dbus_marshal_validate_type (str, pos, &dict_type, &pos))
{
- _dbus_verbose ("double array alignment padding not initialized to nul\n");
+ _dbus_verbose ("invalid dict entry type at offset %d\n", pos);
return FALSE;
}
-
- *end_pos = align_8 + len * 8;
+
+ /* Validate element */
+ if (!_dbus_marshal_validate_arg (str, byte_order,
+ dict_type, pos, &pos))
+ return FALSE;
}
- }
- break;
-
- case DBUS_TYPE_STRING_ARRAY:
- {
- 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++)
+
+ if (pos > end)
{
- 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;
+ _dbus_verbose ("dict contents exceeds array length\n");
+ return FALSE;
}
-
*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);
+ _dbus_verbose ("Unknown message arg type %d\n", type);
return FALSE;
}
@@ -1974,23 +1538,7 @@ _dbus_marshal_test (void)
DBusString str;
char *tmp1, *tmp2;
dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
- 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;
+ int pos = 0, len;
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
@@ -2055,98 +1603,6 @@ _dbus_marshal_test (void)
_dbus_assert_not_reached ("Signed integer array lengths differ!\n");
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);
-
- if (!_dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos, &dict))
- _dbus_assert_not_reached ("could not demarshal dict");
-
- 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 85549e1d..0f40cd70 100644
--- a/dbus/dbus-marshal.h
+++ b/dbus/dbus-marshal.h
@@ -25,7 +25,6 @@
#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>
@@ -124,9 +123,6 @@ 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,
@@ -173,21 +169,22 @@ dbus_bool_t _dbus_demarshal_string_array (const DBusString *str,
int *new_pos,
char ***array,
int *array_len);
-dbus_bool_t _dbus_demarshal_dict (const DBusString *str,
- int byte_order,
- int pos,
- int *new_pos,
- DBusDict **dict);
dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str,
int byte_order,
+ int type,
+ int pos,
+ int *end_pos);
+dbus_bool_t _dbus_marshal_validate_type (const DBusString *str,
int pos,
+ int *type,
int *end_pos);
dbus_bool_t _dbus_marshal_validate_arg (const DBusString *str,
int byte_order,
+ int type,
int pos,
int *end_pos);
diff --git a/dbus/dbus-message-builder.c b/dbus/dbus-message-builder.c
index 044c2a7b..dbfe3239 100644
--- a/dbus/dbus-message-builder.c
+++ b/dbus/dbus-message-builder.c
@@ -297,9 +297,12 @@ append_saved_length (DBusString *dest,
* UINT32 <N> marshals a UINT32
* DOUBLE <N> marshals a double
* STRING 'Foo' marshals a string
+ * BYTE_ARRAY { 'a', 3, 4, 5, 6} marshals a BYTE array
+ * BOOLEAN_ARRAY { false, true, false} marshals a BOOLEAN array
* INT32_ARRAY { 3, 4, 5, 6} marshals an INT32 array
* UINT32_ARRAY { 3, 4, 5, 6} marshals an UINT32 array
* DOUBLE_ARRAY { 1.0, 2.0, 3.0, 4.0} marshals a DOUBLE array
+ * STRING_ARRAY { "foo", "bar", "gazonk"} marshals a STRING array
* @endcode
*
* @todo add support for array types INT32_ARRAY { 3, 4, 5, 6 }
@@ -513,38 +516,6 @@ _dbus_message_data_load (DBusString *dest,
_dbus_string_shorten (dest, val);
}
- else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
- {
- unsigned char the_byte;
-
- _dbus_string_delete_first_word (&line);
-
- if (_dbus_string_equal_c_str (&line, "'\\''"))
- the_byte = '\'';
- else if (_dbus_string_get_byte (&line, 0) == '\'' &&
- _dbus_string_get_length (&line) >= 3 &&
- _dbus_string_get_byte (&line, 2) == '\'')
- the_byte = _dbus_string_get_byte (&line, 1);
- else
- {
- long val;
- if (!_dbus_string_parse_int (&line, 0, &val, NULL))
- {
- _dbus_warn ("Failed to parse integer for BYTE\n");
- goto parse_failed;
- }
-
- if (val > 255)
- {
- _dbus_warn ("A byte must be in range 0-255 not %ld\n",
- val);
- goto parse_failed;
- }
- the_byte = (unsigned char) val;
- }
-
- _dbus_string_append_byte (dest, the_byte);
- }
else if (_dbus_string_starts_with_c_str (&line,
"START_LENGTH"))
{
@@ -619,18 +590,8 @@ _dbus_message_data_load (DBusString *dest,
code = DBUS_TYPE_INVALID;
else if (_dbus_string_starts_with_c_str (&line, "NIL"))
code = DBUS_TYPE_NIL;
- else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN_ARRAY"))
- code = DBUS_TYPE_BOOLEAN_ARRAY;
- else if (_dbus_string_starts_with_c_str (&line, "INT32_ARRAY"))
- code = DBUS_TYPE_INT32_ARRAY;
- else if (_dbus_string_starts_with_c_str (&line, "UINT32_ARRAY"))
- code = DBUS_TYPE_UINT32_ARRAY;
- else if (_dbus_string_starts_with_c_str (&line, "DOUBLE_ARRAY"))
- code = DBUS_TYPE_DOUBLE_ARRAY;
- else if (_dbus_string_starts_with_c_str (&line, "BYTE_ARRAY"))
- code = DBUS_TYPE_BYTE_ARRAY;
- else if (_dbus_string_starts_with_c_str (&line, "STRING_ARRAY"))
- code = DBUS_TYPE_STRING_ARRAY;
+ else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
+ code = DBUS_TYPE_BYTE;
else if (_dbus_string_starts_with_c_str (&line, "BOOLEAN"))
code = DBUS_TYPE_BOOLEAN;
else if (_dbus_string_starts_with_c_str (&line, "INT32"))
@@ -641,6 +602,10 @@ _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, "NAMED"))
+ code = DBUS_TYPE_NAMED;
+ else if (_dbus_string_starts_with_c_str (&line, "ARRAY"))
+ code = DBUS_TYPE_ARRAY;
else if (_dbus_string_starts_with_c_str (&line, "DICT"))
code = DBUS_TYPE_DICT;
else
@@ -656,6 +621,100 @@ _dbus_message_data_load (DBusString *dest,
}
}
else if (_dbus_string_starts_with_c_str (&line,
+ "BYTE_ARRAY"))
+ {
+ SAVE_FOR_UNALIGN (dest, 4);
+ int i, len, allocated;
+ unsigned char *values;
+ unsigned char b;
+ long val;
+
+ allocated = 4;
+ values = dbus_new (unsigned char, allocated);
+ if (!values)
+ {
+ _dbus_warn ("could not allocate memory for BYTE_ARRAY\n");
+ goto parse_failed;
+ }
+
+ len = 0;
+
+ _dbus_string_delete_first_word (&line);
+ _dbus_string_skip_blank (&line, 0, &i);
+ b = _dbus_string_get_byte (&line, i++);
+
+ if (b != '{')
+ goto parse_failed;
+
+ while (i < _dbus_string_get_length (&line))
+ {
+ _dbus_string_skip_blank (&line, i, &i);
+
+ if (_dbus_string_get_byte (&line, i) == '\'' &&
+ _dbus_string_get_length (&line) >= i + 4 &&
+ _dbus_string_get_byte (&line, i + 1) == '\\' &&
+ _dbus_string_get_byte (&line, i + 2) == '\'' &&
+ _dbus_string_get_byte (&line, i + 3) == '\'')
+ {
+ val = '\'';
+ i += 4;
+ }
+ else if (_dbus_string_get_byte (&line, i) == '\'' &&
+ _dbus_string_get_length (&line) >= i + 3 &&
+ _dbus_string_get_byte (&line, i + 2) == '\'')
+ {
+ val = _dbus_string_get_byte (&line, i + 1);
+ i += 3;
+ }
+ else
+ {
+ if (!_dbus_string_parse_int (&line, i, &val, &i))
+ {
+ _dbus_warn ("Failed to parse integer for BYTE_ARRAY\n");
+ goto parse_failed;
+ }
+
+ if (val < 0 || val > 255)
+ {
+ _dbus_warn ("A byte must be in range 0-255 not %ld\n",
+ val);
+ goto parse_failed;
+ }
+ }
+
+ values[len++] = val;
+ if (len == allocated)
+ {
+ allocated *= 2;
+ values = dbus_realloc (values, allocated * sizeof (unsigned char));
+ if (!values)
+ {
+ _dbus_warn ("could not allocate memory for BOOLEAN_ARRAY\n");
+ goto parse_failed;
+ }
+ }
+
+ _dbus_string_skip_blank (&line, i, &i);
+
+ b = _dbus_string_get_byte (&line, i++);
+
+ if (b == '}')
+ break;
+ else if (b != ',')
+ goto parse_failed;
+ }
+
+ if (!_dbus_marshal_int32 (dest, endian, len) ||
+ !_dbus_string_append_len (dest, values, len))
+ {
+ _dbus_warn ("failed to append BYTE_ARRAY\n");
+ goto parse_failed;
+ }
+ dbus_free (values);
+
+ PERFORM_UNALIGN (dest);
+ }
+ else if (_dbus_string_starts_with_c_str (&line,
"BOOLEAN_ARRAY"))
{
SAVE_FOR_UNALIGN (dest, 4);
@@ -949,7 +1008,7 @@ _dbus_message_data_load (DBusString *dest,
values = dbus_new (char *, allocated);
if (!values)
{
- _dbus_warn ("could not allocate memory for DOUBLE_ARRAY\n");
+ _dbus_warn ("could not allocate memory for STRING_ARRAY\n");
goto parse_failed;
}
@@ -1017,6 +1076,38 @@ _dbus_message_data_load (DBusString *dest,
PERFORM_UNALIGN (dest);
}
+ else if (_dbus_string_starts_with_c_str (&line, "BYTE"))
+ {
+ unsigned char the_byte;
+
+ _dbus_string_delete_first_word (&line);
+
+ if (_dbus_string_equal_c_str (&line, "'\\''"))
+ the_byte = '\'';
+ else if (_dbus_string_get_byte (&line, 0) == '\'' &&
+ _dbus_string_get_length (&line) >= 3 &&
+ _dbus_string_get_byte (&line, 2) == '\'')
+ the_byte = _dbus_string_get_byte (&line, 1);
+ else
+ {
+ long val;
+ if (!_dbus_string_parse_int (&line, 0, &val, NULL))
+ {
+ _dbus_warn ("Failed to parse integer for BYTE\n");
+ goto parse_failed;
+ }
+
+ if (val > 255)
+ {
+ _dbus_warn ("A byte must be in range 0-255 not %ld\n",
+ val);
+ goto parse_failed;
+ }
+ the_byte = (unsigned char) val;
+ }
+
+ _dbus_string_append_byte (dest, the_byte);
+ }
else if (_dbus_string_starts_with_c_str (&line,
"BOOLEAN"))
{
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 46c4c406..994e160d 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -103,22 +103,40 @@ struct DBusMessage
DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
long size_counter_delta; /**< Size we incremented the size counter by. */
+
+ dbus_uint32_t changed_stamp;
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
};
+enum {
+ DBUS_MESSAGE_ITER_TYPE_MESSAGE,
+ DBUS_MESSAGE_ITER_TYPE_ARRAY,
+ DBUS_MESSAGE_ITER_TYPE_DICT
+};
+
+typedef struct DBusMessageRealIter DBusMessageRealIter;
+
/**
* @brief Internals of DBusMessageIter
*
* Object representing a position in a message. All fields are internal.
*/
-struct DBusMessageIter
+struct DBusMessageRealIter
{
- int refcount; /**< Reference count */
-
- int pos; /**< Current position in the string */
-
+ DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
DBusMessage *message; /**< Message used */
+ dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
+
+ /* This is an int instead of an enum to get a guaranteed size for the dummy: */
+ int type; /**< type of iter */
+
+ int pos; /**< Current position in the string */
+ int end; /**< position right after the container */
+ int container_type; /**< type of the items in the container (used for arrays) */
+ int container_start; /**< offset of the start of the container */
+ int container_length_pos; /**< offset of the length of the container */
+ int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
};
/**
@@ -861,6 +879,7 @@ dbus_message_new_error_reply (DBusMessage *original_message,
{
DBusMessage *message;
const char *sender;
+ DBusMessageIter iter;
sender = get_string_field (original_message,
FIELD_SENDER, NULL);
@@ -879,7 +898,8 @@ dbus_message_new_error_reply (DBusMessage *original_message,
return NULL;
}
- if (!dbus_message_append_string (message, error_message))
+ dbus_message_append_iter_init (message, &iter);
+ if (!dbus_message_iter_append_string (&iter, error_message))
{
dbus_message_unref (message);
return NULL;
@@ -1034,10 +1054,12 @@ dbus_message_get_service (DBusMessage *message)
/**
* Appends fields to a message given a variable argument
* list. The variable argument list should contain the type
- * of the argument followed by the value to add. Array values
- * are specified by a pointer to the array followed by an int
- * giving the length of the array. The list is terminated
- * with 0.
+ * of the argument followed by the value to add.
+ * Array values are specified by a int typecode followed by a pointer
+ * to the array followed by an int giving the length of the array.
+ * The argument list must be terminated with 0.
+ *
+ * This function doesn't support dicts or non-fundamental arrays.
*
* @param message the message
* @param first_arg_type type of the first argument
@@ -1064,6 +1086,9 @@ dbus_message_append_args (DBusMessage *message,
/**
* This function takes a va_list for use by language bindings
*
+ * @todo: Shouldn't this function clean up the changes to the message
+ * on failures?
+
* @see dbus_message_append_args.
* @param message the message
* @param first_arg_type type of first argument
@@ -1076,122 +1101,110 @@ dbus_message_append_args_valist (DBusMessage *message,
va_list var_args)
{
int type, old_len;
+ DBusMessageIter iter;
old_len = _dbus_string_get_length (&message->body);
type = first_arg_type;
+ dbus_message_append_iter_init (message, &iter);
+
while (type != 0)
{
switch (type)
{
case DBUS_TYPE_NIL:
- if (!dbus_message_append_nil (message))
- goto enomem;
+ if (!dbus_message_iter_append_nil (&iter))
+ goto errorout;
+ break;
case DBUS_TYPE_BOOLEAN:
- if (!dbus_message_append_boolean (message, va_arg (var_args, dbus_bool_t)))
- goto enomem;
+ if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
+ goto errorout;
break;
case DBUS_TYPE_INT32:
- if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
- goto enomem;
+ if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
+ goto errorout;
break;
case DBUS_TYPE_UINT32:
- if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
- goto enomem;
+ if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
+ goto errorout;
break;
case DBUS_TYPE_DOUBLE:
- if (!dbus_message_append_double (message, va_arg (var_args, double)))
- goto enomem;
+ if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
+ goto errorout;
break;
case DBUS_TYPE_STRING:
- if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
- goto enomem;
+ if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
+ goto errorout;
break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
+ case DBUS_TYPE_NAMED:
{
- int len;
+ const char *name;
unsigned char *data;
-
- data = va_arg (var_args, unsigned char *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_boolean_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_INT32_ARRAY:
- {
- int len;
- dbus_int32_t *data;
-
- data = va_arg (var_args, dbus_int32_t *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_int32_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- {
int len;
- dbus_uint32_t *data;
-
- data = va_arg (var_args, dbus_uint32_t *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_uint32_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- int len;
- double *data;
-
- data = va_arg (var_args, double *);
- len = va_arg (var_args, int);
-
- if (!dbus_message_append_double_array (message, data, len))
- goto enomem;
- }
- break;
- case DBUS_TYPE_BYTE_ARRAY:
- {
- int len;
- unsigned char *data;
-
+
+ name = va_arg (var_args, const char *);
data = va_arg (var_args, unsigned char *);
len = va_arg (var_args, int);
- if (!dbus_message_append_byte_array (message, data, len))
- goto enomem;
+ if (!dbus_message_iter_append_named (&iter, name, data, len))
+ goto errorout;
+ break;
}
- break;
- case DBUS_TYPE_STRING_ARRAY:
+ case DBUS_TYPE_ARRAY:
{
- int len;
- const char **data;
-
- data = va_arg (var_args, const char **);
+ void *data;
+ int len, type;
+
+ type = va_arg (var_args, int);
+ data = va_arg (var_args, void *);
len = va_arg (var_args, int);
- if (!dbus_message_append_string_array (message, data, len))
- goto enomem;
+ switch (type)
+ {
+ case DBUS_TYPE_BYTE:
+ if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_INT32:
+ if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_UINT32:
+ if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_DOUBLE:
+ if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_STRING:
+ if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
+ goto errorout;
+ break;
+ case DBUS_TYPE_NIL:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_DICT:
+ _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
+ goto errorout;
+ default:
+ _dbus_warn ("Unknown field type %d\n", type);
+ goto errorout;
+ }
}
break;
+
case DBUS_TYPE_DICT:
- {
- DBusDict *dict;
-
- dict = va_arg (var_args, DBusDict *);
-
- if (!dbus_message_append_dict (message, dict))
- goto enomem;
- break;
- }
+ _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
+ goto errorout;
default:
_dbus_warn ("Unknown field type %d\n", type);
+ goto errorout;
}
type = va_arg (var_args, int);
@@ -1199,360 +1212,82 @@ dbus_message_append_args_valist (DBusMessage *message,
return TRUE;
- enomem:
+ errorout:
return FALSE;
}
-/**
- * Appends a nil value to the message
- *
- * @param message the message
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_nil (DBusMessage *message)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_NIL))
- return FALSE;
- else
- return TRUE;
-}
-
-/**
- * Appends a boolean value to the message
- *
- * @param message the message
- * @param value the boolean value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_boolean (DBusMessage *message,
- dbus_bool_t value)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN))
- return FALSE;
-
- if (!_dbus_string_append_byte (&message->body, (value != FALSE)))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a 32 bit signed integer to the message.
- *
- * @param message the message
- * @param value the integer value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_int32 (DBusMessage *message,
- dbus_int32_t value)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
- return FALSE;
-
- if (!_dbus_marshal_int32 (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
/**
- * Appends a 32 bit unsigned integer to the message.
- *
- * @param message the message
- * @param value the integer value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_uint32 (DBusMessage *message,
- dbus_uint32_t value)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
- return FALSE;
-
- if (!_dbus_marshal_uint32 (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a double value to the message.
- *
- * @param message the message
- * @param value the double value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_double (DBusMessage *message,
- double value)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
- return FALSE;
-
- if (!_dbus_marshal_double (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a UTF-8 string to the message.
+ * 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
+ * stored. The list is terminated with 0.
*
* @param message the message
- * @param value the string
- * @returns #TRUE on success
+ * @param error error to be filled in on failure
+ * @param first_arg_type the first argument type
+ * @param ... location for first argument value, then list of type-location pairs
+ * @returns #FALSE if the error was set
*/
dbus_bool_t
-dbus_message_append_string (DBusMessage *message,
- const char *value)
+dbus_message_get_args (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ ...)
{
- _dbus_assert (!message->locked);
+ dbus_bool_t retval;
+ va_list var_args;
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
- return FALSE;
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
- if (!_dbus_marshal_string (&message->body, message->byte_order, value))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a boolean array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_boolean_array (DBusMessage *message,
- unsigned const char *value,
- int len)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a 32 bit signed integer array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_int32_array (DBusMessage *message,
- const dbus_int32_t *value,
- int len)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_int32_array (&message->body, message->byte_order,
- value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a 32 bit unsigned integer array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_uint32_array (DBusMessage *message,
- const dbus_uint32_t *value,
- int len)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_uint32_array (&message->body, message->byte_order,
- value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a double array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_double_array (DBusMessage *message,
- const double *value,
- int len)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_double_array (&message->body, message->byte_order,
- value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a byte array to the message.
- *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_byte_array (DBusMessage *message,
- unsigned const char *value,
- int len)
-{
- _dbus_assert (!message->locked);
+ va_start (var_args, first_arg_type);
+ retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
+ va_end (var_args);
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
+ return retval;
}
/**
- * Appends a string array to the message.
+ * This function takes a va_list for use by language bindings
*
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_string_array (DBusMessage *message,
- const char **value,
- int len)
-{
- _dbus_assert (!message->locked);
-
- if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
- return FALSE;
-
- if (!_dbus_marshal_string_array (&message->body, message->byte_order,
- (const char **)value, len))
- {
- _dbus_string_shorten (&message->body, 1);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * Appends a dict to the message.
+ * @todo We need to free the argument data when an error occurs.
*
+ * @see dbus_message_get_args
* @param message the message
- * @param dict the dict
- * @returns #TRUE on success
+ * @param error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
*/
dbus_bool_t
-dbus_message_append_dict (DBusMessage *message,
- DBusDict *dict)
+dbus_message_get_args_valist (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
{
- _dbus_assert (!message->locked);
+ DBusMessageIter iter;
- 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;
+ dbus_message_iter_init (message, &iter);
+ return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
}
/**
- * Gets arguments from a message given a variable argument list.
+ * Gets arguments from a message iterator 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
* stored. The list is terminated with 0.
*
- * @param message the message
+ * @param iter the message iterator
* @param error error to be filled in on failure
* @param first_arg_type the first argument type
* @param ... location for first argument value, then list of type-location pairs
* @returns #FALSE if the error was set
*/
dbus_bool_t
-dbus_message_get_args (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- ...)
+dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...)
{
dbus_bool_t retval;
va_list var_args;
@@ -1560,7 +1295,7 @@ dbus_message_get_args (DBusMessage *message,
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
va_start (var_args, first_arg_type);
- retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
+ retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
va_end (var_args);
return retval;
@@ -1579,31 +1314,22 @@ dbus_message_get_args (DBusMessage *message,
* @todo We need to free the argument data when an error occurs.
*
* @see dbus_message_get_args
- * @param message the message
+ * @param iter the message iter
* @param error error to be filled in
* @param first_arg_type type of the first argument
* @param var_args return location for first argument, followed by list of type/location pairs
* @returns #FALSE if error was set
*/
dbus_bool_t
-dbus_message_get_args_valist (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- va_list var_args)
+dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
{
int spec_type, msg_type, i;
- DBusMessageIter *iter;
dbus_bool_t retval;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
-
- iter = dbus_message_get_args_iter (message);
-
- if (iter == NULL)
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- return FALSE;
- }
retval = FALSE;
@@ -1629,6 +1355,15 @@ dbus_message_get_args_valist (DBusMessage *message,
{
case DBUS_TYPE_NIL:
break;
+ case DBUS_TYPE_BYTE:
+ {
+ unsigned char *ptr;
+
+ ptr = va_arg (var_args, unsigned char *);
+
+ *ptr = dbus_message_iter_get_byte (iter);
+ break;
+ }
case DBUS_TYPE_BOOLEAN:
{
dbus_bool_t *ptr;
@@ -1684,117 +1419,109 @@ dbus_message_get_args_valist (DBusMessage *message,
break;
}
- case DBUS_TYPE_BOOLEAN_ARRAY:
+ case DBUS_TYPE_NAMED:
{
- unsigned char **ptr;
+ char **name;
+ unsigned char **data;
int *len;
-
- ptr = va_arg (var_args, unsigned char **);
+
+ name = va_arg (var_args, char **);
+ data = va_arg (var_args, unsigned char **);
len = va_arg (var_args, int *);
- if (!dbus_message_iter_get_boolean_array (iter, ptr, len))
- {
+ *name = dbus_message_iter_get_named (iter, data, len);
+ if (*name == NULL)
+ {
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
+ goto out;
+ }
}
-
- case DBUS_TYPE_INT32_ARRAY:
- {
- dbus_int32_t **ptr;
- int *len;
-
- ptr = va_arg (var_args, dbus_int32_t **);
- len = va_arg (var_args, int *);
-
- if (!dbus_message_iter_get_int32_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
-
- break;
- }
-
- case DBUS_TYPE_UINT32_ARRAY:
+ break;
+ case DBUS_TYPE_ARRAY:
{
- dbus_uint32_t **ptr;
- int *len;
-
- ptr = va_arg (var_args, dbus_uint32_t **);
+ void **data;
+ int *len, type;
+
+ type = va_arg (var_args, int);
+ data = va_arg (var_args, void *);
len = va_arg (var_args, int *);
- if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
+ if (dbus_message_iter_get_array_type (iter) != type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"array of %s\", but "
+ "is actually of type \"array of %s\"\n", i,
+ _dbus_type_to_string (type),
+ _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
+ goto out;
+ }
- break;
- }
-
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- double **ptr;
- int *len;
-
- ptr = va_arg (var_args, double **);
- len = va_arg (var_args, int *);
-
- if (!dbus_message_iter_get_double_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
-
- case DBUS_TYPE_BYTE_ARRAY:
- {
- unsigned char **ptr;
- int *len;
-
- ptr = va_arg (var_args, unsigned char **);
- len = va_arg (var_args, int *);
-
- if (!dbus_message_iter_get_byte_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
- case DBUS_TYPE_STRING_ARRAY:
- {
- char ***ptr;
- int *len;
-
- ptr = va_arg (var_args, char ***);
- len = va_arg (var_args, int *);
-
- if (!dbus_message_iter_get_string_array (iter, ptr, len))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
+ switch (type)
+ {
+ case DBUS_TYPE_BYTE:
+ if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_INT32:
+ if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_UINT32:
+ if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_DOUBLE:
+ if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_STRING:
+ if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ goto out;
+ }
+ break;
+ case DBUS_TYPE_NIL:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_NAMED:
+ case DBUS_TYPE_DICT:
+ _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
+ default:
+ _dbus_warn ("Unknown field type %d\n", type);
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
+ }
}
+ break;
case DBUS_TYPE_DICT:
- {
- DBusDict **dict;
-
- dict = va_arg (var_args, DBusDict **);
-
- if (!dbus_message_iter_get_dict (iter, dict))
- {
- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
- goto out;
- }
- break;
- }
+ _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
+ goto out;
default:
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
_dbus_warn ("Unknown field type %d\n", spec_type);
+ goto out;
}
spec_type = va_arg (var_args, int);
@@ -1811,81 +1538,92 @@ dbus_message_get_args_valist (DBusMessage *message,
retval = TRUE;
out:
- dbus_message_iter_unref (iter);
+
return retval;
}
+
/**
- * Returns a DBusMessageIter representing the arguments of the
+ * Initializes a DBusMessageIter representing the arguments of the
* message passed in.
*
- * @todo IMO the message iter should follow the GtkTextIter pattern,
- * a static object with a "stamp" value used to detect invalid
- * iter uses (uninitialized or after changing the message).
- * ref/unref is kind of annoying to deal with, and slower too.
- * This implies not ref'ing the message from the iter.
- *
- * @todo I'd also name this dbus_message_iter_new() or
- * for the static object dbus_message_iter_init() rather
- * than making it a method on the message
- *
* @param message the message
- * @returns a new iter.
+ * @param _iter pointer to an iterator to initialize
*/
-DBusMessageIter *
-dbus_message_get_args_iter (DBusMessage *message)
+void
+dbus_message_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
{
- DBusMessageIter *iter;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
- iter = dbus_new (DBusMessageIter, 1);
-
- if (iter != NULL)
- {
- dbus_message_ref (message);
+ real->message = message;
+ real->parent_iter = NULL;
+ real->changed_stamp = message->changed_stamp;
- iter->refcount = 1;
- iter->message = message;
- iter->pos = 0;
- }
+ real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
+ real->pos = 0;
+ real->end = _dbus_string_get_length (&message->body);
- return iter;
+ real->container_type = 0;
+ real->container_start = 0;
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
}
-/**
- * Increments the reference count of a DBusMessageIter.
- *
- * @param iter the message iter
- * @see dbus_message_iter_unref
- */
-void
-dbus_message_iter_ref (DBusMessageIter *iter)
+static void
+dbus_message_iter_check (DBusMessageRealIter *iter)
{
- _dbus_assert (iter->refcount > 0);
-
- iter->refcount += 1;
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ _dbus_warn ("dbus iterator check failed: invalid iterator\n");
+ if (iter->pos < 0 || iter->pos > iter->end)
+ _dbus_warn ("dbus iterator check failed: invalid position\n");
}
-/**
- * Decrements the reference count of a DBusMessageIter.
- *
- * @param iter The message iter
- * @see dbus_message_iter_ref
- */
-void
-dbus_message_iter_unref (DBusMessageIter *iter)
+static int
+dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
{
- _dbus_assert (iter->refcount > 0);
-
- iter->refcount -= 1;
-
- if (iter->refcount == 0)
+ const char *data;
+ int pos, len;
+
+ switch (iter->type)
{
- dbus_message_unref (iter->message);
-
- dbus_free (iter);
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ iter->pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ *type = *data;
+ else
+ *type = DBUS_TYPE_INVALID;
+
+ return iter->pos + 1;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ *type = iter->container_type;
+ return iter->pos;
+
+
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ /* Get the length of the string */
+ len = _dbus_demarshal_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->pos, &pos);
+ pos = pos + len + 1;
+ data = _dbus_string_get_const_data_len (&iter->message->body,
+ pos, 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ *type = *data;
+ else
+ *type = DBUS_TYPE_INVALID;
+ return pos + 1;
+ default:
+ _dbus_assert_not_reached ("Invalid iter type");
+ break;
}
+ *type = DBUS_TYPE_INVALID;
+ return iter->pos;
}
+
/**
* Checks if an iterator has any more fields.
*
@@ -1896,39 +1634,54 @@ dbus_message_iter_unref (DBusMessageIter *iter)
dbus_bool_t
dbus_message_iter_has_next (DBusMessageIter *iter)
{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int end_pos;
-
- if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
- iter->message->byte_order,
- iter->pos, &end_pos))
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ if (real->pos >= real->end)
return FALSE;
- if (end_pos >= _dbus_string_get_length (&iter->message->body))
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
+ real->message->byte_order,
+ type, pos, &end_pos))
return FALSE;
+ if (end_pos >= real->end)
+ return FALSE;
+
return TRUE;
}
/**
* Moves the iterator to the next field.
*
- * @param iter The message iter
+ * @param _iter The message iter
* @returns #TRUE if the iterator was moved to the next field
*/
dbus_bool_t
dbus_message_iter_next (DBusMessageIter *iter)
{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int end_pos;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
- iter->message->byte_order,
- iter->pos, &end_pos))
+ if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
+ real->message->byte_order,
+ type, pos, &end_pos))
return FALSE;
- if (end_pos >= _dbus_string_get_length (&iter->message->body))
+ if (end_pos >= real->end)
return FALSE;
- iter->pos = end_pos;
+ real->pos = end_pos;
return TRUE;
}
@@ -1943,19 +1696,54 @@ dbus_message_iter_next (DBusMessageIter *iter)
int
dbus_message_iter_get_arg_type (DBusMessageIter *iter)
{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ if (real->pos >= real->end)
+ return DBUS_TYPE_INVALID;
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ return type;
+}
+
+/**
+ * Returns the element type of the array that the
+ * message iterator points at. Note that you need
+ * to check that the iterator points to an array
+ * prior to using this function.
+ *
+ * @param iter the message iter
+ * @returns the field type
+ */
+int
+dbus_message_iter_get_array_type (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
const char *data;
- if (iter->pos >= _dbus_string_get_length (&iter->message->body))
+ dbus_message_iter_check (real);
+
+ if (real->pos >= real->end)
return DBUS_TYPE_INVALID;
- data = _dbus_string_get_const_data_len (&iter->message->body, iter->pos, 1);
+ pos = dbus_message_iter_get_data_start (real, &type);
- if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
- return *data;
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ return *data;
+
return DBUS_TYPE_INVALID;
}
+
/**
* Returns the string value that an iterator may point to.
* Note that you need to check that the iterator points to
@@ -1968,29 +1756,114 @@ dbus_message_iter_get_arg_type (DBusMessageIter *iter)
char *
dbus_message_iter_get_string (DBusMessageIter *iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_STRING);
+
+ return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ pos, NULL);
+}
+
+/**
+ * Returns the name and data from a named type that an
+ * iterator may point to.Note that you need to check that
+ * the iterator points to a named type before using this
+ * function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @param value return location for data
+ * @param len return location for length of data
+ * @returns the named type name as a string
+ *
+ */
+char *
+dbus_message_iter_get_named (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ char *name;
- return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_NAMED);
+
+ name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ pos, &pos);
+
+ if (name == NULL)
+ return NULL;
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ {
+ dbus_free (name);
+ return NULL;
+ }
+ else
+ return name;
}
/**
+ * Returns the byte value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a byte value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the byte value
+ */
+unsigned char
+dbus_message_iter_get_byte (DBusMessageIter *iter)
+{
+ unsigned char value;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_BYTE);
+
+ value = _dbus_string_get_byte (&real->message->body, pos);
+
+ return value;
+}
+
+
+/**
* Returns the boolean value that an iterator may point to.
* Note that you need to check that the iterator points to
* a boolean value before using this function.
*
* @see dbus_message_iter_get_arg_type
* @param iter the message iter
- * @returns the string
+ * @returns the boolean value
*/
dbus_bool_t
dbus_message_iter_get_boolean (DBusMessageIter *iter)
{
unsigned char value;
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN);
+ _dbus_assert (type == DBUS_TYPE_BOOLEAN);
- value = _dbus_string_get_byte (&iter->message->body, iter->pos + 1);
+ value = _dbus_string_get_byte (&real->message->body, pos);
return value;
}
@@ -2004,13 +1877,20 @@ dbus_message_iter_get_boolean (DBusMessageIter *iter)
* @param iter the message iter
* @returns the integer
*/
-int
+dbus_int32_t
dbus_message_iter_get_int32 (DBusMessageIter *iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_INT32);
- return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
+ pos, NULL);
}
/**
@@ -2022,13 +1902,20 @@ dbus_message_iter_get_int32 (DBusMessageIter *iter)
* @param iter the message iter
* @returns the integer
*/
-int
+dbus_uint32_t
dbus_message_iter_get_uint32 (DBusMessageIter *iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
- return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ _dbus_assert (type == DBUS_TYPE_UINT32);
+
+ return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos, NULL);
}
/**
@@ -2043,10 +1930,160 @@ dbus_message_iter_get_uint32 (DBusMessageIter *iter)
double
dbus_message_iter_get_double (DBusMessageIter *iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_DOUBLE);
- return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL);
+ return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
+ pos, NULL);
+}
+
+/**
+ * Initializes an iterator for the array that the iterator
+ * may point to. Note that you need to check that the iterator
+ * points to an array prior to using this function.
+ *
+ * The array element type is returned in array_type, and the array
+ * iterator can only be used to get that type of data.
+ *
+ * @param iter the iterator
+ * @param array_iter pointer to an iterator to initialize
+ * @param array_type gets set to the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int *array_type)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int type, pos, len_pos, len;
+ int _array_type;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+ if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
+ _array_type = *data;
+ else
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t));
+ len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos + 1, &pos);
+
+ array_real->parent_iter = real;
+ array_real->message = real->message;
+ array_real->changed_stamp = real->message->changed_stamp;
+
+ array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
+ array_real->pos = pos;
+ array_real->end = pos + len;
+
+ array_real->container_type = _array_type;
+ array_real->container_start = pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
+
+ if (array_type != NULL)
+ *array_type = _array_type;
+
+ return TRUE;
+}
+
+
+/**
+ * Initializes an iterator for 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_iter pointer to an iterator to initialize
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int type, pos, len_pos, len;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_DICT);
+
+ len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
+ len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+ pos, &pos);
+
+ dict_real->parent_iter = real;
+ dict_real->message = real->message;
+ dict_real->changed_stamp = real->message->changed_stamp;
+
+ dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
+ dict_real->pos = pos;
+ dict_real->end = pos + len;
+
+ dict_real->container_type = 0;
+ dict_real->container_start = pos;
+ dict_real->container_length_pos = len_pos;
+ dict_real->wrote_dict_key = 0;
+
+ return TRUE;
+}
+
+/**
+ * Returns the byte array that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a byte array prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for array values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_byte_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_BYTE);
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
+ return FALSE;
+ else
+ return TRUE;
}
/**
@@ -2064,10 +2101,24 @@ dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
unsigned char **value,
int *len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
+
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
- if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_BOOLEAN);
+
+ if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2088,10 +2139,24 @@ dbus_message_iter_get_int32_array (DBusMessageIter *iter,
dbus_int32_t **value,
int *len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!_dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_INT32);
+
+ if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2112,10 +2177,24 @@ dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
dbus_uint32_t **value,
int *len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!_dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_UINT32);
+
+ if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2136,34 +2215,24 @@ dbus_message_iter_get_double_array (DBusMessageIter *iter,
double **value,
int *len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!_dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
- return FALSE;
- else
- return TRUE;
-}
+ dbus_message_iter_check (real);
-/**
- * Returns the byte array that the iterator may point to.
- * Note that you need to check that the iterator points
- * to a byte array prior to using this function.
- *
- * @param iter the iterator
- * @param value return location for array values
- * @param len return location for length of byte array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_iter_get_byte_array (DBusMessageIter *iter,
- unsigned char **value,
- int *len)
-{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
- if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ _dbus_assert (*data == DBUS_TYPE_DOUBLE);
+
+ if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
return FALSE;
else
return TRUE;
@@ -2189,35 +2258,756 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter,
char ***value,
int *len)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ int type, pos;
+ const char *data;
- if (!_dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, value, len))
+ dbus_message_iter_check (real);
+
+ pos = dbus_message_iter_get_data_start (real, &type);
+
+ _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+ data = _dbus_string_get_const_data_len (&real->message->body,
+ pos,
+ 1);
+
+ _dbus_assert (*data == DBUS_TYPE_STRING);
+
+ if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
+ pos + 1, NULL, value, len))
return FALSE;
else
return TRUE;
}
/**
- * 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.
+ * Returns the key name fot the dict entry that an iterator
+ * may point to. Note that you need to check that the iterator
+ * points to a dict entry before using this function.
*
- * @param iter the iterator
- * @param dict return location for dict
+ * @see dbus_message_iter_init_dict_iterator
+ * @param iter the message iter
+ * @returns the key name
+ */
+char *
+dbus_message_iter_get_dict_key (DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_check (real);
+
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+ real->pos, NULL);
+}
+
+/**
+ * Initializes a DBusMessageIter pointing to the end of the
+ * message. This iterator can be used to append data to the
+ * message.
+ *
+ * @param message the message
+ * @param _iter pointer to an iterator to initialize
+ */
+void
+dbus_message_append_iter_init (DBusMessage *message,
+ DBusMessageIter *iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ real->message = message;
+ real->parent_iter = NULL;
+ real->changed_stamp = message->changed_stamp;
+
+ real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
+ real->end = _dbus_string_get_length (&real->message->body);
+ real->pos = real->end;
+
+ real->container_type = 0;
+ real->container_length_pos = 0;
+ real->wrote_dict_key = 0;
+}
+
+static void
+dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+ _dbus_assert (!iter->message->locked);
+
+ if (iter->changed_stamp != iter->message->changed_stamp)
+ _dbus_warn ("dbus iterator check failed: invalid iterator");
+
+ if (iter->pos != iter->end)
+ _dbus_warn ("dbus iterator check failed: can only append at end of message");
+
+ if (iter->pos != _dbus_string_get_length (&iter->message->body))
+ _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
+}
+
+static dbus_bool_t
+dbus_message_iter_append_type (DBusMessageRealIter *iter,
+ int type)
+{
+ switch (iter->type)
+ {
+ case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ return FALSE;
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_ARRAY:
+ if (type != iter->container_type)
+ {
+ _dbus_warn ("Appended element of wrong type for array\n");
+ return FALSE;
+ }
+ break;
+
+ case DBUS_MESSAGE_ITER_TYPE_DICT:
+ if (!iter->wrote_dict_key)
+ {
+ _dbus_warn ("Appending dict data before key name\n");
+ return FALSE;
+ }
+
+ if (!_dbus_string_append_byte (&iter->message->body, type))
+ return FALSE;
+
+ break;
+
+ default:
+ _dbus_assert_not_reached ("Invalid iter type");
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
+{
+ iter->changed_stamp = iter->message->changed_stamp;
+
+ /* Set new end of iter */
+ iter->end = _dbus_string_get_length (&iter->message->body);
+ iter->pos = iter->end;
+
+ /* Set container length */
+ if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
+ iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
+ _dbus_marshal_set_uint32 (&iter->message->body,
+ iter->message->byte_order,
+ iter->container_length_pos,
+ iter->end - iter->container_start);
+
+ if (iter->parent_iter)
+ dbus_message_iter_update_after_change (iter->parent_iter);
+}
+
+static void
+dbus_message_iter_append_done (DBusMessageRealIter *iter)
+{
+ iter->message->changed_stamp++;
+ dbus_message_iter_update_after_change (iter);
+ iter->wrote_dict_key = FALSE;
+}
+
+/**
+ * Appends a nil value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
* @returns #TRUE on success
*/
dbus_bool_t
-dbus_message_iter_get_dict (DBusMessageIter *iter,
- DBusDict **dict)
+dbus_message_iter_append_nil (DBusMessageIter *iter)
{
- _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT);
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
- if (!_dbus_demarshal_dict (&iter->message->body, iter->message->byte_order,
- iter->pos + 1, NULL, dict))
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
return FALSE;
- else
- return TRUE;
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a boolean value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+ dbus_bool_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the byte value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte (DBusMessageIter *iter,
+ unsigned char value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a 32 bit signed integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32 (DBusMessageIter *iter,
+ dbus_int32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
+ return FALSE;
+
+ if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+ dbus_uint32_t value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
+ return FALSE;
+
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a double value to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the double value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double (DBusMessageIter *iter,
+ double value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
+ return FALSE;
+
+ if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a UTF-8 string to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a named type data chunk to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param name the name of the type
+ * @parame
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_named (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
+ return FALSE;
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, data))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a dict key name to the message. The iterator used
+ * must point to a dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+ const char *value)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+ _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
+
+ if (real->wrote_dict_key)
+ {
+ _dbus_warn ("Appendinging multiple dict key names\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+ {
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+ real->wrote_dict_key = TRUE;
+
+ return TRUE;
+}
+
+/**
+ * Appends an array to the message and initializes an iterator that
+ * can be used to append to the array.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param array_iter pointer to an iter that will be initialized
+ * @param element_type the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_array (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int element_type)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
+ int len_pos;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, element_type))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ array_real->parent_iter = real;
+ array_real->message = real->message;
+ array_real->changed_stamp = real->message->changed_stamp;
+
+ array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
+ array_real->pos = _dbus_string_get_length (&real->message->body);
+ array_real->end = array_real->end;
+
+ array_real->container_type = element_type;
+ array_real->container_start = array_real->pos;
+ array_real->container_length_pos = len_pos;
+ array_real->wrote_dict_key = 0;
+
+ dbus_message_iter_append_done (array_real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a dict to the message and initializes an iterator that
+ * can be used to append to the dict.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param array_iter pointer to an iter that will be initialized
+ * @param element_type the type of the array elements
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_dict (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+ DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+ int len_pos;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
+ return FALSE;
+
+ len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+ /* Empty length for now, backfill later */
+ if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dict_real->parent_iter = real;
+ dict_real->message = real->message;
+ dict_real->changed_stamp = real->message->changed_stamp;
+
+ dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
+ dict_real->pos = _dbus_string_get_length (&real->message->body);
+ dict_real->end = dict_real->end;
+
+ dict_real->container_type = 0;
+ dict_real->container_start = dict_real->pos;
+ dict_real->container_length_pos = len_pos;
+ dict_real->wrote_dict_key = 0;
+
+ dbus_message_iter_append_done (dict_real);
+
+ return TRUE;
+}
+
+
+/**
+ * Appends a boolean array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BOOLEAN))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit signed integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter *iter,
+ const dbus_int32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_INT32))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a 32 bit unsigned integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
+ const dbus_uint32_t *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_UINT32))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a double array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_double_array (DBusMessageIter *iter,
+ const double *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_DOUBLE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a byte array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_byte_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
+}
+
+/**
+ * Appends a string array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_string_array (DBusMessageIter *iter,
+ const char **value,
+ int len)
+{
+ DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+ dbus_message_iter_append_check (real);
+
+ if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
+ {
+ _dbus_string_set_length (&real->message->body, real->pos);
+ return FALSE;
+ }
+
+ dbus_message_iter_append_done (real);
+
+ return TRUE;
}
/**
@@ -2621,6 +3411,7 @@ decode_header_data (const DBusString *data,
const char *field;
int pos, new_pos;
int i;
+ int type;
if (header_len < 16)
return FALSE;
@@ -2723,7 +3514,13 @@ decode_header_data (const DBusString *data,
field[0], field[1], field[2], field[3], pos);
}
- if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
+ if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
+ {
+ _dbus_verbose ("Failed to validate type of named header field\n");
+ return FALSE;
+ }
+
+ if (!_dbus_marshal_validate_arg (data, byte_order, type, pos, &new_pos))
{
_dbus_verbose ("Failed to validate argument to named header field\n");
return FALSE;
@@ -2891,13 +3688,24 @@ _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
next_arg = header_len;
while (next_arg < (header_len + body_len))
{
+ int type;
int prev = next_arg;
+ if (!_dbus_marshal_validate_type (&loader->data, next_arg,
+ &type, &next_arg))
+ {
+ _dbus_verbose ("invalid typecode at offset %d\n", prev);
+ loader->corrupted = TRUE;
+ return TRUE;
+ }
+
if (!_dbus_marshal_validate_arg (&loader->data,
byte_order,
+ type,
next_arg,
&next_arg))
{
+ _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
loader->corrupted = TRUE;
return TRUE;
}
@@ -3078,66 +3886,245 @@ _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
static void
message_iter_test (DBusMessage *message)
{
- DBusMessageIter *iter;
+ DBusMessageIter iter, dict, array;
char *str;
- iter = dbus_message_get_args_iter (message);
+ dbus_message_iter_init (message, &iter);
/* String tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
_dbus_assert_not_reached ("Argument type isn't string");
- str = dbus_message_iter_get_string (iter);
+ str = dbus_message_iter_get_string (&iter);
if (strcmp (str, "Test string") != 0)
_dbus_assert_not_reached ("Strings differ");
dbus_free (str);
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
/* Signed integer tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
_dbus_assert_not_reached ("Argument type isn't int32");
- if (dbus_message_iter_get_int32 (iter) != -0x12345678)
+ if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
_dbus_assert_not_reached ("Signed integers differ");
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of fields");
/* Unsigned integer tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
_dbus_assert_not_reached ("Argument type isn't int32");
- if (dbus_message_iter_get_uint32 (iter) != 0xedd1e)
+ if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
_dbus_assert_not_reached ("Unsigned integers differ");
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
_dbus_assert_not_reached ("Reached end of arguments");
/* Double tests */
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
_dbus_assert_not_reached ("Argument type isn't double");
- if (dbus_message_iter_get_double (iter) != 3.14159)
+ if (dbus_message_iter_get_double (&iter) != 3.14159)
_dbus_assert_not_reached ("Doubles differ");
- if (dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
+ _dbus_assert_not_reached ("Argument type not an array");
+
+ if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Array type not uint32");
+
+
+ if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
+ _dbus_assert_not_reached ("Array init failed");
+
+ if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Argument type isn't int32");
+
+ if (dbus_message_iter_get_uint32 (&array) != 0x12345678)
+ _dbus_assert_not_reached ("Unsigned integers differ");
+
+ if (!dbus_message_iter_next (&array))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("Argument type isn't int32");
+
+ if (dbus_message_iter_get_uint32 (&array) != 0x23456781)
+ _dbus_assert_not_reached ("Unsigned integers differ");
+
+ if (dbus_message_iter_next (&array))
_dbus_assert_not_reached ("Didn't reach end of arguments");
- dbus_message_iter_unref (iter);
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
+ _dbus_assert_not_reached ("not dict type");
+
+ if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
+ _dbus_assert_not_reached ("dict iter failed");
+
+ str = dbus_message_iter_get_dict_key (&dict);
+ if (str == NULL || strcmp (str, "test") != 0)
+ _dbus_assert_not_reached ("wrong dict key");
+ dbus_free (str);
+
+ if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong dict entry type");
+
+ if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
+ _dbus_assert_not_reached ("wrong dict entry value");
+
+ if (dbus_message_iter_next (&dict))
+ _dbus_assert_not_reached ("Didn't reach end of dict");
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong type after dict");
+
+ if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
+ _dbus_assert_not_reached ("wrong value after dict");
+
+ if (dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Didn't reach end of arguments");
}
+
+static dbus_bool_t
+check_message_handling_type (DBusMessageIter *iter,
+ int type)
+{
+ DBusMessageIter child_iter;
+
+ switch (type)
+ {
+ case DBUS_TYPE_NIL:
+ break;
+ case DBUS_TYPE_BYTE:
+ dbus_message_iter_get_byte (iter);
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_boolean (iter);
+ break;
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_int32 (iter);
+ break;
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_uint32 (iter);
+ break;
+ case DBUS_TYPE_DOUBLE:
+ dbus_message_iter_get_double (iter);
+ break;
+ case DBUS_TYPE_STRING:
+ {
+ char *str;
+ str = dbus_message_iter_get_string (iter);
+ if (str == NULL)
+ {
+ _dbus_warn ("NULL string int message\n");
+ return FALSE;
+ }
+ dbus_free (str);
+ }
+ break;
+ case DBUS_TYPE_NAMED:
+ {
+ char *name;
+ unsigned char *data;
+ int len;
+
+ name = dbus_message_iter_get_named (iter, &data, &len);
+ if (name == NULL)
+ {
+ _dbus_warn ("error reading name from named type\n");
+ return FALSE;
+ }
+ dbus_free (data);
+ dbus_free (name);
+ }
+ break;
+ case DBUS_TYPE_ARRAY:
+ {
+ int array_type;
+
+ if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
+ {
+ _dbus_warn ("Failed to init array iterator\n");
+ return FALSE;
+ }
+
+ while (dbus_message_iter_has_next (&child_iter))
+ {
+ if (!check_message_handling_type (&child_iter, array_type))
+ {
+ _dbus_warn ("error in array element\n");
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_next (&child_iter))
+ break;
+ }
+ }
+ break;
+ case DBUS_TYPE_DICT:
+ {
+ int entry_type;
+ char *key;
+
+ if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
+ {
+ _dbus_warn ("Failed to init dict iterator\n");
+ return FALSE;
+ }
+
+ while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
+ {
+ key = dbus_message_iter_get_dict_key (&child_iter);
+ if (key == NULL)
+ {
+ _dbus_warn ("error reading dict key\n");
+ return FALSE;
+ }
+ dbus_free (key);
+
+ if (!check_message_handling_type (&child_iter, entry_type))
+ {
+ _dbus_warn ("error in dict value\n");
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_next (&child_iter))
+ break;
+ }
+ }
+ break;
+
+ default:
+ _dbus_warn ("unknown type %d\n", type);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+
static dbus_bool_t
check_message_handling (DBusMessage *message)
{
- DBusMessageIter *iter;
+ DBusMessageIter iter;
int type;
dbus_bool_t retval;
dbus_int32_t client_serial;
retval = FALSE;
- iter = NULL;
client_serial = dbus_message_get_serial (message);
@@ -3155,109 +4142,20 @@ check_message_handling (DBusMessage *message)
* 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_message_iter_init (message, &iter);
+ while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
{
- switch (type)
- {
- case DBUS_TYPE_NIL:
- break;
- case DBUS_TYPE_INT32:
- dbus_message_iter_get_int32 (iter);
- break;
- case DBUS_TYPE_UINT32:
- dbus_message_iter_get_uint32 (iter);
- break;
- case DBUS_TYPE_DOUBLE:
- dbus_message_iter_get_double (iter);
- break;
- case DBUS_TYPE_STRING:
- {
- char *str;
- str = dbus_message_iter_get_string (iter);
- dbus_free (str);
- }
- break;
- case DBUS_TYPE_BOOLEAN_ARRAY:
- {
- unsigned char *values;
- int len;
-
- if (!dbus_message_iter_get_boolean_array (iter, &values, &len))
- return FALSE;
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_INT32_ARRAY:
- {
- dbus_int32_t *values;
- int len;
-
- if (!dbus_message_iter_get_int32_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_UINT32_ARRAY:
- {
- dbus_uint32_t *values;
- int len;
-
- if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_DOUBLE_ARRAY:
- {
- double *values;
- int len;
-
- if (!dbus_message_iter_get_double_array (iter, &values, &len))
- return FALSE;
-
- dbus_free (values);
- }
- break;
- case DBUS_TYPE_STRING_ARRAY:
- {
- char **values;
- int len;
-
- if (!dbus_message_iter_get_string_array (iter, &values, &len))
- return FALSE;
-
- 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;
+ if (!check_message_handling_type (&iter, type))
+ goto failed;
- default:
- break;
- }
-
- if (!dbus_message_iter_next (iter))
+ if (!dbus_message_iter_next (&iter))
break;
}
-
+
retval = TRUE;
failed:
- if (iter)
- dbus_message_iter_unref (iter);
-
return retval;
}
@@ -3408,6 +4306,7 @@ dbus_internal_do_not_use_load_message_file (const DBusString *filename,
{
DBusError error;
+ _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
dbus_error_init (&error);
if (!_dbus_file_get_contents (data, filename, &error))
{
@@ -3733,14 +4632,25 @@ verify_test_message (DBusMessage *message)
char *our_str;
double our_double;
dbus_bool_t our_bool;
-
- if (!dbus_message_get_args (message, NULL,
- DBUS_TYPE_INT32, &our_int,
- DBUS_TYPE_STRING, &our_str,
- DBUS_TYPE_DOUBLE, &our_double,
- DBUS_TYPE_BOOLEAN, &our_bool,
- 0))
- _dbus_assert_not_reached ("Could not get arguments");
+ dbus_int32_t *our_int_array;
+ int our_int_array_len;
+ DBusMessageIter iter, dict;
+ DBusError error;
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&error);
+ if (!dbus_message_iter_get_args (&iter, &error,
+ DBUS_TYPE_INT32, &our_int,
+ DBUS_TYPE_STRING, &our_str,
+ DBUS_TYPE_DOUBLE, &our_double,
+ DBUS_TYPE_BOOLEAN, &our_bool,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &our_int_array, &our_int_array_len,
+ 0))
+ {
+ _dbus_verbose ("error: %s - %s\n", error.name, (error.message != NULL)?error.message: "no message");
+ _dbus_assert_not_reached ("Could not get arguments");
+ }
if (our_int != -0x12345678)
_dbus_assert_not_reached ("integers differ!");
@@ -3750,11 +4660,56 @@ verify_test_message (DBusMessage *message)
if (strcmp (our_str, "Test string") != 0)
_dbus_assert_not_reached ("strings differ!");
+ dbus_free (our_str);
if (!our_bool)
_dbus_assert_not_reached ("booleans differ");
-
+
+ if (our_int_array_len != 4 ||
+ our_int_array[0] != 0x12345678 ||
+ our_int_array[1] != 0x23456781 ||
+ our_int_array[2] != 0x34567812 ||
+ our_int_array[3] != 0x45678123)
+ _dbus_assert_not_reached ("array differ");
+ dbus_free (our_int_array);
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
+ _dbus_assert_not_reached ("not dict type");
+
+ if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
+ _dbus_assert_not_reached ("dict iter failed");
+
+ our_str = dbus_message_iter_get_dict_key (&dict);
+ if (our_str == NULL || strcmp (our_str, "test") != 0)
+ _dbus_assert_not_reached ("wrong dict key");
dbus_free (our_str);
+
+ if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
+ {
+ _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
+ _dbus_assert_not_reached ("wrong dict entry type");
+ }
+
+ if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
+ _dbus_assert_not_reached ("wrong dict entry value");
+
+ if (dbus_message_iter_next (&dict))
+ _dbus_assert_not_reached ("Didn't reach end of dict");
+
+ if (!dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Reached end of arguments");
+
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
+ _dbus_assert_not_reached ("wrong type after dict");
+
+ if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
+ _dbus_assert_not_reached ("wrong value after dict");
+
+ if (dbus_message_iter_next (&iter))
+ _dbus_assert_not_reached ("Didn't reach end of arguments");
}
/**
@@ -3768,12 +4723,17 @@ _dbus_message_test (const char *test_data_dir)
{
DBusMessage *message;
DBusMessageLoader *loader;
+ DBusMessageIter iter, child_iter;
int i;
const char *data;
DBusMessage *copy;
const char *name1;
const char *name2;
-
+ const dbus_uint32_t our_int32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
+
+
+ _dbus_assert (sizeof (DBusMessageRealIter) == sizeof (DBusMessageIter));
+
/* Test the vararg functions */
message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
_dbus_message_set_serial (message, 1);
@@ -3782,7 +4742,15 @@ _dbus_message_test (const char *test_data_dir)
DBUS_TYPE_STRING, "Test string",
DBUS_TYPE_DOUBLE, 3.14159,
DBUS_TYPE_BOOLEAN, TRUE,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_int32_array, 4,
0);
+
+ dbus_message_append_iter_init (message, &iter);
+ dbus_message_iter_append_dict (&iter, &child_iter);
+ dbus_message_iter_append_dict_key (&child_iter, "test");
+ dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
+ dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
+
_dbus_verbose_bytes_of_string (&message->header, 0,
_dbus_string_get_length (&message->header));
_dbus_verbose_bytes_of_string (&message->body, 0,
@@ -3816,11 +4784,21 @@ _dbus_message_test (const char *test_data_dir)
_dbus_message_set_serial (message, 1);
dbus_message_set_reply_serial (message, 0x12345678);
- dbus_message_append_string (message, "Test string");
- dbus_message_append_int32 (message, -0x12345678);
- dbus_message_append_uint32 (message, 0xedd1e);
- dbus_message_append_double (message, 3.14159);
+ dbus_message_append_iter_init (message, &iter);
+ dbus_message_iter_append_string (&iter, "Test string");
+ dbus_message_iter_append_int32 (&iter, -0x12345678);
+ dbus_message_iter_append_uint32 (&iter, 0xedd1e);
+ dbus_message_iter_append_double (&iter, 3.14159);
+ dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_UINT32);
+ dbus_message_iter_append_uint32 (&child_iter, 0x12345678);
+ dbus_message_iter_append_uint32 (&child_iter, 0x23456781);
+
+ dbus_message_iter_append_dict (&iter, &child_iter);
+ dbus_message_iter_append_dict_key (&child_iter, "test");
+ dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
+ dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
+
message_iter_test (message);
/* Message loader test */
diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h
index 47337863..6c82cf07 100644
--- a/dbus/dbus-message.h
+++ b/dbus/dbus-message.h
@@ -28,7 +28,6 @@
#define DBUS_MESSAGE_H
#include <dbus/dbus-macros.h>
-#include <dbus/dbus-dict.h>
#include <dbus/dbus-types.h>
#include <stdarg.h>
@@ -37,6 +36,21 @@ DBUS_BEGIN_DECLS;
typedef struct DBusMessage DBusMessage;
typedef struct DBusMessageIter DBusMessageIter;
+struct DBusMessageIter
+{
+ void *dummy1;
+ void *dummy2;
+ dbus_uint32_t dummy3;
+ int dummy4;
+ int dummy5;
+ int dummy6;
+ int dummy7;
+ int dummy8;
+ int dummy9;
+ int dummy10;
+};
+
+
DBusMessage* dbus_message_new (const char *service,
const char *name);
DBusMessage* dbus_message_new_reply (DBusMessage *original_message);
@@ -68,85 +82,119 @@ dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message,
dbus_int32_t dbus_message_get_reply_serial (DBusMessage *message);
-dbus_bool_t dbus_message_append_args (DBusMessage *message,
- int first_arg_type,
+dbus_bool_t dbus_message_append_args (DBusMessage *message,
+ int first_arg_type,
+ ...);
+dbus_bool_t dbus_message_append_args_valist (DBusMessage *message,
+ int first_arg_type,
+ va_list var_args);
+dbus_bool_t dbus_message_get_args (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
...);
-dbus_bool_t dbus_message_append_args_valist (DBusMessage *message,
- int first_arg_type,
- va_list var_args);
-dbus_bool_t dbus_message_append_nil (DBusMessage *message);
-dbus_bool_t dbus_message_append_boolean (DBusMessage *message,
- dbus_bool_t value);
-dbus_bool_t dbus_message_append_int32 (DBusMessage *message,
- dbus_int32_t value);
-dbus_bool_t dbus_message_append_uint32 (DBusMessage *message,
- dbus_uint32_t value);
-dbus_bool_t dbus_message_append_double (DBusMessage *message,
- double value);
-dbus_bool_t dbus_message_append_string (DBusMessage *message,
- const char *value);
-dbus_bool_t dbus_message_append_boolean_array (DBusMessage *message,
- unsigned const char *value,
- int len);
-dbus_bool_t dbus_message_append_int32_array (DBusMessage *message,
- const dbus_int32_t *value,
- int len);
-dbus_bool_t dbus_message_append_uint32_array (DBusMessage *message,
- const dbus_uint32_t *value,
- int len);
-dbus_bool_t dbus_message_append_double_array (DBusMessage *message,
- const double *value,
- int len);
-dbus_bool_t dbus_message_append_byte_array (DBusMessage *message,
- unsigned const char *value,
- int len);
-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);
-dbus_bool_t dbus_message_get_args (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- ...);
-dbus_bool_t dbus_message_get_args_valist (DBusMessage *message,
- DBusError *error,
- int first_arg_type,
- va_list var_args);
-
-
-void dbus_message_iter_ref (DBusMessageIter *iter);
-void dbus_message_iter_unref (DBusMessageIter *iter);
-dbus_bool_t dbus_message_iter_has_next (DBusMessageIter *iter);
-dbus_bool_t dbus_message_iter_next (DBusMessageIter *iter);
-int dbus_message_iter_get_arg_type (DBusMessageIter *iter);
-dbus_bool_t dbus_message_iter_get_boolean (DBusMessageIter *iter);
-int dbus_message_iter_get_int32 (DBusMessageIter *iter);
-int dbus_message_iter_get_uint32 (DBusMessageIter *iter);
-double dbus_message_iter_get_double (DBusMessageIter *iter);
-char * dbus_message_iter_get_string (DBusMessageIter *iter);
-dbus_bool_t dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
+dbus_bool_t dbus_message_get_args_valist (DBusMessage *message,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args);
+dbus_bool_t dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...);
+dbus_bool_t dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args);
+
+
+
+void dbus_message_iter_init (DBusMessage *message,
+ DBusMessageIter *iter);
+dbus_bool_t dbus_message_iter_has_next (DBusMessageIter *iter);
+dbus_bool_t dbus_message_iter_next (DBusMessageIter *iter);
+int dbus_message_iter_get_arg_type (DBusMessageIter *iter);
+int dbus_message_iter_get_array_type (DBusMessageIter *iter);
+unsigned char dbus_message_iter_get_byte (DBusMessageIter *iter);
+dbus_bool_t dbus_message_iter_get_boolean (DBusMessageIter *iter);
+dbus_int32_t dbus_message_iter_get_int32 (DBusMessageIter *iter);
+dbus_uint32_t dbus_message_iter_get_uint32 (DBusMessageIter *iter);
+double dbus_message_iter_get_double (DBusMessageIter *iter);
+char * dbus_message_iter_get_string (DBusMessageIter *iter);
+char * dbus_message_iter_get_dict_key (DBusMessageIter *iter);
+char * dbus_message_iter_get_named (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len);
+
+dbus_bool_t dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int *array_type);
+dbus_bool_t dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter);
+dbus_bool_t dbus_message_iter_get_byte_array (DBusMessageIter *iter,
+ unsigned char **value,
+ int *len);
+dbus_bool_t dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
unsigned char **value,
int *len);
-dbus_bool_t dbus_message_iter_get_int32_array (DBusMessageIter *iter,
+dbus_bool_t dbus_message_iter_get_int32_array (DBusMessageIter *iter,
dbus_int32_t **value,
int *len);
-dbus_bool_t dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
+dbus_bool_t dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
dbus_uint32_t **value,
int *len);
-dbus_bool_t dbus_message_iter_get_double_array (DBusMessageIter *iter,
+dbus_bool_t dbus_message_iter_get_double_array (DBusMessageIter *iter,
double **value,
int *len);
-dbus_bool_t dbus_message_iter_get_byte_array (DBusMessageIter *iter,
- unsigned char **value,
- int *len);
-dbus_bool_t dbus_message_iter_get_string_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);
+
+
+void dbus_message_append_iter_init (DBusMessage *message,
+ DBusMessageIter *iter);
+dbus_bool_t dbus_message_iter_append_nil (DBusMessageIter *iter);
+dbus_bool_t dbus_message_iter_append_boolean (DBusMessageIter *iter,
+ dbus_bool_t value);
+dbus_bool_t dbus_message_iter_append_byte (DBusMessageIter *iter,
+ unsigned char value);
+dbus_bool_t dbus_message_iter_append_int32 (DBusMessageIter *iter,
+ dbus_int32_t value);
+dbus_bool_t dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+ dbus_uint32_t value);
+dbus_bool_t dbus_message_iter_append_double (DBusMessageIter *iter,
+ double value);
+dbus_bool_t dbus_message_iter_append_string (DBusMessageIter *iter,
+ const char *value);
+dbus_bool_t dbus_message_iter_append_named (DBusMessageIter *iter,
+ const char *name,
+ const unsigned char *data,
+ int len);
+dbus_bool_t dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+ const char *value);
+dbus_bool_t dbus_message_iter_append_array (DBusMessageIter *iter,
+ DBusMessageIter *array_iter,
+ int element_type);
+dbus_bool_t dbus_message_iter_append_dict (DBusMessageIter *iter,
+ DBusMessageIter *dict_iter);
+
+/* Helpers for normal types: */
+dbus_bool_t dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len);
+dbus_bool_t dbus_message_iter_append_int32_array (DBusMessageIter *iter,
+ const dbus_int32_t *value,
+ int len);
+dbus_bool_t dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
+ const dbus_uint32_t *value,
+ int len);
+dbus_bool_t dbus_message_iter_append_double_array (DBusMessageIter *iter,
+ const double *value,
+ int len);
+dbus_bool_t dbus_message_iter_append_byte_array (DBusMessageIter *iter,
+ unsigned const char *value,
+ int len);
+dbus_bool_t dbus_message_iter_append_string_array (DBusMessageIter *iter,
+ const char **value,
+ int len);
diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h
index c7eb737f..651969c4 100644
--- a/dbus/dbus-protocol.h
+++ b/dbus/dbus-protocol.h
@@ -42,19 +42,18 @@ extern "C" {
/* Data types */
#define DBUS_TYPE_INVALID 0
#define DBUS_TYPE_NIL 1
-#define DBUS_TYPE_BOOLEAN 2
-#define DBUS_TYPE_INT32 3
-#define DBUS_TYPE_UINT32 4
-#define DBUS_TYPE_DOUBLE 5
-#define DBUS_TYPE_STRING 6
-#define DBUS_TYPE_BOOLEAN_ARRAY 7
-#define DBUS_TYPE_INT32_ARRAY 8
-#define DBUS_TYPE_UINT32_ARRAY 9
-#define DBUS_TYPE_DOUBLE_ARRAY 10
-#define DBUS_TYPE_BYTE_ARRAY 11
-#define DBUS_TYPE_STRING_ARRAY 12
-#define DBUS_TYPE_DICT 13
-
+#define DBUS_TYPE_BYTE 2
+#define DBUS_TYPE_BOOLEAN 3
+#define DBUS_TYPE_INT32 4
+#define DBUS_TYPE_UINT32 5
+#define DBUS_TYPE_DOUBLE 6
+#define DBUS_TYPE_STRING 7
+#define DBUS_TYPE_NAMED 8
+#define DBUS_TYPE_ARRAY 9
+#define DBUS_TYPE_DICT 10
+
+#define DBUS_TYPE_LAST DBUS_TYPE_DICT
+
/* Header flags */
#define DBUS_HEADER_FLAG_ERROR 0x1
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index b55cc892..b39b3a0d 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -472,10 +472,6 @@ _dbus_string_get_data_len (DBusString *str,
/**
* const version of _dbus_string_get_data_len().
*
- * @todo should return the const char* instead of using an out param;
- * the temporary variable encourages a bug where you use const data
- * after modifying the string and possibly causing a realloc.
- *
* @param str the string
* @param start byte offset to return
* @param len length of segment to return
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index df921b17..bb471876 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -39,6 +39,7 @@
#include <sys/un.h>
#include <pwd.h>
#include <time.h>
+#include <locale.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -1107,16 +1108,168 @@ _dbus_string_parse_uint (const DBusString *str,
return TRUE;
}
+static dbus_bool_t
+ascii_isspace (char c)
+{
+ return (c == ' ' ||
+ c == '\f' ||
+ c == '\n' ||
+ c == '\r' ||
+ c == '\t' ||
+ c == '\v');
+}
+
+static dbus_bool_t
+ascii_isdigit (char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+static dbus_bool_t
+ascii_isxdigit (char c)
+{
+ return (ascii_isdigit (c) ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F'));
+}
+
+
+/* Calls strtod in a locale-independent fashion, by looking at
+ * the locale data and patching the decimal comma to a point.
+ *
+ * Relicensed from glib.
+ */
+static double
+ascii_strtod (const char *nptr,
+ char **endptr)
+{
+ char *fail_pos;
+ double val;
+ struct lconv *locale_data;
+ const char *decimal_point;
+ int decimal_point_len;
+ const char *p, *decimal_point_pos;
+ const char *end = NULL; /* Silence gcc */
+
+ fail_pos = NULL;
+
+ locale_data = localeconv ();
+ decimal_point = locale_data->decimal_point;
+ decimal_point_len = strlen (decimal_point);
+
+ _dbus_assert (decimal_point_len != 0);
+
+ decimal_point_pos = NULL;
+ if (decimal_point[0] != '.' ||
+ decimal_point[1] != 0)
+ {
+ p = nptr;
+ /* Skip leading space */
+ while (ascii_isspace (*p))
+ p++;
+
+ /* Skip leading optional sign */
+ if (*p == '+' || *p == '-')
+ p++;
+
+ if (p[0] == '0' &&
+ (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ /* HEX - find the (optional) decimal point */
+
+ while (ascii_isxdigit (*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ while (ascii_isxdigit (*p))
+ p++;
+
+ if (*p == 'p' || *p == 'P')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (ascii_isdigit (*p))
+ p++;
+ end = p;
+ }
+ }
+ else
+ {
+ while (ascii_isdigit (*p))
+ p++;
+
+ if (*p == '.')
+ {
+ decimal_point_pos = p++;
+
+ while (ascii_isdigit (*p))
+ p++;
+
+ if (*p == 'e' || *p == 'E')
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ while (ascii_isdigit (*p))
+ p++;
+ end = p;
+ }
+ }
+ /* For the other cases, we need not convert the decimal point */
+ }
+
+ /* Set errno to zero, so that we can distinguish zero results
+ and underflows */
+ errno = 0;
+
+ if (decimal_point_pos)
+ {
+ char *copy, *c;
+
+ /* We need to convert the '.' to the locale specific decimal point */
+ copy = dbus_malloc (end - nptr + 1 + decimal_point_len);
+
+ c = copy;
+ memcpy (c, nptr, decimal_point_pos - nptr);
+ c += decimal_point_pos - nptr;
+ memcpy (c, decimal_point, decimal_point_len);
+ c += decimal_point_len;
+ memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
+ c += end - (decimal_point_pos + 1);
+ *c = 0;
+
+ val = strtod (copy, &fail_pos);
+
+ if (fail_pos)
+ {
+ if (fail_pos > decimal_point_pos)
+ fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
+ else
+ fail_pos = (char *)nptr + (fail_pos - copy);
+ }
+
+ dbus_free (copy);
+
+ }
+ else
+ val = strtod (nptr, &fail_pos);
+
+ if (endptr)
+ *endptr = fail_pos;
+
+ return val;
+}
+
+
/**
* Parses a floating point number contained in a DBusString. Either
* return parameter may be #NULL if you aren't interested in it. The
* integer is parsed and stored in value_return. Return parameters are
* not initialized if the function returns #FALSE.
*
- * @todo this function is currently locale-dependent. Should
- * ask alexl to relicense g_ascii_strtod() code and put that in
- * here instead, so it's locale-independent.
- *
* @param str the string
* @param start the byte index of the start of the float
* @param value_return return location of the float value or #NULL
@@ -1133,14 +1286,12 @@ _dbus_string_parse_double (const DBusString *str,
const char *p;
char *end;
- _dbus_warn ("_dbus_string_parse_double() needs to be made locale-independent\n");
-
p = _dbus_string_get_const_data_len (str, start,
_dbus_string_get_length (str) - start);
end = NULL;
errno = 0;
- v = strtod (p, &end);
+ v = ascii_strtod (p, &end);
if (end == NULL || end == p || errno != 0)
return FALSE;
@@ -3173,6 +3324,10 @@ check_path_absolute (const char *path,
dbus_bool_t
_dbus_sysdeps_test (void)
{
+ DBusString str;
+ double val;
+ int pos;
+
check_dirname ("foo", ".");
check_dirname ("foo/bar", "foo");
check_dirname ("foo//bar", "foo");
@@ -3192,6 +3347,25 @@ _dbus_sysdeps_test (void)
check_dirname ("///", "/");
check_dirname ("", ".");
+
+ _dbus_string_init_const (&str, "3.5");
+ if (!_dbus_string_parse_double (&str,
+ 0, &val, &pos))
+ {
+ _dbus_warn ("Failed to parse double");
+ exit (1);
+ }
+ if (val != 3.5)
+ {
+ _dbus_warn ("Failed to parse 3.5 correctly, got: %f", val);
+ exit (1);
+ }
+ if (pos != 3)
+ {
+ _dbus_warn ("_dbus_string_parse_double of \"3.5\" returned wrong position %d", pos);
+ exit (1);
+ }
+
check_path_absolute ("/", TRUE);
check_path_absolute ("/foo", TRUE);
check_path_absolute ("", FALSE);
diff --git a/dbus/dbus-test-main.c b/dbus/dbus-test-main.c
index 0c607ec8..50a1c760 100644
--- a/dbus/dbus-test-main.c
+++ b/dbus/dbus-test-main.c
@@ -26,6 +26,7 @@
#include "dbus-test.h"
#include <stdio.h>
#include <stdlib.h>
+#include <locale.h>
int
main (int argc,
@@ -33,6 +34,9 @@ main (int argc,
{
const char *test_data_dir;
+ setlocale(LC_ALL, "");
+
+
if (argc > 1)
test_data_dir = argv[1];
else
diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c
index 19d6d7cd..2d1b5477 100644
--- a/dbus/dbus-test.c
+++ b/dbus/dbus-test.c
@@ -162,12 +162,6 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir)
check_memleaks ();
- printf ("%s: running dict tests\n", "dbus-test");
- if (!_dbus_dict_test ())
- die ("dicts");
-
- check_memleaks ();
-
printf ("%s: completed successfully\n", "dbus-test");
#else
printf ("Not compiled with unit tests, not running any\n");
diff --git a/dbus/dbus.h b/dbus/dbus.h
index 1128d362..025ccbb2 100644
--- a/dbus/dbus.h
+++ b/dbus/dbus.h
@@ -29,7 +29,6 @@
#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 3bd49ac4..200ef430 100644
--- a/doc/dbus-specification.sgml
+++ b/doc/dbus-specification.sgml
@@ -305,49 +305,41 @@
<entry>1</entry>
<entry>Marks an "unset" or "nonexistent" argument</entry>
</row><row>
- <entry>BOOLEAN</entry>
+ <entry>BYTE</entry>
<entry>2</entry>
+ <entry>8-bit unsigned integer.</entry>
+ </row><row>
+ <entry>BOOLEAN</entry>
+ <entry>3</entry>
<entry>Boolean value, 0 is FALSE and 1 is TRUE. Everything else is invalid.</entry>
</row><row>
<entry>INT32</entry>
- <entry>3</entry>
+ <entry>4</entry>
<entry>32-bit signed integer</entry>
</row><row>
<entry>UINT32</entry>
- <entry>4</entry>
+ <entry>5</entry>
<entry>32-bit unsigned integer</entry>
</row><row>
<entry>DOUBLE</entry>
- <entry>5</entry>
+ <entry>6</entry>
<entry>IEEE 754 double</entry>
</row><row>
<entry>STRING</entry>
- <entry>6</entry>
- <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8)</entry>
- </row><row>
- <entry>BOOLEAN_ARRAY</entry>
- <entry>7</entry>
- <entry>Array of BOOLEAN</entry>
- </row><row>
- <entry>INT32_ARRAY</entry>
- <entry>6</entry>
- <entry>Array of INT32</entry>
- </row><row>
- <entry>UINT32_ARRAY</entry>
<entry>7</entry>
- <entry>Array of UINT32</entry>
- </row><row>
- <entry>DOUBLE_ARRAY</entry>
- <entry>8</entry>
- <entry>Array of DOUBLE</entry>
+ <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be zero terminated. </entry>
</row><row>
- <entry>BYTE_ARRAY</entry>
+ <entry>NAMED</entry>
+ <entry>8</entry>
+ <entry>A named byte array, used for custom types</entry>
+ </row><row>
+ <entry>ARRAY</entry>
<entry>9</entry>
- <entry>Array of bytes</entry>
+ <entry>Array</entry>
</row><row>
- <entry>STRING_ARRAY</entry>
+ <entry>DICT</entry>
<entry>10</entry>
- <entry>Array of STRING</entry>
+ <entry>A dictionary of key/value pairs</entry>
</row>
</tbody>
</tgroup>
@@ -372,6 +364,12 @@
<entry>No data is encoded; the type code is followed immediately
by the type code of the next argument.</entry>
</row><row>
+ <entry>BYTE</entry>
+ <entry>a byte.</entry>
+ </row><row>
+ <entry>BOOLEAN</entry>
+ <entry>a byte, with valid values 0 and 1.</entry>
+ </row><row>
<entry>INT32</entry>
<entry>32-bit signed integer in the message's byte order, aligned to 4-byte boundary.</entry>
</row><row>
@@ -388,35 +386,26 @@
byte.
</entry>
</row><row>
- <entry>INT32_ARRAY</entry>
- <entry>UINT32 giving the number of values in the array,
- followed by the given number of INT32 values.
- </entry>
- </row><row>
- <entry>UINT32_ARRAY</entry>
- <entry>UINT32 giving the number of values in the array,
- followed by the given number of UINT32 values.
- </entry>
- </row><row>
- <entry>DOUBLE_ARRAY</entry>
- <entry>UINT32 giving the number of values in the array,
- followed by the given number of DOUBLE values aligned
- to 8-byte boundary.
- </entry>
- </row><row>
- <entry>BYTE_ARRAY</entry>
- <entry>UINT32 giving the number of values in the array,
- followed by the given number of one-byte values.
+ <entry>NAMED</entry>
+ <entry>A string (encoded as the STRING type above) giving the
+ name of the type followed by an UINT32 aligned to 4-byte boundary
+ indicating the data length in bytes, followed by the data.
</entry>
</row><row>
- <entry>STRING_ARRAY</entry>
- <entry>UINT32 giving the number of values in the array,
- followed by the given number of STRING values.
+ <entry>ARRAY</entry>
+ <entry>a byte giving the element type of the array followed
+ by an UINT32 (aligned to 4 bytes) giving the length of the
+ array data in bytes. This is then followed by a number of
+ entires with the same type, encoded like that type normally
+ would be encoded alone.
</entry>
</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>DICT</entry>
+ <entry>UINT32 giving the length of the dictionary data in bytes.
+ This is followed by a number of keyname/value pairs, where the
+ keyname is encoded as a STRING above, and the value is encoded
+ as a byte with typecode and how that type normally would be encoded
+ alone.
</entry>
</row>
</tbody>
diff --git a/glib/test-thread-client.c b/glib/test-thread-client.c
index 0232b860..38926ef0 100644
--- a/glib/test-thread-client.c
+++ b/glib/test-thread-client.c
@@ -13,6 +13,7 @@ thread_func (gpointer data)
{
gint32 threadnr = GPOINTER_TO_INT (data);
guint32 counter = 0;
+ DBusMessageIter iter;
DBusMessage *message;
char *str;
@@ -20,18 +21,20 @@ thread_func (gpointer data)
{
message = dbus_message_new (NULL, "org.freedesktop.ThreadTest");
- if (!dbus_message_append_int32 (message, threadnr))
+ dbus_message_append_iter_init (message, &iter);
+
+ if (!dbus_message_iter_append_int32 (&iter, threadnr))
{
g_print ("thread %d: append threadnr failed\n", threadnr);
}
- if (!dbus_message_append_uint32 (message, counter))
+ if (!dbus_message_iter_append_uint32 (&iter, counter))
{
g_print ("thread %d: append counter (%d) failed\n", threadnr, counter);
}
str = g_strdup_printf ("Thread %d-%d\n", threadnr, counter);
- if (!dbus_message_append_string (message, str))
+ if (!dbus_message_iter_append_string (&iter, str))
{
g_print ("thread %d: append string (%s) failed\n", threadnr, str);
}
diff --git a/glib/test-thread-server.c b/glib/test-thread-server.c
index 06f597df..367a2b33 100644
--- a/glib/test-thread-server.c
+++ b/glib/test-thread-server.c
@@ -36,41 +36,40 @@ handle_test_message (DBusMessageHandler *handler,
void *user_data)
{
ThreadTestData *data = user_data;
- DBusMessageIter *iter;
+ DBusMessageIter iter;
gint32 threadnr;
guint32 counter;
char *str, *expected_str;
GString *counter_str;
int i;
- iter = dbus_message_get_args_iter (message);
- g_assert (iter != NULL);
+ dbus_message_iter_init (message, &iter);
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
{
g_print ("First arg not right type\n");
goto out;
}
- threadnr = dbus_message_iter_get_int32 (iter);
+ threadnr = dbus_message_iter_get_int32 (&iter);
if (threadnr < 0 || threadnr >= N_TEST_THREADS)
{
g_print ("Invalid thread nr\n");
goto out;
}
- if (! dbus_message_iter_next (iter))
+ if (! dbus_message_iter_next (&iter))
{
g_print ("Couldn't get second arg\n");
goto out;
}
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
{
g_print ("Second arg not right type\n");
goto out;
}
- counter = dbus_message_iter_get_uint32 (iter);
+ counter = dbus_message_iter_get_uint32 (&iter);
if (counter != data->counters[threadnr])
{
@@ -79,19 +78,19 @@ handle_test_message (DBusMessageHandler *handler,
}
data->counters[threadnr]++;
- if (! dbus_message_iter_next (iter))
+ if (! dbus_message_iter_next (&iter))
{
g_print ("Couldn't get third arg\n");
goto out;
}
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
+ if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
{
g_print ("Third arg not right type\n");
goto out;
}
- str = dbus_message_iter_get_string (iter);
+ str = dbus_message_iter_get_string (&iter);
if (str == NULL)
{
@@ -108,7 +107,7 @@ handle_test_message (DBusMessageHandler *handler,
g_free (str);
g_free (expected_str);
- if (dbus_message_iter_next (iter))
+ if (dbus_message_iter_next (&iter))
{
g_print ("Extra args on end of message\n");
goto out;
diff --git a/test/data/incomplete-messages/missing-body.message b/test/data/incomplete-messages/missing-body.message
index c97ef7a3..71ac5abc 100644
--- a/test/data/incomplete-messages/missing-body.message
+++ b/test/data/incomplete-messages/missing-body.message
@@ -1,7 +1,11 @@
## message that's missing an expected body
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
END_LENGTH Header
+ALIGN 8
## create the body, then chop it off
START_LENGTH Body
diff --git a/test/data/invalid-messages/bad-boolean-array.message b/test/data/invalid-messages/bad-boolean-array.message
index 54b31d6c..c045b978 100644
--- a/test/data/invalid-messages/bad-boolean-array.message
+++ b/test/data/invalid-messages/bad-boolean-array.message
@@ -2,10 +2,14 @@
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
ALIGN 8
END_LENGTH Header
START_LENGTH Body
-TYPE BOOLEAN_ARRAY
+TYPE ARRAY
+TYPE BOOLEAN
ALIGN 4
INT32 3
BYTE 0
diff --git a/test/data/invalid-messages/bad-boolean.message b/test/data/invalid-messages/bad-boolean.message
index 0755ab5e..00a29626 100644
--- a/test/data/invalid-messages/bad-boolean.message
+++ b/test/data/invalid-messages/bad-boolean.message
@@ -2,6 +2,9 @@
## VALID_HEADER includes a LENGTH Header and LENGTH Body
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
ALIGN 8
END_LENGTH Header
START_LENGTH Body
diff --git a/test/data/invalid-messages/boolean-array-length-too-long.message-raw b/test/data/invalid-messages/boolean-array-length-too-long.message-raw
index 2326ec9d..07d4b341 100644
--- a/test/data/invalid-messages/boolean-array-length-too-long.message-raw
+++ b/test/data/invalid-messages/boolean-array-length-too-long.message-raw
Binary files differ
diff --git a/test/data/invalid-messages/boolean-has-no-value.message-raw b/test/data/invalid-messages/boolean-has-no-value.message-raw
index cba9e839..11b15c86 100644
--- a/test/data/invalid-messages/boolean-has-no-value.message-raw
+++ b/test/data/invalid-messages/boolean-has-no-value.message-raw
Binary files differ
diff --git a/test/data/invalid-messages/dict-with-nil-value.message b/test/data/invalid-messages/dict-with-nil-value.message
deleted file mode 100644
index 8f899605..00000000
--- a/test/data/invalid-messages/dict-with-nil-value.message
+++ /dev/null
@@ -1,12 +0,0 @@
-# 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
index 6df40b33..14722023 100644
--- a/test/data/invalid-messages/too-short-dict.message
+++ b/test/data/invalid-messages/too-short-dict.message
@@ -1,11 +1,15 @@
# Message with lots of different argument types
VALID_HEADER
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
END_LENGTH Header
ALIGN 8
START_LENGTH Body
TYPE DICT
-STRING_ARRAY { 'int32', 'uint32' }
+STRING 'uint32'
TYPE UINT32
UINT32 0x8765432
+STRING 'uint32'
END_LENGTH Body
diff --git a/test/data/valid-messages/dict-simple.message b/test/data/valid-messages/dict-simple.message
index 0de1a782..34fb47d9 100644
--- a/test/data/valid-messages/dict-simple.message
+++ b/test/data/valid-messages/dict-simple.message
@@ -8,7 +8,10 @@ END_LENGTH Header
ALIGN 8
START_LENGTH Body
TYPE DICT
-STRING_ARRAY { 'int32' }
+LENGTH Dict
+START_LENGTH Dict
+STRING 'int32'
TYPE INT32
INT32 0x12345678
+END_LENGTH Dict
END_LENGTH Body
diff --git a/test/data/valid-messages/dict.message b/test/data/valid-messages/dict.message
index ce99a282..6b9d004e 100644
--- a/test/data/valid-messages/dict.message
+++ b/test/data/valid-messages/dict.message
@@ -8,25 +8,42 @@ ALIGN 8
END_LENGTH Header
START_LENGTH Body
TYPE DICT
-STRING_ARRAY { 'boolean', 'int32', 'uint32', 'double', 'string', 'boolean_array', 'int32_array', 'uint32_array', 'double_array', 'string_array' }
+LENGTH Dict
+START_LENGTH Dict
+STRING 'boolean'
TYPE BOOLEAN
BYTE 1
+STRING 'int32'
TYPE INT32
INT32 0x12345678
+STRING 'uint32'
TYPE UINT32
UINT32 0x8765432
+STRING 'double'
TYPE DOUBLE
DOUBLE 3.141592653589
+STRING 'string'
TYPE STRING
STRING 'This is a string'
-TYPE BOOLEAN_ARRAY
+STRING 'boolean_array'
+TYPE ARRAY
+TYPE BOOLEAN
BOOLEAN_ARRAY { true, false, false, true, false }
-TYPE INT32_ARRAY
+STRING 'int32_array'
+TYPE ARRAY
+TYPE INT32
INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
-TYPE UINT32_ARRAY
+STRING 'uint32_array'
+TYPE ARRAY
+TYPE UINT32
UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
-TYPE DOUBLE_ARRAY
+STRING 'double_array'
+TYPE ARRAY
+TYPE DOUBLE
DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
-TYPE STRING_ARRAY
+STRING 'string_array'
+TYPE ARRAY
+TYPE STRING
STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+END_LENGTH Dict
END_LENGTH Body
diff --git a/test/data/valid-messages/emptiness.message b/test/data/valid-messages/emptiness.message
index 36f3fc3d..87196b16 100644
--- a/test/data/valid-messages/emptiness.message
+++ b/test/data/valid-messages/emptiness.message
@@ -10,35 +10,56 @@ START_LENGTH Body
TYPE STRING
INT32 0
BYTE 0 # Strings need to be NULL-terminated
-TYPE BOOLEAN_ARRAY
+TYPE ARRAY
+TYPE BOOLEAN
INT32 0
-TYPE INT32_ARRAY
+TYPE ARRAY
+TYPE INT32
INT32 0
-TYPE UINT32_ARRAY
+TYPE ARRAY
+TYPE UINT32
INT32 0
-TYPE DOUBLE_ARRAY
+TYPE ARRAY
+TYPE DOUBLE
INT32 0
-TYPE BYTE_ARRAY
+TYPE ARRAY
+TYPE BYTE
INT32 0
-TYPE STRING_ARRAY
+TYPE ARRAY
+TYPE STRING
INT32 0
TYPE DICT
INT32 0
# A dict with empty arrays
TYPE DICT
-STRING_ARRAY {'boolean_array', 'int32_array' , 'uint32_array', 'double_array', 'byte_array', 'string_array' }
-TYPE BOOLEAN_ARRAY
+LENGTH Dict
+START_LENGTH Dict
+STRING 'boolean_array'
+TYPE ARRAY
+TYPE BOOLEAN
INT32 0
-TYPE INT32_ARRAY
+STRING 'int32_array'
+TYPE ARRAY
+TYPE INT32
INT32 0
-TYPE UINT32_ARRAY
+STRING 'uint32_array'
+TYPE ARRAY
+TYPE UINT32
INT32 0
-TYPE DOUBLE_ARRAY
+STRING 'double_array'
+TYPE ARRAY
+TYPE DOUBLE
INT32 0
-TYPE BYTE_ARRAY
+STRING 'byte_array'
+TYPE ARRAY
+TYPE BYTE
INT32 0
-TYPE STRING_ARRAY
+STRING 'string_array' }
+TYPE ARRAY
+TYPE STRING
INT32 0
+END_LENGTH Dict
+
END_LENGTH Body
diff --git a/test/data/valid-messages/lots-of-arguments.message b/test/data/valid-messages/lots-of-arguments.message
index cc9c5a75..6549646e 100644
--- a/test/data/valid-messages/lots-of-arguments.message
+++ b/test/data/valid-messages/lots-of-arguments.message
@@ -8,6 +8,8 @@ END_LENGTH Header
ALIGN 8
START_LENGTH Body
TYPE NIL
+TYPE BYTE
+BYTE 42
TYPE INT32
INT32 0x12345678
TYPE UINT32
@@ -16,14 +18,50 @@ TYPE DOUBLE
DOUBLE 3.141592653589
TYPE STRING
STRING 'This is a string'
-TYPE BOOLEAN_ARRAY
+TYPE ARRAY
+TYPE BOOLEAN
BOOLEAN_ARRAY { true, false, false, true, false }
-TYPE INT32_ARRAY
+TYPE ARRAY
+TYPE INT32
INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
-TYPE UINT32_ARRAY
+TYPE ARRAY
+TYPE UINT32
UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
-TYPE DOUBLE_ARRAY
+TYPE ARRAY
+TYPE DOUBLE
DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
-TYPE STRING_ARRAY
+TYPE ARRAY
+TYPE STRING
STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+TYPE NAMED
+STRING 'named type'
+BYTE_ARRAY { 'b', 'i', 'n', 'a', 'r', 'y', 'd', 'a', 't', 'a' }
+
+TYPE ARRAY
+TYPE DICT
+LENGTH Array
+START_LENGTH Array
+
+LENGTH Dict1
+START_LENGTH Dict1
+STRING 'key1'
+TYPE INT32
+INT32 0x12345678
+STRING 'key2'
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Dict1
+
+LENGTH Dict2
+START_LENGTH Dict2
+STRING 'key1'
+TYPE INT32
+INT32 0x12345678
+STRING 'key2'
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Dict2
+
+END_LENGTH Array
+
END_LENGTH Body
diff --git a/test/data/valid-messages/no-padding.message b/test/data/valid-messages/no-padding.message
index ab5b5a80..b47dca78 100644
--- a/test/data/valid-messages/no-padding.message
+++ b/test/data/valid-messages/no-padding.message
@@ -10,7 +10,8 @@ STRING 'org.freedesktop.Foo'
## this byte array is filled with zeros to the natural length
## of the header
FIELD_NAME unkn
-TYPE BYTE_ARRAY
+TYPE ARRAY
+TYPE BYTE
ALIGN 4
LENGTH ThisByteArray
START_LENGTH ThisByteArray
diff --git a/test/data/valid-messages/recursive-types.message b/test/data/valid-messages/recursive-types.message
new file mode 100644
index 00000000..b7608041
--- /dev/null
+++ b/test/data/valid-messages/recursive-types.message
@@ -0,0 +1,65 @@
+## Message with recursive types
+
+## VALID_HEADER includes a LENGTH Header and LENGTH Body
+VALID_HEADER
+
+FIELD_NAME name
+TYPE STRING
+STRING 'org.freedesktop.Foo'
+
+END_LENGTH Header
+START_LENGTH Body
+
+TYPE ARRAY
+TYPE ARRAY
+LENGTH Array1
+START_LENGTH Array1
+
+
+TYPE UINT32
+UINT32_ARRAY { 1, 2, 3, 4, 5}
+
+
+TYPE STRING
+STRING_ARRAY { 'a', 'string', 'array'}
+
+
+TYPE DICT
+LENGTH Array2
+START_LENGTH Array2
+
+LENGTH Dict1
+START_LENGTH Dict1
+STRING 'uint32'
+TYPE UINT32
+UINT32 1234
+STRING uint32'
+TYPE INT32
+INT32 1234
+END_LENGTH Dict1
+
+LENGTH Dict2
+START_LENGTH Dict2
+
+STRING 'dict'
+TYPE DICT
+LENGTH Dict3
+START_LENGTH Dict3
+STRING 'double-array'
+TYPE ARRAY
+TYPE DOUBLE
+DOUBLE_ARRAY {1.0, 2.0, 3.0}
+STRING 'boolean'
+TYPE BOOLEAN
+BOOLEAN false
+END_LENGTH Dict3
+
+END_LENGTH Dict2
+
+END_LENGTH Array2
+
+
+END_LENGTH Array1
+
+
+END_LENGTH Body
diff --git a/test/test-service.c b/test/test-service.c
index a9a960a1..56764dea 100644
--- a/test/test-service.c
+++ b/test/test-service.c
@@ -27,6 +27,7 @@ handle_echo (DBusConnection *connection,
{
DBusError error;
DBusMessage *reply;
+ DBusMessageIter iter;
char *s;
dbus_error_init (&error);
@@ -55,7 +56,9 @@ handle_echo (DBusConnection *connection,
if (reply == NULL)
die ("No memory\n");
- if (!dbus_message_append_string (reply, s))
+ dbus_message_append_iter_init (message, &iter);
+
+ if (!dbus_message_iter_append_string (&iter, s))
die ("No memory");
if (!dbus_connection_send (connection, reply, NULL))