2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-marshal.c
index f78757f..2222ad9 100644 (file)
@@ -157,7 +157,7 @@ _dbus_marshal_set_int32 (DBusString          *str,
   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                 byte_order == DBUS_BIG_ENDIAN);
   
-  _dbus_string_get_data_len (str, &data, offset, 4);
+  data = _dbus_string_get_data_len (str, offset, 4);
 
   _dbus_pack_int32 (value, byte_order, data);
 }
@@ -183,7 +183,7 @@ _dbus_marshal_set_uint32 (DBusString          *str,
   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                 byte_order == DBUS_BIG_ENDIAN);
   
-  _dbus_string_get_data_len (str, &data, offset, 4);
+  data = _dbus_string_get_data_len (str, offset, 4);
 
   _dbus_pack_uint32 (value, byte_order, data);
 }
@@ -198,6 +198,7 @@ _dbus_marshal_set_uint32 (DBusString          *str,
  * @param offset the byte offset where string should be written
  * @param byte_order the byte order to use
  * @param value the value
+ * @param len the length to use
  * @returns #TRUE on success
  * 
  */
@@ -205,10 +206,10 @@ dbus_bool_t
 _dbus_marshal_set_string (DBusString          *str,
                           int                  byte_order,
                           int                  offset,
-                          const DBusString    *value)
+                          const DBusString    *value,
+                         int                  len)
 {
   int old_len;
-  int new_len;
   
   _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
                 byte_order == DBUS_BIG_ENDIAN);
