summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2003-04-08 15:52:51 +0000
committerAlexander Larsson <alexl@redhat.com>2003-04-08 15:52:51 +0000
commitc5020ac870c5990a36c3576453cc23431213e8bf (patch)
tree8b5c4c5b884e9481d1ce17b9a24d9c1bbe094428
parenta162febe6746269f51b3a16db5f6fb240001f828 (diff)
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.
-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))