2003-04-08 Alexander Larsson <alexl@redhat.com>
authorAlexander Larsson <alexl@redhat.com>
Tue, 8 Apr 2003 15:52:51 +0000 (15:52 +0000)
committerAlexander Larsson <alexl@redhat.com>
Tue, 8 Apr 2003 15:52:51 +0000 (15:52 +0000)
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.

34 files changed:
ChangeLog
bus/driver.c
dbus/Makefile.am
dbus/dbus-dict.c [deleted file]
dbus/dbus-dict.h [deleted file]
dbus/dbus-internals.c
dbus/dbus-marshal.c
dbus/dbus-marshal.h
dbus/dbus-message-builder.c
dbus/dbus-message.c
dbus/dbus-message.h
dbus/dbus-protocol.h
dbus/dbus-string.c
dbus/dbus-sysdeps.c
dbus/dbus-test-main.c
dbus/dbus-test.c
dbus/dbus.h
doc/dbus-specification.sgml
glib/test-thread-client.c
glib/test-thread-server.c
test/data/incomplete-messages/missing-body.message
test/data/invalid-messages/bad-boolean-array.message
test/data/invalid-messages/bad-boolean.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/dict-with-nil-value.message [deleted file]
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 [new file with mode: 0644]
test/test-service.c

index d7542dc..ec91b56 100644 (file)
--- 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
index 814e32a..ba31f3e 100644 (file)
@@ -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))
index 957227e..d99ff1c 100644 (file)
@@ -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 (file)
index e19f9a6..0000000
+++ /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 (file)
index b3b6eb9..0000000
+++ /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 */
index 8d80397..de98c1f 100644 (file)
@@ -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";
     }
index 2222ad9..a5cea38 100644 (file)
@@ -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);
   
       
index 85549e1..0f40cd7 100644 (file)
@@ -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);
 
index 044c2a7..dbfe323 100644 (file)
@@ -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"))
        {
index 46c4c40..994e160 100644 (file)
@@ -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,1025 +1212,1802 @@ 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
+ * 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 boolean value
- * @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_boolean (DBusMessage  *message,
-                            dbus_bool_t   value)
+dbus_message_get_args (DBusMessage     *message,
+                       DBusError       *error,
+                      int              first_arg_type,
+                      ...)
 {
-  _dbus_assert (!message->locked);
-  
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN))
-    return FALSE;
+  dbus_bool_t retval;
+  va_list var_args;
 
-  if (!_dbus_string_append_byte (&message->body, (value != FALSE)))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  _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);
+  va_end (var_args);
 