@@ -216,14 +217,12 @@ _dbus_marshal_set_string (DBusString          *str,
   old_len = _dbus_demarshal_uint32 (str, byte_order,
                                     offset, NULL);
 
-  new_len = _dbus_string_get_length (value);
-  
-  if (!_dbus_string_replace_len (value, 0, new_len,
+  if (!_dbus_string_replace_len (value, 0, len,
                                  str, offset + 4, old_len))
     return FALSE;
 
   _dbus_marshal_set_uint32 (str, byte_order,
-                            offset, new_len);
+                            offset, len);
 
   return TRUE;
 }
@@ -353,7 +352,10 @@ _dbus_marshal_byte_array (DBusString          *str,
       return FALSE;
     }
 
-  return _dbus_string_append_len (str, value, len);
+  if (len == 0)
+    return TRUE;
+  else
+    return _dbus_string_append_len (str, value, len);
 }
 
 /**
@@ -496,6 +498,193 @@ _dbus_marshal_string_array (DBusString  *str,
   return FALSE;      
 }
 
+
+/**
+ * Marshals a dict
+ * @param str the string to append the marshalled value to
+ * @param byte_order the byte order to use
+ * @param dict the dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+_dbus_marshal_dict (DBusString *str,
+                   int         byte_order,
+                   DBusDict   *dict)
+{
+  int old_string_len;
+  int i, len;
+  char **keys;
+  
+  old_string_len = _dbus_string_get_length (str);
+
+  if (!dbus_dict_get_keys (dict, &keys, &len))
+    goto error;
+
+  if (len == 0)
+    return TRUE;
+
+  if (!_dbus_marshal_string_array (str, byte_order,
+                                  (const char **)keys, len))
+    goto error;
+
+  for (i = 0; i < len; i++)
+    {
+      int value_type;
+
+      value_type = dbus_dict_get_value_type (dict, keys[i]);
+
+      if (!_dbus_string_append_byte (str, value_type))
+       goto error;
+      
+      switch (dbus_dict_get_value_type (dict, keys[i]))
+       {
+       case DBUS_TYPE_BOOLEAN:
+         {
+           dbus_bool_t value;
+
+           if (!dbus_dict_get_boolean (dict, keys[i], &value))
+             goto error;
+           
+           if (!_dbus_string_append_byte (str, (value != FALSE)))
+             goto error;
+
+           break;
+         }
+         
+       case DBUS_TYPE_INT32:
+         {
+           dbus_int32_t value;
+           
+           if (!dbus_dict_get_int32 (dict, keys[i], &value))
+             goto error;
+           
+           if (!_dbus_marshal_int32 (str, byte_order, value))
+             goto error;
+
+           break;
+         }
+       case DBUS_TYPE_UINT32:
+         {
+           dbus_uint32_t value;
+           
+           if (!dbus_dict_get_uint32 (dict, keys[i], &value))
+             goto error;
+           
+           if (!_dbus_marshal_uint32 (str, byte_order, value))
+             goto error;
+
+           break;
+         }
+       case DBUS_TYPE_DOUBLE:
+         {
+           double value;
+           
+           if (!dbus_dict_get_double (dict, keys[i], &value))
+             goto error;
+
+           if (!_dbus_marshal_double (str, byte_order, value))
+             goto error;
+
+           break;
+         }
+       case DBUS_TYPE_INT32_ARRAY:
+         {
+           const dbus_int32_t *value;
+           int len;
+
+           if (!dbus_dict_get_int32_array (dict, keys[i], &value, &len))
+             goto error;
+
+           if (!_dbus_marshal_int32_array (str, byte_order, value, len))
+             goto error;
+           
+           break;
+         }
+       case DBUS_TYPE_STRING:
+         {
+           const char *value;
+
+           if (!dbus_dict_get_string (dict, keys[i], &value))
+             goto error;
+
+           if (!_dbus_marshal_string (str, byte_order, value))
+             goto error;
+           
+           break;
+         }       
+       case DBUS_TYPE_BOOLEAN_ARRAY:
+         {
+           const unsigned char *value;
+           int len;
+
+           if (!dbus_dict_get_boolean_array (dict, keys[i], &value, &len))
+             goto error;
+
+           if (!_dbus_marshal_byte_array (str, byte_order, value, len))
+             goto error;
+           
+           break;
+         }       
+       case DBUS_TYPE_UINT32_ARRAY:
+         {
+           const dbus_uint32_t *value;
+           int len;
+
+           if (!dbus_dict_get_uint32_array (dict, keys[i], &value, &len))
+             goto error;
+
+           if (!_dbus_marshal_uint32_array (str, byte_order, value, len))
+             goto error;
+           
+           break;
+         }       
+       case DBUS_TYPE_DOUBLE_ARRAY:
+         {
+           const double *value;
+           int len;
+
+           if (!dbus_dict_get_double_array (dict, keys[i], &value, &len))
+             goto error;
+
+           if (!_dbus_marshal_double_array (str, byte_order, value, len))
+             goto error;
+           
+           break;
+         }
+       case DBUS_TYPE_STRING_ARRAY:
+         {
+           const char **value;
+           int len;
+
+           if (!dbus_dict_get_string_array (dict, keys[i], &value, &len))
+             goto error;
+
+           if (!_dbus_marshal_string_array (str, byte_order, (const char **)value, len))
+             goto error;
+           
+           break;
+         }
+       default:
+         _dbus_warn ("unkown value type %d\n", dbus_dict_get_value_type (dict, keys[i]));
+         _dbus_assert_not_reached ("unknown value type in dict");
+       }
+    }
+
+  dbus_free_string_array (keys);
+
+  return TRUE;
+  
+ error:
+  
+  dbus_free_string_array (keys);
+  
+  /* Restore previous length */
+  _dbus_string_set_length (str, old_string_len);
+
+  return FALSE;
+}
+
+
 /**
  * Demarshals a double.
  *
@@ -516,7 +705,7 @@ _dbus_demarshal_double (const DBusString  *str,
 
   pos = _DBUS_ALIGN_VALUE (pos, sizeof (double));
 
-  _dbus_string_get_const_data_len (str, &buffer, pos, sizeof (double));
+  buffer = _dbus_string_get_const_data_len (str, pos, sizeof (double));
 
   retval = *(double *)buffer;
   
@@ -618,7 +807,7 @@ _dbus_demarshal_string (const DBusString *str,
   if (!retval)
     return NULL;
 
-  _dbus_string_get_const_data_len (str, &data, pos, len);
+  data = _dbus_string_get_const_data_len (str, pos, len);
 
   if (!data)
     return NULL;
@@ -641,15 +830,18 @@ _dbus_demarshal_string (const DBusString *str,
  * @param byte_order the byte order
  * @param pos the position in the string
  * @param new_pos the new position of the string
+ * @param array the array
  * @param array_len length of the demarshaled data
- * @returns the demarshaled data.
+ * @returns #TRUE on success
  */
