]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
2004-05-28 Michael Meeks <michael@ximian.com>
authorMichael Meeks <michael@ximian.com>
Fri, 28 May 2004 13:10:36 +0000 (13:10 +0000)
committerMichael Meeks <michael@ximian.com>
Fri, 28 May 2004 13:10:36 +0000 (13:10 +0000)
* glib/dbus-gvalue.c (dbus_gvalue_marshal, dbus_gvalue_demarshal):
fix no int64 case.

* dbus/dbus-string.c (_dbus_string_parse_basic_type): impl.

* dbus/dbus-message.c (_dbus_message_iter_get_basic_type),
(_dbus_message_iter_get_basic_type_array): impl.
drastically simplify ~all relevant _get methods to use these.
(_dbus_message_iter_append_basic_array),
(dbus_message_iter_append_basic): impl
drastically simplify ~all relevant _append methods to use these.

* dbus/dbus-message-builder.c (parse_basic_type)
(parse_basic_array, lookup_basic_type): impl.
(_dbus_message_data_load): prune scads of duplicate /
cut & paste coding.

* dbus/dbus-marshal.c (_dbus_demarshal_basic_type_array)
(_dbus_demarshal_basic_type): implement,
(demarshal_and_validate_len/arg): beef up debug.
(_dbus_marshal_basic_type, _dbus_marshal_basic_type_array): impl.

ChangeLog
dbus/dbus-marshal.c
dbus/dbus-marshal.h
dbus/dbus-message-builder.c
dbus/dbus-message.c
dbus/dbus-string.c
dbus/dbus-string.h
glib/dbus-gvalue.c

index 2b2dbd7fca96bae333ac4590f70e07e30d4edfe2..3c5c97e4b06ca993e782059c89040cab52ab1673 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2004-05-28  Michael Meeks  <michael@ximian.com>
+
+       * glib/dbus-gvalue.c (dbus_gvalue_marshal, dbus_gvalue_demarshal): 
+       fix no int64 case.
+
+       * dbus/dbus-string.c (_dbus_string_parse_basic_type): impl.
+
+       * dbus/dbus-message.c (_dbus_message_iter_get_basic_type),
+       (_dbus_message_iter_get_basic_type_array): impl.
+       drastically simplify ~all relevant _get methods to use these.
+       (_dbus_message_iter_append_basic_array),
+       (dbus_message_iter_append_basic): impl
+       drastically simplify ~all relevant _append methods to use these.
+
+       * dbus/dbus-message-builder.c (parse_basic_type) 
+       (parse_basic_array, lookup_basic_type): impl.
+       (_dbus_message_data_load): prune scads of duplicate /
+       cut & paste coding.
+
+       * dbus/dbus-marshal.c (_dbus_demarshal_basic_type_array) 
+       (_dbus_demarshal_basic_type): implement,
+       (demarshal_and_validate_len/arg): beef up debug.
+       (_dbus_marshal_basic_type, _dbus_marshal_basic_type_array): impl.
+
 2004-05-27  Seth Nickell  <seth@gnome.org>
 
        * configure.in:
index 7524452bf5fa6f1f0bd894c2f143fbc9ffde883c..9856930f8509a80f00ae5a5419c3d717ab97ab17 100644 (file)
@@ -1067,6 +1067,61 @@ _dbus_demarshal_uint64  (const DBusString *str,
 
 #endif /* DBUS_HAVE_INT64 */
 
+/**
+ * Demarshals a basic type
+ *
+ * @param str the string containing the data
+ * @param type type of value to demarshal
+ * @param value pointer to return value data
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+void
+_dbus_demarshal_basic_type (const DBusString      *str,
+                           int                    type,
+                           void                  *value,
+                           int                    byte_order,
+                           int                   *pos)
+{
+  const char *str_data = _dbus_string_get_const_data (str);
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      *(unsigned char *) value = _dbus_string_get_byte (str, *pos);
+      (*pos)++;
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 4);
+      *(dbus_uint32_t *) value = *(dbus_uint32_t *)(str_data + *pos);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+       *(dbus_uint32_t *) value = DBUS_UINT32_SWAP_LE_BE (*(dbus_uint32_t *) value);
+      *pos += 4;
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      *pos = _DBUS_ALIGN_VALUE (*pos, 8);
+      memcpy (value, str_data + *pos, 8);
+      if (byte_order != DBUS_COMPILER_BYTE_ORDER)
+#ifdef DBUS_HAVE_INT64
+       *(dbus_uint64_t *) value = DBUS_UINT64_SWAP_LE_BE (*(dbus_uint64_t *) value);
+#else  
+       swap_bytes (value, 8);
+#endif
+      *pos += 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+}
+
 /**
  * Demarshals an UTF-8 string.
  *
@@ -1392,6 +1447,53 @@ _dbus_demarshal_double_array (const DBusString  *str,
                                    (DBusOctets8**) array, array_len);
 }
 
+
+/**
+ * Demarshals an array of basic types
+ *
+ * @param str the string containing the data
+ * @param element_type type of array elements to demarshal
+ * @param array pointer to pointer to array data
+ * @param array_len pointer to array length
+ * @param byte_order the byte order
+ * @param pos pointer to position in the string,
+ *            updated on return to new position
+ **/
+dbus_bool_t
+_dbus_demarshal_basic_type_array (const DBusString      *str,
+                                 int                    element_type,
+                                 void                 **array,
+                                 int                   *array_len,
+                                 int                    byte_order,
+                                 int                   *pos)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: do we want to post-normalize these ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_demarshal_byte_array (str, byte_order, *pos, pos,
+                                        (unsigned char **)array, array_len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return demarshal_4_octets_array (str, byte_order, *pos, pos,
+                                      (dbus_uint32_t *) array, array_len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return demarshal_8_octets_array (str, byte_order, *pos, pos,
+                                      (DBusOctets8**) array, array_len);
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+  return FALSE;
+}
+
 /**
  * Demarshals a string array.
  *
@@ -1725,7 +1827,7 @@ demarshal_and_validate_len (const DBusString *str,
   if (!_dbus_string_validate_nul (str, pos,
                                   align_4 - pos))
     {
-      _dbus_verbose ("array length alignment padding not initialized to nul\n");
+      _dbus_verbose ("array length alignment padding not initialized to nul at %d\n", pos);
       return -1;
     }
 
@@ -1740,8 +1842,8 @@ demarshal_and_validate_len (const DBusString *str,
 #define MAX_ARRAY_LENGTH (((unsigned int)_DBUS_INT_MAX) / 32)
   if (len > MAX_ARRAY_LENGTH)
     {
-      _dbus_verbose ("array length %u exceeds maximum of %u\n",
-                     len, MAX_ARRAY_LENGTH);
+      _dbus_verbose ("array length %u exceeds maximum of %u at pos %d\n",
+                     len, MAX_ARRAY_LENGTH, pos);
       return -1;
     }
   else
@@ -2021,7 +2123,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
         if (!_dbus_string_validate_nul (str, pos,
                                         align_8 - pos))
           {
-            _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul\n");
+            _dbus_verbose ("double/int64/uint64/objid alignment padding not initialized to nul at %d\n", pos);
             return FALSE;
           }
 
@@ -2191,7 +2293,10 @@ _dbus_marshal_validate_arg (const DBusString *str,
            /* Validate element */
            if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
                                             dict_type, -1, pos, &pos))
-             return FALSE;
+             {
+               _dbus_verbose ("dict arg invalid at offset %d\n", pos);
+               return FALSE;
+             }
          }
        
        if (pos > end)
@@ -2356,6 +2461,93 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
   _dbus_verbose_bytes (d, len);
 }
 