-  return TRUE;
+  return retval;
 }
 
 /**
- * Appends a 32 bit signed integer to the message.
+ * This function takes a va_list for use by language bindings
+ *
+ * @todo We need to free the argument data when an error occurs.
  *
+ * @see dbus_message_get_args
  * @param message the message
- * @param value the integer value
- * @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_int32 (DBusMessage  *message,
-                          dbus_int32_t  value)
+dbus_message_get_args_valist (DBusMessage     *message,
+                              DBusError       *error,
+                             int              first_arg_type,
+                             va_list          var_args)
 {
-  _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;
-    }
+  DBusMessageIter iter;
 
-  return TRUE;
+  dbus_message_iter_init (message, &iter);
+  return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
 }
 
 /**
- * Appends a 32 bit unsigned integer to the message.
+ * 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 value the integer value
- * @returns #TRUE on success
+ * @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_append_uint32 (DBusMessage   *message,
-                           dbus_uint32_t  value)
+dbus_message_iter_get_args (DBusMessageIter *iter,
+                           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_UINT32))
-      return FALSE;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
-  if (!_dbus_marshal_uint32 (&message->body, message->byte_order, value))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  va_start (var_args, first_arg_type);
+  retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
+  va_end (var_args);
 
-  return TRUE;      
+  return retval;
 }
 
 /**
- * Appends a double value to the message.
+ * This function takes a va_list for use by language bindings
  *
- * @param message the message
- * @param value the double value
- * @returns #TRUE on success
+ * @todo this function (or some lower-level non-convenience function)
+ * needs better error handling; should allow the application to
+ * distinguish between out of memory, and bad data from the remote
+ * app. It also needs to not leak a bunch of args when it gets
+ * to the arg that's bad, as that would be a security hole
+ * (allow one app to force another to leak memory)
+ *
+ * @todo We need to free the argument data when an error occurs.
+ *
+ * @see dbus_message_get_args
+ * @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_append_double (DBusMessage *message,
-                           double       value)
+dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+                                  DBusError       *error,
+                                  int              first_arg_type,
+                                  va_list          var_args)
 {
-  _dbus_assert (!message->locked);
+  int spec_type, msg_type, i;
+  dbus_bool_t retval;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
-    return FALSE;
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
-  if (!_dbus_marshal_double (&message->body, message->byte_order, value))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  retval = FALSE;
   
-  return TRUE;
-}
-
-/**
- * Appends a UTF-8 string to the message.
- *
- * @param message the message
- * @param value the string
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_string (DBusMessage *message,
-                           const char  *value)
-{
-  _dbus_assert (!message->locked);
-
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
-      return FALSE;
+  spec_type = first_arg_type;
+  i = 0;
   
-  if (!_dbus_marshal_string (&message->body, message->byte_order, value))
+  while (spec_type != 0)
     {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;      
-    }
+      msg_type = dbus_message_iter_get_arg_type (iter);      
+      
+      if (msg_type != spec_type)
+       {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Argument %d is specified to be of type \"%s\", but "
+                          "is actually of type \"%s\"\n", i,
+                          _dbus_type_to_string (spec_type),
+                          _dbus_type_to_string (msg_type));
 
-  return TRUE;
-}
+          goto out;
+       }
 
-/**
- * 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);
+      switch (spec_type)
+       {
+       case DBUS_TYPE_NIL:
+         break;
+       case DBUS_TYPE_BYTE:
+         {
+           unsigned char *ptr;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN_ARRAY))
-    return FALSE;
+           ptr = va_arg (var_args, unsigned char *);
 
-  if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+           *ptr = dbus_message_iter_get_byte (iter);
+           break;
+         }
+       case DBUS_TYPE_BOOLEAN:
+         {
+           dbus_bool_t *ptr;
 
-  return TRUE;
-}
+           ptr = va_arg (var_args, dbus_bool_t *);
 
-/**
- * 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);
+           *ptr = dbus_message_iter_get_boolean (iter);
+           break;
+         }
+       case DBUS_TYPE_INT32:
+         {
+           dbus_int32_t *ptr;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32_ARRAY))
-    return FALSE;
+           ptr = va_arg (var_args, dbus_int32_t *);
 
-  if (!_dbus_marshal_int32_array (&message->body, message->byte_order,
-                                 value, len))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+           *ptr = dbus_message_iter_get_int32 (iter);
+           break;
+         }
+       case DBUS_TYPE_UINT32:
+         {
+           dbus_uint32_t *ptr;
+
+           ptr = va_arg (var_args, dbus_uint32_t *);
+
+           *ptr = dbus_message_iter_get_uint32 (iter);
+           break;
+         }
+
+       case DBUS_TYPE_DOUBLE:
+         {
+           double *ptr;
+
+           ptr = va_arg (var_args, double *);
+
+           *ptr = dbus_message_iter_get_double (iter);
+           break;
+         }
+
+       case DBUS_TYPE_STRING:
+         {
+           char **ptr;
+
+           ptr = va_arg (var_args, char **);
+
+           *ptr = dbus_message_iter_get_string (iter);
+
+           if (!*ptr)
+              {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                goto out;
+              }
+           
+           break;
+         }
+
+       case DBUS_TYPE_NAMED:
+         {
+           char **name;
+           unsigned char **data;
+           int *len;
+           name = va_arg (var_args, char **);
+           data = va_arg (var_args, unsigned char **);
+           len = va_arg (var_args, int *);
+
+           *name = dbus_message_iter_get_named (iter, data, len);
+           if (*name == NULL)
+             {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+               goto out;
+             }
+         }
+         break;
+       case DBUS_TYPE_ARRAY:
+         {
+           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_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;
+             }
+           
+           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:
+         _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);
+      if (spec_type != 0 && !dbus_message_iter_next (iter))
+        {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Message has only %d arguments, but more were expected", i);
+          goto out;
+        }
+
+      i++;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  
+  return retval;
+}
 
-  return TRUE;
-}
 
 /**
- * Appends a 32 bit unsigned integer array to the message.
+ * Initializes a DBusMessageIter representing the arguments of the
+ * message passed in.
  *
  * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param _iter pointer to an iterator to initialize
  */