-unsigned char *
-_dbus_demarshal_byte_array (const DBusString *str,
-                           int         byte_order,
-                           int         pos,
-                           int        *new_pos,
-                           int        *array_len)
+dbus_bool_t
+_dbus_demarshal_byte_array (const DBusString  *str,
+                           int                byte_order,
+                           int                pos,
+                           int               *new_pos,
+                           unsigned char    **array,
+                           int               *array_len)
 {
   int len;
   unsigned char *retval;
@@ -657,25 +849,39 @@ _dbus_demarshal_byte_array (const DBusString *str,
 
   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
+  if (len == 0)
+    {
+      *array_len = len;
+      *array = NULL;
+
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+  
   retval = dbus_malloc (len);
 
   if (!retval)
-    return NULL;
+    return FALSE;
 
-  _dbus_string_get_const_data_len (str, &data, pos, len);
+  data = _dbus_string_get_const_data_len (str, pos, len);
 
   if (!data)
-    return NULL;
+    {
+      dbus_free (retval);
+      return FALSE;
+    }
 
   memcpy (retval, data, len);
 
   if (new_pos)
     *new_pos = pos + len;
 
-  if (array_len)
-    *array_len = len;
-
-  return retval;
+  *array = retval;
+  *array_len = len;
+  
+  return TRUE;
 }
 
 /**
@@ -685,25 +891,38 @@ _dbus_demarshal_byte_array (const DBusString *str,
  * @param byte_order the byte order
  * @param pos the position in the string
  * @param new_pos the new position of the string
+ * @param array the array
  * @param array_len length of the demarshaled data
- * @returns the demarshaled data.
+ * @returns #TRUE on success
  */
-dbus_int32_t *
-_dbus_demarshal_int32_array (const DBusString *str,
-                            int         byte_order,
-                            int         pos,
-                            int        *new_pos,
-                            int        *array_len)
+dbus_bool_t
+_dbus_demarshal_int32_array (const DBusString  *str,
+                            int                byte_order,
+                            int                pos,
+                            int               *new_pos,
+                            dbus_int32_t     **array,
+                            int               *array_len)
 {
   int len, i;
   dbus_int32_t *retval;
   
   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
-  retval = dbus_new (dbus_int32_t, len);
+  if (len == 0)
+    {
+      *array_len = 0;
+      *array = NULL;
 
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+  
+  retval = dbus_new (dbus_int32_t, len);
+  
   if (!retval)
-    return NULL;
+    return FALSE;
 
   for (i = 0; i < len; i++)
     retval[i] = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
@@ -711,10 +930,10 @@ _dbus_demarshal_int32_array (const DBusString *str,
   if (new_pos)
     *new_pos = pos;
 
-  if (array_len)
-    *array_len = len;
+  *array_len = len;
+  *array = retval;
   
-  return retval;
+  return TRUE;
 }
 
 /**
@@ -724,25 +943,38 @@ _dbus_demarshal_int32_array (const DBusString *str,
  * @param byte_order the byte order
  * @param pos the position in the string
  * @param new_pos the new position of the string
+ * @param array the array
  * @param array_len length of the demarshaled data
- * @returns the demarshaled data.
+ * @returns #TRUE on success
  */
-dbus_uint32_t *
-_dbus_demarshal_uint32_array (const DBusString *str,
-                             int         byte_order,
-                             int         pos,
-                             int        *new_pos,
-                             int        *array_len)
+dbus_bool_t
+_dbus_demarshal_uint32_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             dbus_uint32_t    **array,
+                             int               *array_len)
 {
   int len, i;
   dbus_uint32_t *retval;
   
   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
+  if (len == 0)
+    {
+      *array_len = 0;
+      *array = NULL;
+
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+  
   retval = dbus_new (dbus_uint32_t, len);
 
   if (!retval)
-    return NULL;
+    return FALSE;
 
   for (i = 0; i < len; i++)
     retval[i] = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
@@ -750,10 +982,10 @@ _dbus_demarshal_uint32_array (const DBusString *str,
   if (new_pos)
     *new_pos = pos;
 
-  if (array_len)
-    *array_len = len;
+  *array_len = len;
+  *array = retval;
   
-  return retval;  
+  return TRUE;  
 }
 
 /**
@@ -763,25 +995,38 @@ _dbus_demarshal_uint32_array (const DBusString *str,
  * @param byte_order the byte order
  * @param pos the position in the string
  * @param new_pos the new position of the string
+ * @param array the array
  * @param array_len length of the demarshaled data
- * @returns the demarshaled data.
+ * @returns #TRUE on success
  */
-double *
-_dbus_demarshal_double_array (const DBusString *str,
-                             int         byte_order,
-                             int         pos,
-                             int        *new_pos,
-                             int        *array_len)
+dbus_bool_t
+_dbus_demarshal_double_array (const DBusString  *str,
+                             int                byte_order,
+                             int                pos,
+                             int               *new_pos,
+                             double           **array,
+                             int               *array_len)
 {
   int len, i;
   double *retval;
   
   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
+  if (len == 0)
+    {
+      *array_len = 0;
+      *array = NULL;
+
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+  
   retval = dbus_new (double, len);
 
   if (!retval)
-    return NULL;
+    return FALSE;
 
   for (i = 0; i < len; i++)
     retval[i] = _dbus_demarshal_double (str, byte_order, pos, &pos);
@@ -789,10 +1034,10 @@ _dbus_demarshal_double_array (const DBusString *str,
   if (new_pos)
     *new_pos = pos;
 
-  if (array_len)
-    *array_len = len;
+  *array_len = len;
+  *array = retval;
   
-  return retval;  
+  return TRUE; 
 }
 
 /**
@@ -802,25 +1047,38 @@ _dbus_demarshal_double_array (const DBusString *str,
  * @param byte_order the byte order
  * @param pos the position in the string
  * @param new_pos the new position of the string
+ * @param array the array
  * @param array_len length of the demarshaled data
- * @returns the demarshaled data.
+ * @returns #TRUE on success
  */
-char **
-_dbus_demarshal_string_array (const DBusString *str,
-                             int         byte_order,
-                             int         pos,
-                             int        *new_pos,
-                             int        *array_len)
+dbus_bool_t
+_dbus_demarshal_string_array (const DBusString   *str,
+                             int                 byte_order,
+                             int                 pos,
+                             int                *new_pos,
+                             char             ***array,
+                             int                *array_len)
 {
   int len, i, j;
   char **retval;
 
   len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
 
+  if (len == 0)
+    {
+      *array_len = 0;
+      *array = NULL;
+
+      if (new_pos)
+       *new_pos = pos;
+      
+      return TRUE;
+    }
+  
   retval = dbus_new (char *, len + 1);
 
   if (!retval)
-    return NULL;
+    return FALSE;
 
   retval[len] = NULL;
   
@@ -835,17 +1093,230 @@ _dbus_demarshal_string_array (const DBusString *str,
  if (new_pos)
     *new_pos = pos;
 
-  if (array_len)
   *array_len = len;
+ *array = retval;
+ *array_len = len;
   
-  return retval;
+  return TRUE;
 
  error:
   for (j = 0; j < i; j++)
     dbus_free (retval[i]);
   dbus_free (retval);
 
-  return NULL;
+  return FALSE;
+}
+
+/**
+ * Demarshals a dict
+ *
+ * @param str the string containing the data
+ * @param byte_order the byte order
+ * @param pos the position in the string
+ * @param new_pos the new position in the string
+ * @param dict the dict
+ * @returns #TRUE on success.
+ */
+dbus_bool_t
+_dbus_demarshal_dict (const DBusString *str,
+                     int               byte_order,
+                     int               pos,
+                     int              *new_pos,
+                     DBusDict       **dict)
+{
+  char **keys;
+  int i, len;
+  
+  *dict = dbus_dict_new ();
+  if (!*dict)
+    return FALSE;
+
+  if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &keys, &len))
+    goto error;
+
+  for (i = 0; i < len; i++)
+    {
+      int value_type;
+      
+      switch ((value_type = _dbus_string_get_byte (str, pos ++)))
+       {
+       case DBUS_TYPE_BOOLEAN:
+         {
+           dbus_bool_t value;
+
+           value = _dbus_string_get_byte (str, pos ++);
+
+           if (!dbus_dict_set_boolean (*dict, keys[i], value))
+             goto error;
+           break;
+         }
+       case DBUS_TYPE_INT32:
+         {
+           dbus_int32_t value;
+
+           value = _dbus_demarshal_int32 (str, byte_order, pos, &pos);
+
+           if (!dbus_dict_set_int32 (*dict, keys[i], value))
+             goto error;
+           
+           break;
+         }
+       case DBUS_TYPE_UINT32:
+         {
+           dbus_uint32_t value;
+
+           value = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+
+           if (!dbus_dict_set_uint32 (*dict, keys[i], value))
+             goto error;
+           
+           break;
+         }
+       case DBUS_TYPE_DOUBLE:
+         {
+           double value;
+
+           value = _dbus_demarshal_double (str, byte_order, pos, &pos);
+
+           if (!dbus_dict_set_double (*dict, keys[i], value))
+             goto error;
+           
+           break;
+         }
+       case DBUS_TYPE_STRING:
+         {
+           char *value;
+
+           value = _dbus_demarshal_string (str, byte_order, pos, &pos);
+
+           if (!value)
+             goto error;
+
+           if (!dbus_dict_set_string (*dict, keys[i], value))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           
+           break;
+         }
+       case DBUS_TYPE_BOOLEAN_ARRAY:
+         {
+           unsigned char *value;
+           int len;
+           
+           if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_boolean_array (*dict, keys[i], value, len))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           break;
+         }
+       case DBUS_TYPE_INT32_ARRAY:
+         {
+           dbus_int32_t *value;
+           int len;
+           
+           if (!_dbus_demarshal_int32_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_int32_array (*dict, keys[i], value, len))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           break;
+         }
+       case DBUS_TYPE_UINT32_ARRAY:
+         {
+           dbus_uint32_t *value;
+           int len;
+           
+           if (!_dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_uint32_array (*dict, keys[i], value, len))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           break;
+         }
+       case DBUS_TYPE_DOUBLE_ARRAY:
+         {
+           double *value;
+           int len;
+           
+           if (!_dbus_demarshal_double_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_double_array (*dict, keys[i], value, len))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           break;
+         }
+       case DBUS_TYPE_BYTE_ARRAY:
+         {
+           unsigned char *value;
+           int len;
+           
+           if (!_dbus_demarshal_byte_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_byte_array (*dict, keys[i], value, len))
+             {
+               dbus_free (value);
+               goto error;
+             }
+
+           dbus_free (value);
+           break;
+         }
+       case DBUS_TYPE_STRING_ARRAY:
+         {
+           char **value;
+           int len;
+           
+           if (!_dbus_demarshal_string_array (str, byte_order, pos, &pos, &value, &len))
+             goto error;
+
+           if (!dbus_dict_set_string_array (*dict, keys[i], (const char **)value, len))
+             {
+               dbus_free_string_array (value);
+               goto error;
+             }
+
+           dbus_free_string_array (value);
+           break;
+         }
+       default:
+         _dbus_warn ("unknown value type %d\n", value_type);
+         _dbus_assert_not_reached ("unknown value arg");
+       }
+    }
+  
+  dbus_free_string_array (keys);
+  return TRUE;
+  
+ error:
+  dbus_free_string_array (keys);
+  dbus_dict_unref (*dict);
+  
+  return FALSE;
 }
 
 /** 
@@ -871,7 +1342,7 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
   if (pos >= _dbus_string_get_length (str))
     return FALSE;
 
-  _dbus_string_get_const_data_len (str, &data, pos, 1);
+  data = _dbus_string_get_const_data_len (str, pos, 1);
   
   switch (*data)
     {
@@ -980,7 +1451,34 @@ _dbus_marshal_get_arg_end_pos (const DBusString *str,
        *end_pos = pos;
       }
       break;
-      
+
+    case DBUS_TYPE_DICT:
+      {
+       int len, i;
+
+       /* Demarshal the length */
+       len = _dbus_demarshal_uint32 (str, byte_order, pos + 1, &pos);
+
+       for (i = 0; i < len; i++)
+         {
+           int str_len;
+           
+           /* Demarshal string length */
+           str_len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+           pos += str_len + 1;
+         }
+
+       /* Now check the values */
+       for (i = 0; i < len; i++)
+         {
+           if (!_dbus_marshal_get_arg_end_pos (str, byte_order, pos, &pos))
+               return FALSE;
+         }
+
+       *end_pos = pos;
+       
+       break;
+      }
     default:
       _dbus_warn ("Unknown message arg type %d\n", *data);
       _dbus_assert_not_reached ("Unknown message argument type\n");
@@ -1017,7 +1515,7 @@ demarshal_and_validate_len (const DBusString *str,
 
   _dbus_assert (new_pos != NULL);
   
-  if ((align_4 + 4) >= _dbus_string_get_length (str))
+  if ((align_4 + 4) > _dbus_string_get_length (str))
     {
       _dbus_verbose ("not enough room in message for array length\n");
       return -1;
@@ -1104,7 +1602,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
   if (pos >= _dbus_string_get_length (str))
     return FALSE;
 
-  _dbus_string_get_const_data_len (str, &data, pos, 1);
+  data = _dbus_string_get_const_data_len (str, pos, 1);
   
   switch (*data)
     {
@@ -1252,15 +1750,20 @@ _dbus_marshal_validate_arg (const DBusString *str,
         if (len < 0)
           return FALSE;
 
-        align_8 = _DBUS_ALIGN_VALUE (pos, 8);
-        if (!_dbus_string_validate_nul (str, pos,
-                                        align_8 - pos))
-          {
-            _dbus_verbose ("double array alignment padding not initialized to nul\n");
-            return FALSE;
-          }
-        
-       *end_pos = align_8 + len * 8;
+       if (len == 0)
+         *end_pos = pos;
+       else
+         {
+           align_8 = _DBUS_ALIGN_VALUE (pos, 8);
+           if (!_dbus_string_validate_nul (str, pos,
+                                           align_8 - pos))
+             {
+               _dbus_verbose ("double array alignment padding not initialized to nul\n");
+               return FALSE;
+             }
+
+           *end_pos = align_8 + len * 8;
+         }
       }
       break;
       
@@ -1289,7 +1792,53 @@ _dbus_marshal_validate_arg (const DBusString *str,
        *end_pos = pos;
       }
       break;
-      
+
+      case DBUS_TYPE_DICT:
+       {
+         int len;
+         int i;
+
+         len = demarshal_and_validate_len (str, byte_order, pos + 1, &pos);
+         if (len < 0)
+           return FALSE;
+         
+         for (i = 0; i < len; i++)
+           {
+             int str_len;
+             
+             str_len = demarshal_and_validate_len (str, byte_order,
+                                                   pos, &pos);
+             if (str_len < 0)
+               return FALSE;
+             
+             if (!validate_string (str, pos, str_len, &pos))
+               return FALSE;            
+           }
+
+         /* Now validate each argument */
+         for (i = 0; i < len; i++)
+           {
+             if (pos >= _dbus_string_get_length (str))
+               {
+                 _dbus_verbose ("not enough values in dict\n");
+                 return FALSE;
+               }
+
+             if (_dbus_string_get_byte (str, pos) == DBUS_TYPE_NIL)
+               {
+                 _dbus_verbose ("can't have NIL values in dicts\n");
+                 return FALSE;
+               }
+             
+             if (!_dbus_marshal_validate_arg (str, byte_order, pos, &pos))
+               return FALSE;
+           }
+
+         *end_pos = pos;
+
+         break;
+       }
+       
     default:
       _dbus_verbose ("Unknown message arg type %d\n", *data);
       return FALSE;
@@ -1408,8 +1957,7 @@ _dbus_verbose_bytes_of_string (const DBusString    *str,
       len = real_len - start;
     }
   
-  
-  _dbus_string_get_const_data_len (str, &d, start, len);
+  d = _dbus_string_get_const_data_len (str, start, len);
 
   _dbus_verbose_bytes (d, len);
 }
@@ -1426,9 +1974,25 @@ _dbus_marshal_test (void)
   DBusString str;
   char *tmp1, *tmp2;
   dbus_int32_t array1[3] = { 0x123, 0x456, 0x789 }, *array2;
-  int pos = 0, len;
+  int pos = 0, i, len;
+  dbus_bool_t our_bool;
+  dbus_int32_t our_int;
+  dbus_uint32_t our_uint;
+  double our_double;
+  const char *our_string;
+  const unsigned char boolean_array[] = { TRUE, FALSE, FALSE, TRUE };
+  const unsigned char *our_boolean_array;
+  const dbus_int32_t int32_array[] = { 0x12345678, -1911, 0, 0xaffe, 0xedd1e };
+  const dbus_int32_t *our_int32_array;
+  const dbus_uint32_t uint32_array[] = { 0x12345678, 0, 0xdeadbeef, 0x87654321, 0xffffffff };
+  const dbus_uint32_t *our_uint32_array;
+  const double double_array[] = { 3.14159, 1.2345, 6.7890 };
+  const double *our_double_array;
+  const char *string_array[] = { "This", "Is", "A", "Test" };
+  const char **our_string_array;
+  DBusDict *dict;
   
-  if (!_dbus_string_init (&str, _DBUS_INT_MAX))
+  if (!_dbus_string_init (&str))
     _dbus_assert_not_reached ("failed to init string");
 
   /* Marshal doubles */
@@ -1484,14 +2048,105 @@ _dbus_marshal_test (void)
   /* Marshal signed integer arrays */
   if (!_dbus_marshal_int32_array (&str, DBUS_BIG_ENDIAN, array1, 3))
     _dbus_assert_not_reached ("could not marshal integer array");
-  array2 = _dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &len);
+  if (!_dbus_demarshal_int32_array (&str, DBUS_BIG_ENDIAN, pos, &pos, &array2, &len))
+    _dbus_assert_not_reached ("could not demarshal integer array");
 
   if (len != 3)
     _dbus_assert_not_reached ("Signed integer array lengths differ!\n");
   dbus_free (array2);
   
 
+  /* Marshal dicts */
+  dict = dbus_dict_new ();
+
+  if (dbus_dict_get_value_type (dict, "foo") != DBUS_TYPE_NIL)
+    _dbus_assert_not_reached ("didn't return DBUS_TYPE_NIL for non-existant entry");
+  
+  if (!dbus_dict_set_boolean (dict, "boolean", TRUE))
+    _dbus_assert_not_reached ("could not add boolean value");
+
+  if (!dbus_dict_set_int32 (dict, "int32", 0x12345678))
+    _dbus_assert_not_reached ("could not add int32 value");
+
+  if (!dbus_dict_set_uint32 (dict, "uint32", 0x87654321))
+    _dbus_assert_not_reached ("could not add uint32 value");
+
+  if (!dbus_dict_set_double (dict, "double", 3.14159))
+    _dbus_assert_not_reached ("could not add double value");
+
+  if (!dbus_dict_set_string (dict, "string", "test string"))
+    _dbus_assert_not_reached ("could not add string value");
+
+  if (!dbus_dict_set_boolean_array (dict, "boolean_array", boolean_array, 4))
+    _dbus_assert_not_reached ("could not add boolean array");
+
+  if (!dbus_dict_set_int32_array (dict, "int32_array", int32_array, 5))
+    _dbus_assert_not_reached ("could not add int32 array");
+
+  if (!dbus_dict_set_uint32_array (dict, "uint32_array", uint32_array, 5))
+    _dbus_assert_not_reached ("could not add uint32 array");
+
+  if (!dbus_dict_set_double_array (dict, "double_array", double_array, 3))
+    _dbus_assert_not_reached ("could not add double array");
+
+  if (!dbus_dict_set_string_array (dict, "string_array", string_array, 4))
+    _dbus_assert_not_reached ("could not add string array");
+
+  if (!_dbus_marshal_dict (&str, DBUS_BIG_ENDIAN, dict))
+    _dbus_assert_not_reached ("could not marshal dict");
+  
+  dbus_dict_unref (dict);
+  
+  if (!_dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos, &dict))
+    _dbus_assert_not_reached ("could not demarshal dict");
+
+  if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
+      !our_bool)
+    _dbus_assert_not_reached ("could not get boolean value");
+
+  if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
+    _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
+  
+  if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
+    _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
+
+  if (!dbus_dict_get_double (dict, "double", &our_double)
+      || our_double != 3.14159)
+     _dbus_assert_not_reached ("could not get double value or double values differ");
+
+  if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
+    _dbus_assert_not_reached ("could not get string value or string values differ");
+
+  if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
+      len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
+    _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
 
+  if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
+      len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
+    _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
+
+  if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
+      len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
+    _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
+
+  if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
+      len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
+    _dbus_assert_not_reached ("could not get double array value or double array values differ");
+
+  if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
+    _dbus_assert_not_reached ("could not get string array value");
+
+  if (len != 4)
+    _dbus_assert_not_reached ("string array lengths differ");
+
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (our_string_array[i], string_array[i]) != 0)
+       _dbus_assert_not_reached ("string array fields differ");
+    }
+  
+  dbus_dict_unref (dict);
+  
   _dbus_string_free (&str);