+/**
+ * Marshals a basic type
+ *
+ * @param str string to marshal to
+ * @param type type of value
+ * @param value pointer to value
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type (DBusString *str,
+                         char        type,
+                         void       *value,
+                         int         byte_order)
+{
+  dbus_bool_t retval;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      retval = _dbus_string_append_byte (str, *(unsigned char *)value);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets (str, byte_order, *(dbus_uint32_t *)value);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+      retval = _dbus_marshal_uint64 (str, byte_order, *(dbus_uint64_t *)value);
+      break;
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      retval = _dbus_marshal_double (str, byte_order, *(double *)value);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      retval = FALSE;
+      break;
+    }
+  return retval;
+}
+
+/**
+ * Marshals a basic type array
+ *
+ * @param str string to marshal to
+ * @param element_type type of array elements
+ * @param value pointer to value
+ * @param len length of value data in elements
+ * @param byte_order byte order
+ * @returns #TRUE on success
+ **/
+dbus_bool_t
+_dbus_marshal_basic_type_array (DBusString *str,
+                               char        element_type,
+                               const void *value,
+                               int         len,
+                               int         byte_order)
+{
+  switch (element_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      /* FIXME: we canonicalize to 0 or 1 for the single boolean case 
+       * should we here too ? */
+    case DBUS_TYPE_BYTE:
+      return _dbus_marshal_byte_array (str, byte_order, value, len);
+      break;
+    case DBUS_TYPE_INT32:
+    case DBUS_TYPE_UINT32:
+      return marshal_4_octets_array (str, byte_order, value, len);
+      break;
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      return marshal_8_octets_array (str, byte_order, value, len);
+      break;
+    default:
+      _dbus_assert_not_reached ("non basic type in array");
+      break;
+    }
+  return FALSE;
+}
+
 /** @} */
 
 #ifdef DBUS_BUILD_TESTS