-dbus_bool_t
-dbus_message_append_uint32_array (DBusMessage         *message,
-                                 const dbus_uint32_t *value,
-                                 int                  len)
+void
+dbus_message_iter_init (DBusMessage *message,
+                       DBusMessageIter *iter)
 {
-  _dbus_assert (!message->locked);
+  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->pos = 0;
+  real->end = _dbus_string_get_length (&message->body);
+  
+  real->container_type = 0;
+  real->container_start = 0;
+  real->container_length_pos = 0;
+  real->wrote_dict_key = 0;
+}
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32_ARRAY))
-    return FALSE;
+static void
+dbus_message_iter_check (DBusMessageRealIter *iter)
+{
+  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");
+}
 
-  if (!_dbus_marshal_uint32_array (&message->body, message->byte_order,
-                                 value, len))
+static int
+dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
+{
+  const char *data;
+  int pos, len;
+  
+  switch (iter->type)
     {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
+    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;
     }
-
-  return TRUE;
+  *type = DBUS_TYPE_INVALID;
+  return iter->pos;
 }
 
+
 /**
- * Appends a double array to the message.
+ * Checks if an iterator has any more fields.
  *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns #TRUE if there are more fields
+ * following
  */
 dbus_bool_t
-dbus_message_append_double_array (DBusMessage  *message,
-                                 const double *value,
-                                 int           len)
+dbus_message_iter_has_next (DBusMessageIter *iter)
 {
-  _dbus_assert (!message->locked);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int end_pos;
+  int type, pos;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE_ARRAY))
-    return FALSE;
+  dbus_message_iter_check (real);
 
-  if (!_dbus_marshal_double_array (&message->body, message->byte_order,
-                                  value, len))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  if (real->pos >= real->end)
+    return FALSE;
+  
+  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;
+  return TRUE;  
 }
 
 /**
- * Appends a byte array to the message.
+ * Moves the iterator to the next field.
  *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param _iter The message iter
+ * @returns #TRUE if the iterator was moved to the next field
  */
 dbus_bool_t
-dbus_message_append_byte_array (DBusMessage         *message,
-                               unsigned const char *value,
-                               int                 len)
+dbus_message_iter_next (DBusMessageIter *iter)
 {
-  _dbus_assert (!message->locked);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int end_pos;
+  int type, pos;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
-    return FALSE;
+  dbus_message_iter_check (real);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
   
-  if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
-      
+  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;
+
+  real->pos = end_pos;
+
   return TRUE;
 }
 
 /**
- * Appends a string array to the message.
+ * Returns the argument type of the argument that the
+ * message iterator points at.
  *
- * @param message the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns the field type
  */
-dbus_bool_t
-dbus_message_append_string_array (DBusMessage  *message,
-                                 const char  **value,
-                                 int           len)
+int
+dbus_message_iter_get_arg_type (DBusMessageIter *iter)
 {
-  _dbus_assert (!message->locked);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
-    return FALSE;
+  dbus_message_iter_check (real);
 
-  if (!_dbus_marshal_string_array (&message->body, message->byte_order,
-                                  (const char **)value, len))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  if (real->pos >= real->end)
+    return DBUS_TYPE_INVALID;
 
-  return TRUE;
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  return type;
 }
 
 /**
- * Appends a dict to the message.
+ * 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 message the message
- * @param dict the dict
- * @returns #TRUE on success
+ * @param iter the message iter
+ * @returns the field type
  */
-dbus_bool_t
-dbus_message_append_dict (DBusMessage *message,
-                         DBusDict    *dict)
+int
+dbus_message_iter_get_array_type (DBusMessageIter *iter)
 {
-  _dbus_assert (!message->locked);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
+  const char *data;
 
-  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT))
-    return FALSE;
+  dbus_message_iter_check (real);
 
-  if (!_dbus_marshal_dict (&message->body, message->byte_order, dict))
-    {
-      _dbus_string_shorten (&message->body, 1);
-      return FALSE;
-    }
+  if (real->pos >= real->end)
+    return DBUS_TYPE_INVALID;
 
-  return TRUE;
+  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)
+    return *data;
+  
+  return DBUS_TYPE_INVALID;
 }
 
+
 /**
- * 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.
+ * Returns the string value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a string value before using this function.
  *
- * @param message the message
- * @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
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the string
  */
