dbus/dbus dbus-marshal.c, 1.49, 1.50 dbus-marshal.h, 1.20, 1.21 dbus-message-builder.c, 1.22, 1.23 dbus-message.c, 1.128, 1.129 dbus-string.c, 1.47, 1.48 dbus-string.h, 1.24, 1.25

Michael Meeks michael at pdx.freedesktop.org
Fri May 28 06:10:38 PDT 2004


Update of /cvs/dbus/dbus/dbus
In directory pdx:/tmp/cvs-serv26544/dbus

Modified Files:
	dbus-marshal.c dbus-marshal.h dbus-message-builder.c 
	dbus-message.c dbus-string.c dbus-string.h 
Log Message:
2004-05-28  Michael Meeks  <michael at 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.



Index: dbus-marshal.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- a/dbus-marshal.c	21 Mar 2004 13:42:23 -0000	1.49
+++ b/dbus-marshal.c	28 May 2004 13:10:35 -0000	1.50
@@ -1068,6 +1068,61 @@
 #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.
  *
  * @todo Should we check the string to make sure
@@ -1392,6 +1447,53 @@
                                    (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 @@
   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 @@
 #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 @@
         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 @@
 	    /* 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 (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: dbus-marshal.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- a/dbus-marshal.h	2 Dec 2003 10:44:21 -0000	1.20
+++ b/dbus-marshal.h	28 May 2004 13:10:35 -0000	1.21
@@ -184,6 +184,10 @@
 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 @@
 					    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 @@
 					    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 @@
 					    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: dbus-message-builder.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message-builder.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- a/dbus-message-builder.c	22 Apr 2004 19:14:45 -0000	1.22
+++ b/dbus-message-builder.c	28 May 2004 13:10:35 -0000	1.23
@@ -335,6 +335,193 @@
   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 @@
   DBusHashTable *length_hash;
   int endian;
   DBusHashIter iter;
+  char type;
+  dbus_bool_t is_array;
   
   retval = FALSE;
   length_hash = NULL;
@@ -510,7 +699,7 @@
             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 @@
             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"))
@@ -754,380 +935,6 @@
             }
         }
       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"))
 	{
 	  SAVE_FOR_UNALIGN (dest, 4);
@@ -1209,124 +1016,6 @@
 	  
 	  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 @@
           
           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: dbus-message.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.c,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -d -r1.128 -r1.129
--- a/dbus-message.c	23 May 2004 18:09:46 -0000	1.128
+++ b/dbus-message.c	28 May 2004 13:10:35 -0000	1.129
@@ -1884,175 +1884,6 @@
 }
 
 /**
- * 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
@@ -2142,264 +1973,6 @@
 }
 
 /**
- * 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;
-        }
-
-      i++;
-    }
-  
-  retval = TRUE;
-  
- out:
-  
-  return retval;
-}
-
-
-/**
  * Initializes a DBusMessageIter representing the arguments of the
  * message passed in.
  *
@@ -2788,6 +2361,240 @@
   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 **);
+
+	    *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;
+        }
+
+      i++;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  
+  return retval;
+}
+
 /**
  * Returns the byte value that an iterator may point to.
  * Note that you need to check that the iterator points to
@@ -2800,22 +2607,13 @@
 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_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_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_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_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_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 @@
 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 @@
   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 @@
 				  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 @@
 				     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_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_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_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_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 @@
 				     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 @@
   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_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_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_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_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_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_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_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);
 }
 
 /**
@@ -4138,28 +3733,22 @@
   return TRUE;
 }
 
-
-/**
- * Appends a boolean array to the message.
- *
- * @param iter an iterator pointing to the end of the message
- * @param value the array
- * @param len the length of the array
- * @returns #TRUE on success
- */
-dbus_bool_t
-dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
-					unsigned const char *value,
-					int                  len)
+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, DBUS_TYPE_BOOLEAN, NULL, NULL))
+  if (!append_array_type (real, type, NULL, NULL))
     return FALSE;
   
-  if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
+  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;
@@ -4170,35 +3759,189 @@
   return TRUE;
 }
 
+
 /**
- * Appends a 32 bit signed integer array to the message.
+ * This function takes a va_list for use by language bindings.
+ * It's otherwise the same as dbus_message_append_args().
  *
- * @param iter an iterator pointing to the end of the message
- * @param value the array
- * @param len the length of the array
+ * @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_iter_append_int32_array (DBusMessageIter    *iter,
-				      const dbus_int32_t *value,
-				      int                 len)
+dbus_message_append_args_valist (DBusMessage *message,
+				 int          first_arg_type,
+				 va_list      var_args)
 {
-  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  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);
+  
+  old_len = _dbus_string_get_length (&message->body);
+  
+  type = first_arg_type;
 
-  if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
-    return FALSE;
+  dbus_message_append_iter_init (message, &iter);
   
-  if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
+  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);
     }
 
-  dbus_message_iter_append_done (real);
-  
   return TRUE;
+
+ errorout:
+  return FALSE;
+}
+
+/**
+ * Appends a boolean array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
+					unsigned const char *value,
+					int                  len)
+{
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_BOOLEAN,
+						value, len);
+}
+
+/**
+ * Appends a 32 bit signed integer array to the message.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param value the array
+ * @param len the length of the array
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
+				      const dbus_int32_t *value,
+				      int                 len)
+{
+  return _dbus_message_iter_append_basic_array (iter, DBUS_TYPE_INT32,
+						value, len);
 }
 
 /**
@@ -4214,22 +3957,8 @@
 				       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 @@
 				      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 @@
 				       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 @@
 				       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 @@
 				     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: dbus-string.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- a/dbus-string.c	17 May 2004 22:19:04 -0000	1.47
+++ b/dbus-string.c	28 May 2004 13:10:35 -0000	1.48
@@ -2816,6 +2816,113 @@
 #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: dbus-string.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-string.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- a/dbus-string.h	17 May 2004 22:19:04 -0000	1.24
+++ b/dbus-string.h	28 May 2004 13:10:36 -0000	1.25
@@ -165,6 +165,11 @@
                                                   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,




More information about the dbus-commit mailing list