index b1b8e2c9d67fd34241095fb62fbb56ee015d0011..1c34c531deaf2f6d4365763db70b907e7cce4b0c 100644 (file)
@@ -184,6 +184,10 @@ dbus_bool_t   _dbus_marshal_double         (DBusString            *str,
 dbus_bool_t   _dbus_marshal_string         (DBusString            *str,
                                            int                    byte_order,
                                            const char            *value);
+dbus_bool_t   _dbus_marshal_basic_type     (DBusString            *str,
+                                           char                   type,
+                                           void                  *value,
+                                           int                    byte_order);
 dbus_bool_t   _dbus_marshal_byte_array     (DBusString            *str,
                                            int                    byte_order,
                                            const unsigned char   *value,
@@ -210,6 +214,12 @@ dbus_bool_t   _dbus_marshal_double_array   (DBusString            *str,
                                            int                    byte_order,
                                            const double          *value,
                                            int                    len);
+dbus_bool_t   _dbus_marshal_basic_type_array (DBusString            *str,
+                                             char                   element_type,
+                                             const void            *value,
+                                             int                    len,
+                                             int                    byte_order);
+
 dbus_bool_t   _dbus_marshal_string_array   (DBusString            *str,
                                            int                    byte_order,
                                            const char           **value,
@@ -241,6 +251,11 @@ dbus_uint64_t _dbus_demarshal_uint64       (const DBusString      *str,
                                            int                    pos,
                                            int                   *new_pos);
 #endif /* DBUS_HAVE_INT64 */
+void          _dbus_demarshal_basic_type   (const DBusString      *str,
+                                           int                    type,
+                                           void                  *value,
+                                           int                    byte_order,
+                                           int                   *pos);
 char *        _dbus_demarshal_string       (const DBusString      *str,
                                            int                    byte_order,
                                            int                    pos,
@@ -283,6 +298,13 @@ dbus_bool_t   _dbus_demarshal_double_array (const DBusString      *str,
                                            int                   *new_pos,
                                            double               **array,
                                            int                   *array_len);
+dbus_bool_t   _dbus_demarshal_basic_type_array (const DBusString      *str,
+                                               int                    type,
+                                               void                 **array,
+                                               int                   *array_len,
+                                               int                    byte_order,
+                                               int                   *pos);
+
 dbus_bool_t   _dbus_demarshal_string_array (const DBusString      *str,
                                            int                    byte_order,
                                            int                    pos,
index 00941e9cf0bc8826c39e36b700121f8d5cd36131..2ff13b21a5ca47fe5643e94d3e6aafd52af81b03 100644 (file)
@@ -335,6 +335,193 @@ append_string_field (DBusString *dest,
   return TRUE;
 }
 
+static dbus_bool_t
+parse_basic_type (DBusString *src, char type,
+                 DBusString *dest, dbus_bool_t *unalign,
+                 int endian)
+{
+  int align;
+  int align_pad_start, align_pad_end;
+  unsigned char data[16];
+
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      align = 1;
+      break;
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT32:
+      align = 4;
+      break;
+    case DBUS_TYPE_DOUBLE:
+      align = 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+
+  align_pad_start = _dbus_string_get_length (dest);
+  align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, align);
+
+  _dbus_string_delete_first_word (src);
+
+  if (!_dbus_string_parse_basic_type (src, type, 0, data, NULL))
+    {
+      _dbus_verbose ("failed to parse type '%c'", type);
+      return FALSE;
+    }
+
+  if (!_dbus_marshal_basic_type (dest, type, data, endian))
+    {
+      _dbus_verbose ("failed to marshal type '%c'", type);
+      return FALSE;
+    }
+
+  if (*unalign)
+    {
+      _dbus_string_delete (dest, align_pad_start,
+                           align_pad_end - align_pad_start);
+      *unalign = FALSE;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+parse_basic_array (DBusString *src, char type,
+                  DBusString *dest, dbus_bool_t *unalign,
+                  int endian)
+{
+  int array_align, elem_size;
+  int i, len, allocated;
+  unsigned char *values, b;
+  int values_offset;
+  int align_pad_start, align_pad_end;
+  dbus_bool_t retval = FALSE;
+
+  array_align = 4; /* length */
+  switch (type)
+    {
+    case DBUS_TYPE_BYTE:
+    case DBUS_TYPE_BOOLEAN:
+      elem_size = 1;
+      break;
+    case DBUS_TYPE_UINT32:
+    case DBUS_TYPE_INT32:
+      elem_size = 4;
+      break;
+    case DBUS_TYPE_DOUBLE:
+      array_align = 8;
+      elem_size = 8;
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+
+  align_pad_start = _dbus_string_get_length (dest);
+  align_pad_end = _DBUS_ALIGN_VALUE (align_pad_start, array_align);
+
+  len = 0;
+  allocated = 2;
+  values = NULL;
+  values_offset = 0;
+         
+  _dbus_string_delete_first_word (src);
+  _dbus_string_skip_blank (src, 0, &i);
+  b = _dbus_string_get_byte (src, i++);
+
+  if (b != '{')
+    goto failed;
+
+  while (i < _dbus_string_get_length (src))
+    {
+      _dbus_string_skip_blank (src, i, &i);
+
+      if (!values || len == allocated - 1)
+       {
+         allocated *= 2;
+         values = dbus_realloc (values, allocated * elem_size);
+         if (!values)
+           {
+             _dbus_warn ("could not allocate memory for '%c' ARRAY\n", type);
+             goto failed;
+           }
+       }
+
+      if (!_dbus_string_parse_basic_type (src, type, i, values + values_offset, &i))
+       {
+         _dbus_warn ("could not parse integer element %d of '%c' ARRAY\n", len, type);
+         goto failed;
+       }
+
+      values_offset += elem_size;
+      len++;
+             
+      _dbus_string_skip_blank (src, i, &i);
+
+      b = _dbus_string_get_byte (src, i++);
+
+      if (b == '}')
+       break;
+      else if (b != ',')
+       goto failed;
+    }
+
+  if (!_dbus_marshal_basic_type_array (dest, type, values, len, endian))
+    {
+      _dbus_warn ("failed to append '%c' ARRAY\n", type);
+      goto failed;
+    }
+
+  if (*unalign)
+    {
+      _dbus_string_delete (dest, align_pad_start,
+                           align_pad_end - align_pad_start);
+      *unalign = FALSE;
+    }
+
+  retval = TRUE;
+
+ failed:
+  dbus_free (values);
+  return retval;
+}
+
+static char
+lookup_basic_type (const DBusString *str, dbus_bool_t *is_array)
+{
+  int i;
+  char type = DBUS_TYPE_INVALID;
+  static struct {
+    const char *name;
+    char        type;
+  } name_to_type[] = {
+    { "BYTE",    DBUS_TYPE_BYTE },
+    { "BOOLEAN", DBUS_TYPE_BOOLEAN },
+    { "INT32",   DBUS_TYPE_INT32 },
+    { "UINT32",  DBUS_TYPE_UINT32 },
+    { "DOUBLE",  DBUS_TYPE_DOUBLE }
+  };
+
+  for (i = 0; i < _DBUS_N_ELEMENTS(name_to_type); i++)
+    {
+      const char *name = name_to_type[i].name;
+      if (_dbus_string_starts_with_c_str (str, name)) 
+       {
+         int offset = strlen (name);
+         type = name_to_type[i].type;
+         if (is_array)
+           *is_array = _dbus_string_find (str, offset, "_ARRAY", NULL);
+         break;
+       }
+    }
+
+  return type;
+}
+
 /**
  * Reads the given filename, which should be in "message description
  * language" (look at some examples), and builds up the message data
@@ -399,6 +586,8 @@ _dbus_message_data_load (DBusString       *dest,
   DBusHashTable *length_hash;
   int endian;
   DBusHashIter iter;
+  char type;
+  dbus_bool_t is_array;
   
   retval = FALSE;
   length_hash = NULL;
@@ -510,7 +699,7 @@ _dbus_message_data_load (DBusString       *dest,
             goto parse_failed;
           
           /* client serial */
-          if (!_dbus_marshal_int32 (dest, endian, 1))
+          if (!_dbus_marshal_uint32 (dest, endian, 1))
             {
               _dbus_warn ("couldn't append client serial\n");
               goto parse_failed;
@@ -721,16 +910,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, "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"))
-            code = DBUS_TYPE_INT32;
-          else if (_dbus_string_starts_with_c_str (&line, "UINT32"))
-            code = DBUS_TYPE_UINT32;
-          else if (_dbus_string_starts_with_c_str (&line, "DOUBLE"))
-            code = DBUS_TYPE_DOUBLE;
+         else if ((code = lookup_basic_type (&line, NULL)) != DBUS_TYPE_INVALID)
+           ;
           else if (_dbus_string_starts_with_c_str (&line, "STRING"))
             code = DBUS_TYPE_STRING;
           else if (_dbus_string_starts_with_c_str (&line, "OBJECT_PATH"))
@@ -753,380 +934,6 @@ _dbus_message_data_load (DBusString       *dest,
               goto parse_failed;
             }
         }
-      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 BYTE_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);
-         int i, len, allocated;
-         unsigned char *values;
-         unsigned char b, val;
-
-         allocated = 4;
-         values = dbus_new (unsigned char, allocated);
-         if (!values)
-           {
-             _dbus_warn ("could not allocate memory for BOOLEAN_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_find_to (&line, i, i + 5,
-                                       "false", NULL))
-               {
-                 i += 5;
-                 val = TRUE;
-               }
-             else if (_dbus_string_find_to (&line, i, i + 4,
-                                            "true", NULL))
-               {
-                 i += 4;
-                 val = FALSE;
-               }
-             else
-               {
-                 _dbus_warn ("could not parse BOOLEAN_ARRAY\n");
-                 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 BOOLEAN_ARRAY\n");
-              goto parse_failed;
-            }
-         dbus_free (values);
-         
-         PERFORM_UNALIGN (dest);
-       }
-      else if (_dbus_string_starts_with_c_str (&line,
-                                              "INT32_ARRAY"))
-       {
-         SAVE_FOR_UNALIGN (dest, 4);
-         int i, len, allocated;
-         dbus_int32_t *values;
-         long val;
-         unsigned char b;
-
-         allocated = 4;
-         values = dbus_new (dbus_int32_t, allocated);
-         if (!values)
-           {
-             _dbus_warn ("could not allocate memory for INT32_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_parse_int (&line, i, &val, &i))
-               {
-                 _dbus_warn ("could not parse integer for INT32_ARRAY\n");
-                 goto parse_failed;
-               }
-
-             values[len++] = val;
-             if (len == allocated)
-               {
-                 allocated *= 2;
-                 values = dbus_realloc (values, allocated * sizeof (dbus_int32_t));
-                 if (!values)
-                   {
-                     _dbus_warn ("could not allocate memory for INT32_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_array (dest, endian, values, len))
-            {
-              _dbus_warn ("failed to append INT32_ARRAY\n");
-              goto parse_failed;
-            }
-         dbus_free (values);
-         
-         PERFORM_UNALIGN (dest);
-       }
-      else if (_dbus_string_starts_with_c_str (&line,
-                                              "UINT32_ARRAY"))
-       {
-         SAVE_FOR_UNALIGN (dest, 4);
-         int i, len, allocated;
-         dbus_uint32_t *values;
-         long val;
-         unsigned char b;
-
-         allocated = 4;
-         values = dbus_new (dbus_uint32_t, allocated);
-         if (!values)
-           {
-             _dbus_warn ("could not allocate memory for UINT32_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_parse_int (&line, i, &val, &i))
-               {
-                 _dbus_warn ("could not parse integer for UINT32_ARRAY\n");
-                 goto parse_failed;
-               }
-
-             values[len++] = val;
-             if (len == allocated)
-               {
-                 allocated *= 2;
-                 values = dbus_realloc (values, allocated * sizeof (dbus_uint32_t));
-                 if (!values)
-                   {
-                     _dbus_warn ("could not allocate memory for UINT32_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_uint32_array (dest, endian, values, len))
-            {
-              _dbus_warn ("failed to append UINT32_ARRAY\n");
-              goto parse_failed;
-            }
-         dbus_free (values);
-         
-         PERFORM_UNALIGN (dest);
-       }
-      else if (_dbus_string_starts_with_c_str (&line,
-                                              "DOUBLE_ARRAY"))
-       {
-         SAVE_FOR_UNALIGN (dest, 8);
-         int i, len, allocated;
-         double *values;
-         double val;
-         unsigned char b;
-
-         allocated = 4;
-         values = dbus_new (double, allocated);
-         if (!values)
-           {
-             _dbus_warn ("could not allocate memory for DOUBLE_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_parse_double (&line, i, &val, &i))
-               {
-                 _dbus_warn ("could not parse double for DOUBLE_ARRAY\n");
-                 goto parse_failed;
-               }
-
-             values[len++] = val;
-             if (len == allocated)
-               {
-                 allocated *= 2;
-                 values = dbus_realloc (values, allocated * sizeof (double));
-                 if (!values)
-                   {
-                     _dbus_warn ("could not allocate memory for DOUBLE_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_double_array (dest, endian, values, len))
-            {
-              _dbus_warn ("failed to append DOUBLE_ARRAY\n");
-              goto parse_failed;
-            }
-         dbus_free (values);
-         
-         PERFORM_UNALIGN (dest);
-       }
       else if (_dbus_string_starts_with_c_str (&line,
                                               "STRING_ARRAY"))
        {
@@ -1209,124 +1016,6 @@ _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"))
-       {
-         unsigned char val;
-
-         _dbus_string_delete_first_word (&line);
-
-         if (_dbus_string_starts_with_c_str (&line, "true"))
-           val = TRUE;
-         else if (_dbus_string_starts_with_c_str (&line, "false"))
-           val = FALSE;
-         else
-           {
-             _dbus_warn ("could not parse BOOLEAN\n");
-             goto parse_failed;
-           }
-         if (!_dbus_string_append_byte (dest, val))
-            {
-              _dbus_warn ("failed to append BOOLEAN\n");
-              goto parse_failed;
-            }
-       }
-      
-      else if (_dbus_string_starts_with_c_str (&line,
-                                               "INT32"))
-        {
-          SAVE_FOR_UNALIGN (dest, 4);
-          long val;
-          
-          _dbus_string_delete_first_word (&line);
-
-          if (!_dbus_string_parse_int (&line, 0, &val, NULL))
-            {
-              _dbus_warn ("could not parse integer for INT32\n");
-              goto parse_failed;
-            }
-          
-          if (!_dbus_marshal_int32 (dest, endian,
-                                    val))
-            {
-              _dbus_warn ("failed to append INT32\n");
-              goto parse_failed;
-            }
-
-          PERFORM_UNALIGN (dest);
-        }
-      else if (_dbus_string_starts_with_c_str (&line,
-                                               "UINT32"))
-        {
-          SAVE_FOR_UNALIGN (dest, 4);
-          unsigned long val;
-          
-          _dbus_string_delete_first_word (&line);
-
-          if (!_dbus_string_parse_uint (&line, 0, &val, NULL))
-            goto parse_failed;
-          
-          if (!_dbus_marshal_uint32 (dest, endian,
-                                     val))
-            {
-              _dbus_warn ("failed to append UINT32\n");
-              goto parse_failed;
-            }
-
-          PERFORM_UNALIGN (dest);
-        }
-      else if (_dbus_string_starts_with_c_str (&line,
-                                               "DOUBLE"))
-        {
-          SAVE_FOR_UNALIGN (dest, 8);
-          double val;
-          
-          _dbus_string_delete_first_word (&line);
-
-          if (!_dbus_string_parse_double (&line, 0, &val, NULL))
-            goto parse_failed;
-          
-          if (!_dbus_marshal_double (dest, endian,
-                                     val))
-            {
-              _dbus_warn ("failed to append DOUBLE\n");
-              goto parse_failed;
-            }
-
-          PERFORM_UNALIGN (dest);
-        }
       else if (_dbus_string_starts_with_c_str (&line,
                                                "STRING"))
         {
@@ -1357,8 +1046,21 @@ _dbus_message_data_load (DBusString       *dest,
           
           PERFORM_UNALIGN (dest);
         }
+      else if ((type = lookup_basic_type (&line, &is_array)) != DBUS_TYPE_INVALID)
+       {
+         if (is_array)
+           {
+             if (!parse_basic_array (&line, type, dest, &unalign, endian))
+               goto parse_failed;
+           }
+         else
+           {
+             if (!parse_basic_type (&line, type, dest, &unalign, endian))
+               goto parse_failed;
+           }
+        }
       else if (_dbus_string_starts_with_c_str (&line,
-                                               "OBJECT_PATH"))
+                                              "OBJECT_PATH"))
         {
           SAVE_FOR_UNALIGN (dest, 4);
           int size_offset;
index 98c0d1d1740b337242fcde556febc2407eec96fa..9fa19668106f810f7fd0595c0d1bc9d8e6c68959 100644 (file)
@@ -1884,521 +1884,94 @@ dbus_message_append_args (DBusMessage *message,
 }
 
 /**
- * This function takes a va_list for use by language bindings.
- * It's otherwise the same as dbus_message_append_args().
- *
- * @todo: Shouldn't this function clean up the changes to the message
- *        on failures? (Yes)
-  
- * @see dbus_message_append_args.  
- * @param message the message
- * @param first_arg_type type of first argument
- * @param var_args value of first argument, then list of type/value pairs
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_append_args_valist (DBusMessage *message,
-                                int          first_arg_type,
-                                va_list      var_args)
-{
-  int type, old_len;
-  DBusMessageIter iter;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  
-  old_len = _dbus_string_get_length (&message->body);
-  
-  type = first_arg_type;
-
-  dbus_message_append_iter_init (message, &iter);
-  
-  while (type != DBUS_TYPE_INVALID)
-    {
-      switch (type)
-       {
-       case DBUS_TYPE_NIL:
-         if (!dbus_message_iter_append_nil (&iter))
-           goto errorout;
-         break;
-       case DBUS_TYPE_BYTE:
-         if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_BOOLEAN:
-         if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_INT32:
-         if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_UINT32:
-         if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
-           goto errorout;          
-         break;
-#ifdef DBUS_HAVE_INT64
-        case DBUS_TYPE_INT64:
-         if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_UINT64:
-         if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
-           goto errorout;          
-         break;
-#endif /* DBUS_HAVE_INT64 */
-       case DBUS_TYPE_DOUBLE:
-         if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
-           goto errorout;
-         break;
-       case DBUS_TYPE_STRING:
-         if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
-           goto errorout;
-         break;
-        case DBUS_TYPE_OBJECT_PATH:
-         if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
-           goto errorout;
-          break;
-       case DBUS_TYPE_CUSTOM:
-         {
-           const char *name;
-           unsigned char *data;
-           int len;
-           name = va_arg (var_args, const char *);
-           data = va_arg (var_args, unsigned char *);
-           len = va_arg (var_args, int);
-
-           if (!dbus_message_iter_append_custom (&iter, name, data, len))
-             goto errorout;
-           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);
-
-           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;
-#ifdef DBUS_HAVE_INT64
-              case DBUS_TYPE_INT64:
-               if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_UINT64:
-               if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
-                 goto errorout;
-               break;
-#endif /* DBUS_HAVE_INT64 */
-             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_OBJECT_PATH:
-               if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
-                 goto errorout;
-               break;
-             case DBUS_TYPE_NIL:
-             case DBUS_TYPE_ARRAY:
-             case DBUS_TYPE_CUSTOM:
-             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:
-         _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);
-    }
-
-  return TRUE;
-
- errorout:
-  return FALSE;
-}
-
-
-/**
- * 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 #DBUS_TYPE_INVALID.
- *
- * @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
- */
-dbus_bool_t
-dbus_message_get_args (DBusMessage     *message,
-                       DBusError       *error,
-                      int              first_arg_type,
-                      ...)
-{
-  dbus_bool_t retval;
-  va_list var_args;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-  
-  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 retval;
-}
-
-/**
- * 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 error error to be filled in
- * @param first_arg_type type of the first argument
- * @param var_args return location for first argument, followed by list of type/location pairs
- * @returns #FALSE if error was set
- */
-dbus_bool_t
-dbus_message_get_args_valist (DBusMessage     *message,
-                              DBusError       *error,
-                             int              first_arg_type,
-                             va_list          var_args)
-{
-  DBusMessageIter iter;
-
-  _dbus_return_val_if_fail (message != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-  
-  dbus_message_iter_init (message, &iter);
-  return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
-}
-
-/**
- * Gets arguments from a message 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 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_iter_get_args (DBusMessageIter *iter,
-                           DBusError       *error,
-                           int              first_arg_type,
-                           ...)
-{
-  dbus_bool_t retval;
-  va_list var_args;
-
-  _dbus_return_val_if_fail (iter != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, 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 retval;
-}
-
-/**
- * This function takes a va_list for use by language bindings
- *
- * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
- * only if #DBUS_HAVE_INT64 is defined.
- *
- * @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_iter_get_args_valist (DBusMessageIter *iter,
-                                  DBusError       *error,
-                                  int              first_arg_type,
-                                  va_list          var_args)
-{
-  int spec_type, msg_type, i;
-  dbus_bool_t retval;
-
-  _dbus_return_val_if_fail (iter != NULL, FALSE);
-  _dbus_return_val_if_error_is_set (error, FALSE);
-
-  retval = FALSE;
-  
-  spec_type = first_arg_type;
-  i = 0;
-  
-  while (spec_type != DBUS_TYPE_INVALID)
-    {
-      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));
-
-          goto out;
-       }
-
-      switch (spec_type)
-       {
-       case DBUS_TYPE_NIL:
-         break;
-       case DBUS_TYPE_BYTE:
-         {
-           unsigned char *ptr;
-
-           ptr = va_arg (var_args, unsigned char *);
-
-           *ptr = dbus_message_iter_get_byte (iter);
-           break;
-         }
-       case DBUS_TYPE_BOOLEAN:
-         {
-           dbus_bool_t *ptr;
-
-           ptr = va_arg (var_args, dbus_bool_t *);
-
-           *ptr = dbus_message_iter_get_boolean (iter);
-           break;
-         }
-       case DBUS_TYPE_INT32:
-         {
-           dbus_int32_t *ptr;
-
-           ptr = va_arg (var_args, dbus_int32_t *);
-
-           *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;
-         }
-#ifdef DBUS_HAVE_INT64
-       case DBUS_TYPE_INT64:
-         {
-           dbus_int64_t *ptr;
-
-           ptr = va_arg (var_args, dbus_int64_t *);
-
-           *ptr = dbus_message_iter_get_int64 (iter);
-           break;
-         }
-       case DBUS_TYPE_UINT64:
-         {
-           dbus_uint64_t *ptr;
-
-           ptr = va_arg (var_args, dbus_uint64_t *);
-
-           *ptr = dbus_message_iter_get_uint64 (iter);
-           break;
-         }
-#endif /* DBUS_HAVE_INT64 */
-          
-       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_CUSTOM:
-         {
-           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 *);
-
-           if (!dbus_message_iter_get_custom (iter, name, data, len))
-             {
-                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-               goto out;
-             }
-         }
-         break;
-       case DBUS_TYPE_ARRAY:
-         {
-           void **data;
-           int *len, type;
-           dbus_bool_t err = FALSE;
-           type = va_arg (var_args, int);
-           data = va_arg (var_args, void *);
-           len = va_arg (var_args, int *);
-
-            _dbus_return_val_if_fail (data != NULL, FALSE);
-            _dbus_return_val_if_fail (len != NULL, FALSE);
-            
-           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:
-               err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
-               break;
-             case DBUS_TYPE_BOOLEAN:
-               err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
-               break;
-             case DBUS_TYPE_INT32:
-               err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
-               break;
-             case DBUS_TYPE_UINT32:
-               err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
-               break;
-#ifdef DBUS_HAVE_INT64
-              case DBUS_TYPE_INT64:
-               err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
-               break;
-             case DBUS_TYPE_UINT64:
-               err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
-               break;
-#endif /* DBUS_HAVE_INT64 */
-             case DBUS_TYPE_DOUBLE:
-               err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
-               break;
-             case DBUS_TYPE_STRING:
-               err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
-               break;
-             case DBUS_TYPE_NIL:
-             case DBUS_TYPE_ARRAY:
-             case DBUS_TYPE_CUSTOM:
-             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;
-             }
-           if (err)
-             {
-               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 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 (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
-        {
-          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
-                          "Message has only %d arguments, but more were expected", i);
-          goto out;
-        }
+ * 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 #DBUS_TYPE_INVALID.
+ *
+ * @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
+ */
+dbus_bool_t
+dbus_message_get_args (DBusMessage     *message,
+                       DBusError       *error,
+                      int              first_arg_type,
+                      ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
 
-      i++;
-    }
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
   
-  retval = TRUE;
+  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 retval;
+}
+
+/**
+ * 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 error error to be filled in
+ * @param first_arg_type type of the first argument
+ * @param var_args return location for first argument, followed by list of type/location pairs
+ * @returns #FALSE if error was set
+ */
+dbus_bool_t
+dbus_message_get_args_valist (DBusMessage     *message,
+                              DBusError       *error,
+                             int              first_arg_type,
+                             va_list          var_args)
+{
+  DBusMessageIter iter;
+
+  _dbus_return_val_if_fail (message != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
   
- out:
+  dbus_message_iter_init (message, &iter);
+  return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
+}
+
+/**
+ * Gets arguments from a message 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 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_iter_get_args (DBusMessageIter *iter,
+                           DBusError       *error,
+                           int              first_arg_type,
+                           ...)
+{
+  dbus_bool_t retval;
+  va_list var_args;
+
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, 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 retval;
 }
 
-
 /**
  * Initializes a DBusMessageIter representing the arguments of the
  * message passed in.
@@ -2731,61 +2304,295 @@ dbus_message_iter_get_object_path (DBusMessageIter  *iter)
   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
   int type, pos;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
+  _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
+
+  return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+                                 pos, NULL);
+}
+
+/**
+ * Returns the name and data from a custom type that an iterator may
+ * point to. Note that you need to check that the iterator points to a
+ * custom type before using this function.
+ *
+ * @see dbus_message_iter_get_arg_type
+ * @param iter the message iter
+ * @param name return location for the name of the custom type
+ * @param value return location for data
+ * @param len return location for length of data
+ * @returns TRUE if get succeed
+ * 
+ */
+dbus_bool_t
+dbus_message_iter_get_custom (DBusMessageIter   *iter,
+                              char             **name,
+                              unsigned char    **value,
+                              int               *len)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int type, pos;
+  char *_name;
+
+  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_CUSTOM);
+  
+  _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+                                 pos, &pos);
+
+  if (_name == NULL)
+    return FALSE;
+  
+  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
+                                  pos, NULL, value, len))
+    {
+      dbus_free (_name);
+      return FALSE;
+    }
+
+  *name = _name;
+  
+  return TRUE;
+}
+
+static void
+_dbus_message_iter_get_basic_type (DBusMessageIter *iter,
+                                  char             type,
+                                  void            *value)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int item_type, pos;
+
+  _dbus_return_if_fail (dbus_message_iter_check (real));
+
+  pos = dbus_message_iter_get_data_start (real, &item_type);
+  
+  _dbus_assert (type == item_type);
+  
+  _dbus_demarshal_basic_type (&real->message->body,
+                             type, value,
+                             real->message->byte_order,
+                             &pos);
+}
+
+
+/**
+ * This function takes a va_list for use by language bindings
+ *
+ * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
+ * only if #DBUS_HAVE_INT64 is defined.
+ *
+ * @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_iter_get_args_valist (DBusMessageIter *iter,
+                                  DBusError       *error,
+                                  int              first_arg_type,
+                                  va_list          var_args)
+{
+  int spec_type, msg_type, i;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (iter != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  retval = FALSE;
+  
+  spec_type = first_arg_type;
+  i = 0;
+  
+  while (spec_type != DBUS_TYPE_INVALID)
+    {
+      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));
+
+          goto out;
+       }
+
+      switch (spec_type)
+       {
+       case DBUS_TYPE_NIL:
+         break;
+       case DBUS_TYPE_BOOLEAN:
+         {
+           dbus_bool_t *ptr;
+
+           ptr = va_arg (var_args, dbus_bool_t *);
+
+           *ptr = dbus_message_iter_get_boolean (iter);
+           break;
+         }
+       case DBUS_TYPE_BYTE:
+       case DBUS_TYPE_INT32:
+       case DBUS_TYPE_UINT32:
+#ifdef DBUS_HAVE_INT64
+       case DBUS_TYPE_INT64:
+       case DBUS_TYPE_UINT64:
+#endif /* DBUS_HAVE_INT64 */
+       case DBUS_TYPE_DOUBLE:
+         {
+           void *ptr = va_arg (var_args, void *);
+           _dbus_message_iter_get_basic_type (iter, spec_type, ptr);
+           break;
+         }
+
+       case DBUS_TYPE_STRING:
+         {
+           char **ptr;
+
+           ptr = va_arg (var_args, char **);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
+           *ptr = dbus_message_iter_get_string (iter);
 
-  return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
-                                 pos, NULL);
-}
+           if (!*ptr)
+              {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+                goto out;
+              }
+           
+           break;
+         }
 
-/**
- * Returns the name and data from a custom type that an iterator may
- * point to. Note that you need to check that the iterator points to a
- * custom type before using this function.
- *
- * @see dbus_message_iter_get_arg_type
- * @param iter the message iter
- * @param name return location for the name of the custom type
- * @param value return location for data
- * @param len return location for length of data
- * @returns TRUE if get succeed
- * 
- */
-dbus_bool_t
-dbus_message_iter_get_custom (DBusMessageIter   *iter,
-                              char             **name,
-                              unsigned char    **value,
-                              int               *len)
-{
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-  char *_name;
+       case DBUS_TYPE_CUSTOM:
+         {
+           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 *);
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+           if (!dbus_message_iter_get_custom (iter, name, data, len))
+             {
+                dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+               goto out;
+             }
+         }
+         break;
+       case DBUS_TYPE_ARRAY:
+         {
+           void **data;
+           int *len, type;
+           dbus_bool_t err = FALSE;
+           type = va_arg (var_args, int);
+           data = va_arg (var_args, void *);
+           len = va_arg (var_args, int *);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_CUSTOM);
-  
-  _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
-                                 pos, &pos);
+            _dbus_return_val_if_fail (data != NULL, FALSE);
+            _dbus_return_val_if_fail (len != NULL, FALSE);
+            
+           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:
+               err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
+               break;
+             case DBUS_TYPE_BOOLEAN:
+               err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
+               break;
+             case DBUS_TYPE_INT32:
+               err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
+               break;
+             case DBUS_TYPE_UINT32:
+               err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
+               break;
+#ifdef DBUS_HAVE_INT64
+              case DBUS_TYPE_INT64:
+               err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
+               break;
+             case DBUS_TYPE_UINT64:
+               err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
+               break;
+#endif /* DBUS_HAVE_INT64 */
+             case DBUS_TYPE_DOUBLE:
+               err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
+               break;
+             case DBUS_TYPE_STRING:
+               err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
+               break;
+             case DBUS_TYPE_NIL:
+             case DBUS_TYPE_ARRAY:
+             case DBUS_TYPE_CUSTOM:
+             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;
+             }
+           if (err)
+             {
+               dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 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;
+       }
 
-  if (_name == NULL)
-    return FALSE;
-  
-  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
-                                  pos, NULL, value, len))
-    {
-      dbus_free (_name);
-      return FALSE;
-    }
+      spec_type = va_arg (var_args, int);
+      if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
+        {
+          dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+                          "Message has only %d arguments, but more were expected", i);
+          goto out;
+        }
 
-  *name = _name;
+      i++;
+    }
   
-  return TRUE;
+  retval = TRUE;
+  
+ out:
+  
+  return retval;
 }
 
 /**
@@ -2800,22 +2607,13 @@ dbus_message_iter_get_custom (DBusMessageIter   *iter,
 unsigned char
 dbus_message_iter_get_byte (DBusMessageIter *iter)
 {
-  unsigned char value;
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  unsigned char value = 0;
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_BYTE);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BYTE, &value);
 
-  value = _dbus_string_get_byte (&real->message->body, pos);
-  
   return value;
 }
 
-
 /**
  * Returns the boolean value that an iterator may point to.
  * Note that you need to check that the iterator points to
@@ -2828,19 +2626,11 @@ dbus_message_iter_get_byte (DBusMessageIter *iter)
 dbus_bool_t
 dbus_message_iter_get_boolean (DBusMessageIter *iter)
 {
-  unsigned char value;
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+  unsigned char value = 0;
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_BOOLEAN);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_BOOLEAN, &value);
 
-  value = _dbus_string_get_byte (&real->message->body, pos);
-  
-  return value;
+  return (value != FALSE);
 }
 
 /**
@@ -2855,17 +2645,11 @@ dbus_message_iter_get_boolean (DBusMessageIter *iter)
 dbus_int32_t
 dbus_message_iter_get_int32 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int32_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT32, &value);
 
-  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);
+  return value;
 }
 
 /**
@@ -2880,17 +2664,11 @@ dbus_message_iter_get_int32 (DBusMessageIter *iter)
 dbus_uint32_t
 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int32_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT32, &value);
 
-  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);
+  return value;
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -2909,17 +2687,11 @@ dbus_message_iter_get_uint32 (DBusMessageIter *iter)
 dbus_int64_t
 dbus_message_iter_get_int64 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_int64_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_INT64, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_INT64);
-  
-  return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
-                               pos, NULL);
+  return value;
 }
 
 /**
@@ -2936,17 +2708,11 @@ dbus_message_iter_get_int64 (DBusMessageIter *iter)
 dbus_uint64_t
 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  dbus_uint64_t value = 0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_UINT64, &value);
 
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_UINT64);
-  
-  return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
-                                pos, NULL);
+  return value;
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -2963,17 +2729,11 @@ dbus_message_iter_get_uint64 (DBusMessageIter *iter)
 double
 dbus_message_iter_get_double (DBusMessageIter *iter)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
+  double value = 0.0;
 
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
+  _dbus_message_iter_get_basic_type (iter, DBUS_TYPE_DOUBLE, &value);
 
-  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);
+  return value;
 }
 
 /**
@@ -3074,6 +2834,30 @@ dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
   return len > 0;
 }
 
+static dbus_bool_t
+_dbus_message_iter_get_basic_type_array  (DBusMessageIter *iter,
+                                         char             type,
+                                         void           **array,
+                                         int             *array_len)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  int item_type, pos;
+
+  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+  pos = dbus_message_iter_get_data_start (real, &item_type);
+  
+  _dbus_assert (item_type == DBUS_TYPE_ARRAY);
+
+  item_type = iter_get_array_type (real, NULL);
+  
+  _dbus_assert (type == item_type);
+
+  return _dbus_demarshal_basic_type_array (&real->message->body,
+                                          item_type, array, array_len,
+                                          real->message->byte_order, &pos);
+}
+
 /**
  * Returns the byte array that the iterator may point to.
  * Note that you need to check that the iterator points
@@ -3089,24 +2873,8 @@ dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
                                  unsigned char   **value,
                                   int              *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-
-  _dbus_assert (type == DBUS_TYPE_BYTE);
-
-  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
-                                  pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BYTE,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3124,24 +2892,8 @@ dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
                                     unsigned char    **value,
                                     int               *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-
-  _dbus_assert (type == DBUS_TYPE_BOOLEAN);
-
-  if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
-                                  pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_BOOLEAN,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3159,24 +2911,8 @@ dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
                                    dbus_int32_t   **value,
                                    int             *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-  
-  _dbus_assert (type == DBUS_TYPE_INT32);
-
-  if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
-                                   pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT32,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3194,23 +2930,8 @@ dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
                                     dbus_uint32_t  **value,
                                     int             *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-  _dbus_assert (type == DBUS_TYPE_UINT32);
-
-  if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
-                                   pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT32,
+                                                 (void **) value, len);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -3232,24 +2953,8 @@ dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
                                    dbus_int64_t   **value,
                                    int             *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-  
-  _dbus_assert (type == DBUS_TYPE_INT64);
-
-  if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
-                                   pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_INT64,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3269,23 +2974,8 @@ dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
                                     dbus_uint64_t  **value,
                                     int             *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-  _dbus_assert (type == DBUS_TYPE_UINT64);
-
-  if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
-                                   pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_UINT64,
+                                                 (void **) value, len);
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -3305,23 +2995,8 @@ dbus_message_iter_get_double_array  (DBusMessageIter *iter,
                                     double         **value,
                                     int             *len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  int type, pos;
-
-  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
-
-  pos = dbus_message_iter_get_data_start (real, &type);
-  
-  _dbus_assert (type == DBUS_TYPE_ARRAY);
-
-  type = iter_get_array_type (real, NULL);
-  _dbus_assert (type == DBUS_TYPE_DOUBLE);
-
-  if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
-                                    pos, NULL, value, len))
-    return FALSE;
-  else
-    return TRUE;
+  return _dbus_message_iter_get_basic_type_array (iter, DBUS_TYPE_DOUBLE,
+                                                 (void **) value, len);
 }
 
 /**
@@ -3589,25 +3264,21 @@ dbus_message_iter_append_nil (DBusMessageIter *iter)
   return TRUE;
 }
 
-/**
- * Appends a boolean value to the message
- *
- * @param iter an iterator pointing to the end of the message
- * @param value the boolean value
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_iter_append_boolean (DBusMessageIter *iter,
-                                 dbus_bool_t     value)
+static dbus_bool_t
+dbus_message_iter_append_basic (DBusMessageIter *iter,
+                               char             type,
+                               void            *value)
 {
   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
 
   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
 
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
+  if (!dbus_message_iter_append_type (real, type))
     return FALSE;
-  
-  if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
+
+  if (!_dbus_marshal_basic_type (&real->message->body,
+                                type, value,
+                                real->message->byte_order))
     {
       _dbus_string_set_length (&real->message->body, real->pos);
       return FALSE;
@@ -3615,7 +3286,22 @@ dbus_message_iter_append_boolean (DBusMessageIter *iter,
 
   dbus_message_iter_append_done (real);
   
-  return TRUE;
+  return TRUE;  
+}
+
+/**
+ * Appends a boolean value to the message
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the boolean value
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean (DBusMessageIter *iter,
+                                 dbus_bool_t     value)
+{
+  unsigned char val = (value != FALSE);
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &val);
 }
 
 /**
@@ -3629,25 +3315,9 @@ dbus_bool_t
 dbus_message_iter_append_byte (DBusMessageIter *iter,
                               unsigned char    value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
-    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 dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &value);
 }
 
-
 /**
  * Appends a 32 bit signed integer to the message.
  *
@@ -3659,22 +3329,7 @@ dbus_bool_t
 dbus_message_iter_append_int32   (DBusMessageIter *iter,
                                  dbus_int32_t  value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &value);
 }
 
 /**
@@ -3688,22 +3343,7 @@ dbus_bool_t
 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
                                 dbus_uint32_t    value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
-    return FALSE;
-  
-  if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
-    {
-      _dbus_string_set_length (&real->message->body, real->pos);
-      return FALSE;
-    }
-
-  dbus_message_iter_append_done (real);
-  
-  return TRUE;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -3721,22 +3361,7 @@ dbus_bool_t
 dbus_message_iter_append_int64   (DBusMessageIter *iter,
                                  dbus_int64_t  value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
-    return FALSE;
-  
-  if (!_dbus_marshal_int64 (&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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &value);
 }
 
 /**
@@ -3752,22 +3377,7 @@ dbus_bool_t
 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
                                 dbus_uint64_t    value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
-    return FALSE;
-  
-  if (!_dbus_marshal_uint64 (&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;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &value);
 }
 
 #endif /* DBUS_HAVE_INT64 */
@@ -3783,22 +3393,7 @@ dbus_bool_t
 dbus_message_iter_append_double (DBusMessageIter *iter,
                                 double           value)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
-    return FALSE;
-  
-  if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
-    {
-      _dbus_string_set_length (&real->message->body, real->pos);
-      return FALSE;
-    }
-
-  dbus_message_iter_append_done (real);
-  
-  return TRUE;
+  return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &value);
 }
 
 /**
@@ -4098,46 +3693,222 @@ dbus_message_iter_append_array (DBusMessageIter      *iter,
  * @returns #TRUE on success
  */
 dbus_bool_t