-dbus_bool_t
-dbus_message_get_args (DBusMessage *message,
-                       DBusError   *error,
-                      int          first_arg_type,
-                      ...)
+char *
+dbus_message_iter_get_string (DBusMessageIter *iter)
 {
-  dbus_bool_t retval;
-  va_list var_args;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  dbus_message_iter_check (real);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
   
-  va_start (var_args, first_arg_type);
-  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
-  va_end (var_args);
+  _dbus_assert (type == DBUS_TYPE_STRING);
 
-  return retval;
+  return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+                                 pos, NULL);
 }
 
 /**
- * This function takes a va_list for use by language bindings
- *
- * @todo this function (or some lower-level non-convenience function)
- * needs better error handling; should allow the application to
- * distinguish between out of memory, and bad data from the remote
- * app. It also needs to not leak a bunch of args when it gets
- * to the arg that's bad, as that would be a security hole
- * (allow one app to force another to leak memory)
- *
- * @todo We need to free the argument data when an error occurs.
+ * 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_get_args
- * @param message the message
- * @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
+ * @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
+ * 
  */
-dbus_bool_t
-dbus_message_get_args_valist (DBusMessage *message,
-                              DBusError   *error,
-                             int          first_arg_type,
-                             va_list      var_args)
+char *
+dbus_message_iter_get_named (DBusMessageIter   *iter,
+                            unsigned char    **value,
+                            int               *len)
 {
-  int spec_type, msg_type, i;
-  DBusMessageIter *iter;
-  dbus_bool_t retval;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
+  char *name;
 
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  dbus_message_iter_check (real);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_NAMED);
   
-  iter = dbus_message_get_args_iter (message);
+  name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+                                 pos, &pos);
 
-  if (iter == NULL)
+  if (name == NULL)
+    return NULL;
+  
+  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+                                  pos + 1, NULL, value, len))
     {
-      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-      return FALSE;
+      dbus_free (name);
+      return NULL;
     }
+  else
+    return name;
+}
 
-  retval = FALSE;
+/**
+ * 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);
   
-  spec_type = first_arg_type;
-  i = 0;
+  _dbus_assert (type == DBUS_TYPE_BYTE);
+
+  value = _dbus_string_get_byte (&real->message->body, pos);
   
-  while (spec_type != 0)
-    {
-      msg_type = dbus_message_iter_get_arg_type (iter);      
-      
-      if (msg_type != spec_type)
-       {
-          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                          "Argument %d is specified to be of type \"%s\", but "
-                          "is actually of type \"%s\"\n", i,
-                          _dbus_type_to_string (spec_type),
-                          _dbus_type_to_string (msg_type));
+  return value;
+}
 
-          goto out;
-       }
 
-      switch (spec_type)
-       {
-       case DBUS_TYPE_NIL:
-         break;
-       case DBUS_TYPE_BOOLEAN:
-         {
-           dbus_bool_t *ptr;
+/**
+ * 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 boolean value
+ */
+dbus_bool_t
+dbus_message_iter_get_boolean (DBusMessageIter *iter)
+{
+  unsigned char value;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-           ptr = va_arg (var_args, dbus_bool_t *);
+  dbus_message_iter_check (real);
 
-           *ptr = dbus_message_iter_get_boolean (iter);
-           break;
-         }
-       case DBUS_TYPE_INT32:
-         {
-           dbus_int32_t *ptr;
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_BOOLEAN);
 
-           ptr = va_arg (var_args, dbus_int32_t *);
+  value = _dbus_string_get_byte (&real->message->body, pos);
+  
+  return value;
+}
 
-           *ptr = dbus_message_iter_get_int32 (iter);
-           break;
-         }
-       case DBUS_TYPE_UINT32:
-         {
-           dbus_uint32_t *ptr;
+/**
+ * Returns the 32 bit signed integer value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * an integer value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the integer
+ */
+dbus_int32_t
+dbus_message_iter_get_int32 (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-           ptr = va_arg (var_args, dbus_uint32_t *);
+  dbus_message_iter_check (real);
 
-           *ptr = dbus_message_iter_get_uint32 (iter);
-           break;
-         }
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_INT32);
+  
+  return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
+                               pos, NULL);
+}
 
-       case DBUS_TYPE_DOUBLE:
-         {
-           double *ptr;
+/**
+ * Returns the 32 bit unsigned integer value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * an unsigned integer value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the integer
+ */
+dbus_uint32_t
+dbus_message_iter_get_uint32 (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-           ptr = va_arg (var_args, double *);
+  dbus_message_iter_check (real);
 
-           *ptr = dbus_message_iter_get_double (iter);
-           break;
-         }
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_UINT32);
+  
+  return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+                                pos, NULL);
+}
 
-       case DBUS_TYPE_STRING:
-         {
-           char **ptr;
+/**
+ * Returns the double value that an iterator may point to.
+ * Note that you need to check that the iterator points to
+ * a string value before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @returns the double
+ */
+double
+dbus_message_iter_get_double (DBusMessageIter *iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
 
-           ptr = va_arg (var_args, char **);
+  dbus_message_iter_check (real);
 
-           *ptr = dbus_message_iter_get_string (iter);
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_DOUBLE);
+  
+  return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
+                                pos, NULL);
+}
 
-           if (!*ptr)
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           
-           break;
-         }
+/**
+ * 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;
 
-       case DBUS_TYPE_BOOLEAN_ARRAY:
-         {
-           unsigned char **ptr;
-           int *len;
+  dbus_message_iter_check (real);
 
-           ptr = va_arg (var_args, unsigned char **);
-           len = va_arg (var_args, int *);
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_ARRAY);
 
-           if (!dbus_message_iter_get_boolean_array (iter, ptr, len))
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           break;
-         }
-         
-       case DBUS_TYPE_INT32_ARRAY:
-         {
-           dbus_int32_t **ptr;
-           int *len;
+  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;
 
-           ptr = va_arg (var_args, dbus_int32_t **);
-           len = va_arg (var_args, int *);
+  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 (!dbus_message_iter_get_int32_array (iter, ptr, len))
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           
-           break;
-         }
+  if (array_type != NULL)
+    *array_type = _array_type;
+  
+  return TRUE;
+}
 
-       case DBUS_TYPE_UINT32_ARRAY:
-         {
-           dbus_uint32_t **ptr;
-           int *len;
 
-           ptr = va_arg (var_args, dbus_uint32_t **);
-           len = va_arg (var_args, int *);
+/**
+ * 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;
 
-           if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           
-           break;
-         }
+  dbus_message_iter_check (real);
 
-       case DBUS_TYPE_DOUBLE_ARRAY:
-         {
-           double **ptr;
-           int *len;
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_DICT);
 
-           ptr = va_arg (var_args, double **);
-           len = va_arg (var_args, int *);
+  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;
 
-           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;
+  return TRUE;
+}
 
-           ptr = va_arg (var_args, unsigned char **);
-           len = va_arg (var_args, int *);
+/**
+ * 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;
 
-           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;
+  dbus_message_iter_check (real);
 
-           ptr = va_arg (var_args, char ***);
-           len = va_arg (var_args, int *);
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_ARRAY);
 
-           if (!dbus_message_iter_get_string_array (iter, ptr, len))
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           break;
-         }
-       case DBUS_TYPE_DICT:
-         {
-           DBusDict **dict;
+  data = _dbus_string_get_const_data_len (&real->message->body,
+                                         pos,
+                                         1);
 
-           dict = va_arg (var_args, DBusDict **);
+  _dbus_assert (*data == DBUS_TYPE_BYTE);
 
-           if (!dbus_message_iter_get_dict (iter, dict))
-              {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-                goto out;
-              }
-           break;
-         }
-       default:          
-         _dbus_warn ("Unknown field type %d\n", spec_type);
-       }
-      
-      spec_type = va_arg (var_args, int);
-      if (spec_type != 0 && !dbus_message_iter_next (iter))
-        {
-          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                          "Message has only %d arguments, but more were expected", i);
-          goto out;
-        }
+  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+                                  pos + 1, NULL, value, len))
+    return FALSE;
+  else
+    return TRUE;
+}
 
-      i++;
-    }
+/**
+ * Returns the boolean array that the iterator may point to. Note that
+ * you need to check that the iterator points to an array of the
+ * correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_boolean_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);
   
-  retval = TRUE;
+  _dbus_assert (type == DBUS_TYPE_ARRAY);
+
+  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;
+}
+
+/**
+ * Returns the 32 bit signed integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
+                                   dbus_int32_t   **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);
   
- out:
-  dbus_message_iter_unref (iter);
-  return retval;
+  _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;
 }
 
 /**
- * Returns a DBusMessageIter representing the arguments of the
- * message passed in.
+ * Returns the 32 bit unsigned integer array that the iterator may point
+ * to. Note that you need to check that the iterator points to an
+ * array of the correct type prior to using this function.
+ *
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
+                                    dbus_uint32_t  **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_UINT32);
+
+  if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
+                                   pos + 1, NULL, value, len))
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/**
+ * Returns the double array that the iterator may point to. Note that
+ * you need to check that the iterator points to an array of the
+ * correct type prior to using this function.
  *
- * @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.
+ * @param iter the iterator
+ * @param value return location for the array
+ * @param len return location for the array length
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_double_array  (DBusMessageIter *iter,
+                                    double         **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_DOUBLE);
+
+  if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
+                                    pos + 1, NULL, value, len))
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/**
+ * Returns the string 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.
  *
- * @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
+ * The returned value is a #NULL-terminated array of strings.
+ * Each string is a separate malloc block, and the array
+ * itself is a malloc block. You can free this type of
+ * string array with dbus_free_string_array().
+ *
+ * @param iter the iterator
+ * @param value return location for string values
+ * @param len return location for length of byte array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_string_array (DBusMessageIter *iter,
+                                   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_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 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.
+ *
+ * @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
- * @returns a new iter.
+ * @param _iter pointer to an iterator to initialize
  */