-dbus_message_iter_append_dict (DBusMessageIter      *iter,
-                              DBusMessageIter      *dict_iter)
+dbus_message_iter_append_dict (DBusMessageIter      *iter,
+                              DBusMessageIter      *dict_iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
+  int len_pos;
+
+  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+  
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
+    return FALSE;  
+  
+  len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+  /* Empty length for now, backfill later */
+  if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+  
+  dict_real->parent_iter = real;
+  dict_real->message = real->message;
+  dict_real->changed_stamp = real->message->changed_stamp;
+  
+  dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
+  dict_real->pos = _dbus_string_get_length (&real->message->body);
+  dict_real->end = dict_real->end;
+  
+  dict_real->container_start = dict_real->pos;
+  dict_real->container_length_pos = len_pos;
+  dict_real->wrote_dict_key = 0;
+
+  dbus_message_iter_append_done (dict_real);
+  
+  real->wrote_dict_key = FALSE;
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+_dbus_message_iter_append_basic_array (DBusMessageIter *iter,
+                                      char             type,
+                                      const void      *value,
+                                      int              len)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+
+  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+  if (!append_array_type (real, type, NULL, NULL))
+    return FALSE;
+  
+  if (!_dbus_marshal_basic_type_array (&real->message->body,
+                                      type, value, len,
+                                      real->message->byte_order))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+
+  dbus_message_iter_append_done (real);
+  
+  return TRUE;
+}
+
+
+/**
+ * This function takes a va_list for use by language bindings.
+ * It's otherwise the same as dbus_message_append_args().
+ *
+ * @todo: Shouldn't this function clean up the changes to the message
+ *        on failures? (Yes)
+  
+ * @see dbus_message_append_args.  
+ * @param message the message
+ * @param first_arg_type type of first argument
+ * @param var_args value of first argument, then list of type/value pairs
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_args_valist (DBusMessage *message,
+                                int          first_arg_type,
+                                va_list      var_args)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-  DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
-  int len_pos;
+  int type, old_len;
+  DBusMessageIter iter;
 
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+  _dbus_return_val_if_fail (message != NULL, FALSE);
   
-  if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
-    return FALSE;  
+  old_len = _dbus_string_get_length (&message->body);
   
-  len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+  type = first_arg_type;
 
-  /* Empty length for now, backfill later */
-  if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+  dbus_message_append_iter_init (message, &iter);
+  
+  while (type != DBUS_TYPE_INVALID)
     {
-      _dbus_string_set_length (&real->message->body, real->pos);
-      return FALSE;
+      switch (type)
+       {
+       case DBUS_TYPE_NIL:
+         if (!dbus_message_iter_append_nil (&iter))
+           goto errorout;
+         break;
+       case DBUS_TYPE_BYTE:
+         if (!dbus_message_iter_append_byte (&iter, va_arg (var_args, unsigned char)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_BOOLEAN:
+         if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_INT32:
+         if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_UINT32:
+         if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
+           goto errorout;          
+         break;
+#ifdef DBUS_HAVE_INT64
+        case DBUS_TYPE_INT64:
+         if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_UINT64:
+         if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
+           goto errorout;          
+         break;
+#endif /* DBUS_HAVE_INT64 */
+       case DBUS_TYPE_DOUBLE:
+         if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
+           goto errorout;
+         break;
+       case DBUS_TYPE_STRING:
+         if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
+           goto errorout;
+         break;
+        case DBUS_TYPE_OBJECT_PATH:
+         if (!dbus_message_iter_append_object_path (&iter, va_arg (var_args, const char*)))
+           goto errorout;
+          break;
+       case DBUS_TYPE_CUSTOM:
+         {
+           const char *name;
+           unsigned char *data;
+           int len;
+           name = va_arg (var_args, const char *);
+           data = va_arg (var_args, unsigned char *);
+           len = va_arg (var_args, int);
+
+           if (!dbus_message_iter_append_custom (&iter, name, data, len))
+             goto errorout;
+           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);
+
+           switch (type)
+             {
+             case DBUS_TYPE_BYTE:
+             case DBUS_TYPE_BOOLEAN:
+             case DBUS_TYPE_INT32:
+             case DBUS_TYPE_UINT32:
+#ifdef DBUS_HAVE_INT64
+              case DBUS_TYPE_INT64:
+             case DBUS_TYPE_UINT64:
+#endif /* DBUS_HAVE_INT64 */
+             case DBUS_TYPE_DOUBLE:
+               if (!_dbus_message_iter_append_basic_array (&iter, type, 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_OBJECT_PATH:
+               if (!dbus_message_iter_append_object_path_array (&iter, (const char **)data, len))
+                 goto errorout;
+               break;
+             case DBUS_TYPE_NIL:
+             case DBUS_TYPE_ARRAY:
+             case DBUS_TYPE_CUSTOM:
+             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:
+         _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);
     }
-  
-  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_start = dict_real->pos;
-  dict_real->container_length_pos = len_pos;
-  dict_real->wrote_dict_key = 0;
 
-  dbus_message_iter_append_done (dict_real);
-  
-  real->wrote_dict_key = FALSE;
-  
   return TRUE;
-}
 
+ errorout:
+  return FALSE;
+}
 
 /**
  * Appends a boolean array to the message.
@@ -4152,22 +3923,8 @@ dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
                                        unsigned const char *value,
                                        int                  len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
-    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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
+                                               value, len);
 }
 
 /**
@@ -4183,22 +3940,8 @@ dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
                                      const dbus_int32_t *value,
                                      int                 len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
-    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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
+                                               value, len);
 }
 
 /**
@@ -4214,22 +3957,8 @@ dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
                                       const dbus_uint32_t *value,
                                       int                  len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
-    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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT32,
+                                               value, len);
 }
 
 #ifdef DBUS_HAVE_INT64
@@ -4249,22 +3978,8 @@ dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
                                      const dbus_int64_t *value,
                                      int                 len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
-    return FALSE;
-  
-  if (!_dbus_marshal_int64_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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT64,
+                                               value, len);
 }
 
 /**
@@ -4282,22 +3997,8 @@ dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
                                       const dbus_uint64_t *value,
                                       int                  len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
-    return FALSE;
-  
-  if (!_dbus_marshal_uint64_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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_UINT64,
+                                               value, len);
 }
 #endif /* DBUS_HAVE_INT64 */
 
@@ -4314,22 +4015,8 @@ dbus_message_iter_append_double_array (DBusMessageIter *iter,
                                       const double    *value,
                                       int              len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
-    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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_DOUBLE,
+                                               value, len);
 }
 
 /**
@@ -4345,22 +4032,8 @@ dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
                                     unsigned const char *value,
                                     int                  len)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
-
-  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
-
-  if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
-    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;
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BYTE,
+                                               value, len);
 }
 
 /**
index 8820273d0acc379a3274eede876f668fd2b7661d..a1bab8200c944f740057d623cdeccd951bfef84b 100644 (file)
@@ -2816,6 +2816,113 @@ _dbus_string_zero (DBusString *str)
 #include "dbus-test.h"
 #include <stdio.h>
 
+/**
+ * Parses a basic type defined by type contained in a DBusString. The
+ * end_return parameter may be #NULL if you aren't interested in it. The
+ * type is parsed and stored in value_return. Return parameters are not
+ * initialized if the function returns #FALSE.
+ *
+ * @param str the string
+ * @param type the type of the basic type
+ * @param start the byte index of the start of the type
+ * @param value_return return location of the value or #NULL
+ * @param end_return return location of the end of the type, or #NULL
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_string_parse_basic_type (const DBusString  *str,
+                              char               type,
+                              int                start,
+                              void              *value,
+                              int               *end_return)
+{
+  int end = start;
+
+  switch (type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      {
+       int len = _dbus_string_get_length (str) - start;
+       if (len >= 5 && _dbus_string_find_to (str, start, start + 5, "false", NULL))
+         {
+           end += 5;
+           *(unsigned char *) value = TRUE;
+         }
+       else if (len >= 4 && _dbus_string_find_to (str, start, start + 4, "true", NULL))
+         {
+           end += 4;
+           *(unsigned char *) value = FALSE;
+         }
+       else
+         _dbus_warn ("could not parse BOOLEAN\n");
+       break;
+      }
+    case DBUS_TYPE_BYTE:
+      {
+       long val = 0;
+
+       if (_dbus_string_get_byte (str, start) == '\'' &&
+           _dbus_string_get_length (str) >= start + 4 &&
+           _dbus_string_get_byte (str, start + 1) == '\\' &&
+           _dbus_string_get_byte (str, start + 2) == '\'' &&
+           _dbus_string_get_byte (str, start + 3) == '\'')
+         {
+           val = '\'';
+           end += 4;
+         }
+       else if (_dbus_string_get_byte (str, start) == '\'' &&
+                _dbus_string_get_length (str) >= start + 3 &&
+                _dbus_string_get_byte (str, start + 2) == '\'')
+         {
+           val = _dbus_string_get_byte (str, start + 1);
+           end += 3;
+         }
+       else
+         {
+           if (!_dbus_string_parse_int (str, start, &val, &end)) 
+             _dbus_warn ("Failed to parse integer for BYTE\n");
+         }
+
+       if (val > 255)
+         _dbus_warn ("A byte must be in range 0-255 not %ld\n", val);
+
+       *(unsigned char *) value = val;
+       break;
+      }
+    case DBUS_TYPE_INT32:
+      {
+       long val;
+       if (_dbus_string_parse_int (str, start, &val, &end))
+         *(dbus_int32_t *)value = val;
+       break;
+      }
+    case DBUS_TYPE_UINT32:
+      {
+       unsigned long val;
+       if (_dbus_string_parse_uint (str, start, &val, &end))
+         *(dbus_uint32_t *)value = val;
+       break;
+      }
+#ifdef DBUS_HAVE_INT64
+    case DBUS_TYPE_INT64:
+    case DBUS_TYPE_UINT64: 
+      /* use stroll oull */
+      _dbus_assert_not_reached ("string -> [u]int64 not supported yet");
+      break;
+#endif /* DBUS_HAVE_INT64 */
+    case DBUS_TYPE_DOUBLE:
+      _dbus_string_parse_double (str, start, value, &end);
+      break;
+    default:
+      _dbus_assert_not_reached ("not a basic type");
+      break;
+    }
+  if (end_return)
+    *end_return = end;
+
+  return end != start;
+}
+
 static void
 test_max_len (DBusString *str,
               int         max_len)