-DBusMessageIter *
-dbus_message_get_args_iter (DBusMessage *message)
+void
+dbus_message_append_iter_init (DBusMessage *message,
+                              DBusMessageIter *iter)
 {
-  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;
   
-  iter = dbus_new (DBusMessageIter, 1);
+  real->container_type = 0;
+  real->container_length_pos = 0;
+  real->wrote_dict_key = 0;
+}
 
-  if (iter != NULL)
-    {
-      dbus_message_ref (message);
+static void
+dbus_message_iter_append_check (DBusMessageRealIter *iter)
+{
+  _dbus_assert (!iter->message->locked);
   
-      iter->refcount = 1;
-      iter->message = message;
-      iter->pos = 0;
+  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 iter;
+  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;
 }
 
 /**
- * Increments the reference count of a DBusMessageIter.
+ * Appends a nil value to the message
  *
- * @param iter the message iter
- * @see dbus_message_iter_unref
+ * @param iter an iterator pointing to the end of the message
+ * @returns #TRUE on success
  */
-void
-dbus_message_iter_ref (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_nil (DBusMessageIter *iter)
 {
-  _dbus_assert (iter->refcount > 0);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
+    return FALSE;
+  
+  dbus_message_iter_append_done (real);
   
-  iter->refcount += 1;
+  return TRUE;
 }
 
 /**
- * Decrements the reference count of a DBusMessageIter.
+ * Appends a boolean value to the message
  *
- * @param iter The message iter
- * @see dbus_message_iter_ref
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
  */
-void
-dbus_message_iter_unref (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+                                 dbus_bool_t     value)
 {
-  _dbus_assert (iter->refcount > 0);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
 
-  iter->refcount -= 1;
+  dbus_message_iter_append_check (real);
 
-  if (iter->refcount == 0)
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+    return FALSE;
+  
+  if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
     {
-      dbus_message_unref (iter->message);
-
-      dbus_free (iter);
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
     }
+
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;
 }
 
 /**
- * Checks if an iterator has any more fields.
+ * Appends a byte to the message
  *
- * @param iter the message iter
- * @returns #TRUE if there are more fields
- * following
+ * @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_has_next (DBusMessageIter *iter)
+dbus_message_iter_append_byte (DBusMessageIter *iter,
+                              unsigned char    value)
 {
-  int end_pos;
-  
-  if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
-                                      iter->message->byte_order,
-                                      iter->pos, &end_pos))
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
     return FALSE;
   
-  if (end_pos >= _dbus_string_get_length (&iter->message->body))
-    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;  
+  return TRUE;
 }
 
+
 /**
- * Moves the iterator to the next field.
+ * Appends a 32 bit signed integer to the message.
  *
- * @param iter The message iter
- * @returns #TRUE if the iterator was moved to the next field
+ * @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_next (DBusMessageIter *iter)
+dbus_message_iter_append_int32   (DBusMessageIter *iter,
+                                 dbus_int32_t  value)
 {
-  int end_pos;
-  
-  if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
-                                      iter->message->byte_order,
-                                      iter->pos, &end_pos))
-    return FALSE;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
 
-  if (end_pos >= _dbus_string_get_length (&iter->message->body))
-    return FALSE;
+  dbus_message_iter_append_check (real);
 
-  iter->pos = end_pos;
+  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;
 }
 
 /**
- * Returns the argument type of the argument that the
- * message iterator points at.
+ * Appends a 32 bit unsigned integer to the message.
  *
- * @param iter the message iter
- * @returns the field type
+ * @param iter an iterator pointing to the end of the message
+ * @param value the integer value
+ * @returns #TRUE on success
  */
-int
-dbus_message_iter_get_arg_type (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_uint32 (DBusMessageIter *iter,
+                                dbus_uint32_t    value)
 {
-  const char *data;
-
-  if (iter->pos >= _dbus_string_get_length (&iter->message->body))
-    return DBUS_TYPE_INVALID;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
 
-  data = _dbus_string_get_const_data_len (&iter->message->body, iter->pos, 1);
+  dbus_message_iter_append_check (real);
 
-  if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
-    return *data;
+  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;
+    }
 
-  return DBUS_TYPE_INVALID;
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;
 }
 
 /**
- * Returns the string value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * a string value before using this function.
+ * Appends a double value to the message.
  *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the string
+ * @param iter an iterator pointing to the end of the message
+ * @param value the double value
+ * @returns #TRUE on success
  */
-char *
-dbus_message_iter_get_string (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_double (DBusMessageIter *iter,
+                                double           value)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
+  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;
+    }
 
-  return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
-                                 iter->pos + 1, NULL);
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;
 }
 
 /**
- * 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.
+ * Appends a UTF-8 string to the message.
  *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the string
+ * @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_get_boolean (DBusMessageIter *iter)
+dbus_message_iter_append_string (DBusMessageIter *iter,
+                                const char      *value)
 {
-  unsigned char value;
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
+    return FALSE;
   
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN);
+  if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
 
-  value = _dbus_string_get_byte (&iter->message->body, iter->pos + 1);
+  dbus_message_iter_append_done (real);
   
-  return value;
+  return TRUE;
 }
 
 /**
- * Returns the 32 bit signed integer value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * an integer value before using this function.
+ * Appends a named type data chunk to the message.
  *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the integer
+ * @param iter an iterator pointing to the end of the message
+ * @param name the name of the type
+ * @parame
+ * @returns #TRUE on success
  */