index 1499e0cceb70de97490defcd15e2695c096876fd..2a42879567b2e507d9cb311f91dc61880c2aaeca 100644 (file)
@@ -165,6 +165,11 @@ dbus_bool_t   _dbus_string_parse_double          (const DBusString  *str,
                                                   int                start,
                                                   double            *value,
                                                   int               *end_return);
+dbus_bool_t   _dbus_string_parse_basic_type      (const DBusString  *str,
+                                                 char               type,
+                                                  int                start,
+                                                  void              *value,
+                                                  int               *end_return);
 dbus_bool_t   _dbus_string_find                  (const DBusString  *str,
                                                   int                start,
                                                   const char        *substr,
index 06bf2182a6cadb3870df3b6c34b0c4c3d1b5cbc9..04e962feda750d6c62881cd41922a5cc387fecc7 100644 (file)
@@ -17,8 +17,10 @@ dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)
     MAP(TYPE_BOOLEAN, get_boolean, TYPE_BOOLEAN , set_boolean);
     MAP(TYPE_INT32, get_int32, TYPE_INT , set_int);
     MAP(TYPE_UINT32, get_uint32, TYPE_UINT , set_uint);
+#ifdef DBUS_HAVE_INT64
     MAP(TYPE_INT64, get_int64, TYPE_INT64 , set_int64);
     MAP(TYPE_UINT64, get_uint64, TYPE_UINT64 , set_uint64);
+#endif
     MAP(TYPE_DOUBLE, get_double, TYPE_DOUBLE , set_double);
     case DBUS_TYPE_STRING:
       {
@@ -82,6 +84,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)
       dbus_message_iter_append_uint32 (iter,
                                        g_value_get_ulong (value));
       break;
+#ifdef DBUS_HAVE_INT64
     case G_TYPE_INT64:
       dbus_message_iter_append_int64 (iter,
                                       g_value_get_int64 (value));
@@ -90,6 +93,7 @@ dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value)
       dbus_message_iter_append_uint64 (iter,
                                        g_value_get_uint64 (value));
       break;
+#endif
     case G_TYPE_FLOAT:
       dbus_message_iter_append_double (iter,
                                        g_value_get_float (value));