-int
-dbus_message_iter_get_int32 (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_named (DBusMessageIter      *iter,
+                               const char           *name,
+                               const unsigned char  *data,
+                               int                   len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32);
+  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 _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
-                               iter->pos + 1, NULL);
+  return TRUE;
 }
 
+
 /**
- * Returns the 32 bit unsigned integer value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * an unsigned integer value before using this function.
+ * Appends a dict key name to the message. The iterator used
+ * must point to a dict.
  *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the integer
+ * @param iter an iterator pointing to the end of the message
+ * @param value the string
+ * @returns #TRUE on success
  */
-int
-dbus_message_iter_get_uint32 (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_dict_key (DBusMessageIter *iter,
+                                  const char      *value)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32);
+  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;
+    }
   
-  return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
-                                iter->pos + 1, NULL);
+  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;
 }
 
 /**
- * Returns the double value that an iterator may point to.
- * Note that you need to check that the iterator points to
- * a string value before using this function.
+ * Appends an array to the message and initializes an iterator that
+ * can be used to append to the array.
  *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @returns the double
+ * @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
  */
-double
-dbus_message_iter_get_double (DBusMessageIter *iter)
+dbus_bool_t
+dbus_message_iter_append_array (DBusMessageIter      *iter,
+                               DBusMessageIter      *array_iter,
+                               int                   element_type)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE);
+  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 _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
-                                iter->pos + 1, NULL);
+  return TRUE;
 }
 
 /**
- * Returns the boolean array that the iterator may point to. Note that
- * you need to check that the iterator points to an array of the
- * correct type prior to using this function.
+ * Appends a dict to the message and initializes an iterator that
+ * can be used to append to the dict.
  *
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_boolean_array (DBusMessageIter   *iter,
-                                    unsigned char    **value,
-                                    int               *len)
+dbus_message_iter_append_dict (DBusMessageIter      *iter,
+                              DBusMessageIter      *dict_iter)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+  int len_pos;
 
-  if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
-                                  iter->pos + 1, NULL, value, len))
+  dbus_message_iter_append_check (real);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
     return FALSE;
-  else
-    return TRUE;
+
+  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;
 }
 
+
 /**
- * Returns the 32 bit signed integer array that the iterator may point
- * to. Note that you need to check that the iterator points to an
- * array of the correct type prior to using this function.
+ * Appends a boolean array to the message.
  *
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_int32_array  (DBusMessageIter *iter,
-                                   dbus_int32_t   **value,
-                                   int             *len)
+dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
+                                       unsigned const char *value,
+                                       int                  len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
 
-  if (!_dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
-                                   iter->pos + 1, NULL, value, len))
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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;
 }
 
 /**
- * Returns the 32 bit unsigned integer array that the iterator may point
- * to. Note that you need to check that the iterator points to an
- * array of the correct type prior to using this function.
+ * Appends a 32 bit signed integer array to the message.
  *
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_uint32_array  (DBusMessageIter *iter,
-                                    dbus_uint32_t  **value,
-                                    int             *len)
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
+                                     const dbus_int32_t *value,
+                                     int                 len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
 
-  if (!_dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
-                                    iter->pos + 1, NULL, value, len))
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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;
 }
 
 /**
- * Returns the double array that the iterator may point to. Note that
- * you need to check that the iterator points to an array of the
- * correct type prior to using this function.
+ * Appends a 32 bit unsigned integer array to the message.
  *
- * @param iter the iterator
- * @param value return location for the array
- * @param len return location for the array length
+ * @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_get_double_array  (DBusMessageIter *iter,
-                                    double         **value,
-                                    int             *len)
+dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
+                                      const dbus_uint32_t *value,
+                                      int                  len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
 
-  if (!_dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
-                                    iter->pos + 1, NULL, value, len))
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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;
 }
 
 /**
- * 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.
+ * Appends a double array to the message.
  *
- * @param iter the iterator
- * @param value return location for array values
- * @param len return location for length of byte array
+ * @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_get_byte_array (DBusMessageIter  *iter,
-                                 unsigned char   **value,
-                                  int              *len)
+dbus_message_iter_append_double_array (DBusMessageIter *iter,
+                                      const double    *value,
+                                      int              len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  dbus_message_iter_append_check (real);
 
-  if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
-                                  iter->pos + 1, NULL, value, len))
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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;
 }
 
 /**
- * Returns the string 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.
- *
- * The returned value is a #NULL-terminated array of strings.
- * Each string is a separate malloc block, and the array
- * itself is a malloc block. You can free this type of
- * string array with dbus_free_string_array().
+ * Appends a byte array to the message.
  *
- * @param iter the iterator
- * @param value return location for string values
- * @param len return location for length of byte array
+ * @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_get_string_array (DBusMessageIter *iter,
-                                   char          ***value,
-                                   int             *len)
+dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
+                                    unsigned const char *value,
+                                    int                  len)
 {
-  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
 
-  if (!_dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
-                                    iter->pos + 1, NULL, value, len))
+  dbus_message_iter_append_check (real);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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;
 }
 
 /**
- * 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.
+ * Appends a string array to the message.
  *
- * @param iter the iterator
- * @param dict return location for dict
+ * @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_get_dict (DBusMessageIter *iter,
-                           DBusDict       **dict)
+dbus_message_iter_append_string_array (DBusMessageIter *iter,
+                                      const char     **value,
+                                      int              len)
 {
-  _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_ARRAY))
     return FALSE;
-  else
-    return TRUE;
+  
+  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 */
index 4733786..6c82cf0 100644 (file)
@@ -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);
 
 
 
index c7eb737..651969c 100644 (file)
@@ -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
   
index b55cc89..b39b3a0 100644 (file)
@@ -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
index df921b1..bb47187 100644 (file)
@@ -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);
index 0c607ec..50a1c76 100644 (file)
@@ -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
index 19d6d7c..2d1b547 100644 (file)
@@ -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");
index 1128d36..025ccbb 100644 (file)
@@ -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>
index 3bd49ac..200ef43 100644 (file)
                 <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>
                 <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>
                   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>
index 0232b86..38926ef 100644 (file)
@@ -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);
        }
index 06f597d..367a2b3 100644 (file)
@@ -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;
index c97ef7a..71ac5ab 100644 (file)
@@ -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
index 54b31d6..c045b97 100644 (file)
@@ -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
index 0755ab5..00a2962 100644 (file)
@@ -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
index 2326ec9..07d4b34 100644 (file)
Binary files a/test/data/invalid-messages/boolean-array-length-too-long.message-raw and b/test/data/invalid-messages/boolean-array-length-too-long.message-raw differ
index cba9e83..11b15c8 100644 (file)
Binary files a/test/data/invalid-messages/boolean-has-no-value.message-raw and b/test/data/invalid-messages/boolean-has-no-value.message-raw 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 (file)
index 8f89960..0000000
+++ /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
index 6df40b3..1472202 100644 (file)
@@ -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
index 0de1a78..34fb47d 100644 (file)
@@ -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
index ce99a28..6b9d004 100644 (file)
@@ -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
index 36f3fc3..87196b1 100644 (file)
@@ -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
 
index cc9c5a7..6549646 100644 (file)
@@ -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
index ab5b5a8..b47dca7 100644 (file)
@@ -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 (file)
index 0000000..b760804
--- /dev/null
@@ -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
index a9a960a..56764de 100644 (file)
@@ -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))