2003-03-10 Anders Carlsson <andersca@codefactory.se>
authorAnders Carlsson <andersca@codefactory.se>
Mon, 10 Mar 2003 00:13:55 +0000 (00:13 +0000)
committerAnders Carlsson <andersca@codefactory.se>
Mon, 10 Mar 2003 00:13:55 +0000 (00:13 +0000)
* dbus/dbus-marshal.c:
(_dbus_marshal_set_string):
Take a length argument so we can marshal the correct string
length.

(_dbus_marshal_dict), (_dbus_demarshal_dict),
(_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg),
(_dbus_marshal_test):
* dbus/dbus-marshal.h:
Add support for marshalling and demarshalling dicts.

* dbus/dbus-message-builder.c: (_dbus_message_data_load):
Add support for TYPE DICT.

* dbus/dbus-message.c: (set_string_field):
Adjust header padding.

(dbus_message_append_args_valist), (dbus_message_append_dict),
(dbus_message_get_args_valist), (dbus_message_iter_get_arg_type),
(dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer),
(check_message_handling), (check_have_valid_message):
* dbus/dbus-message.h:
Add functions for setting and getting dicts.

* dbus/dbus-protocol.h:
Add DBUS_TYPE_DICT.

* dbus/dbus.h:
Add dbus-dict.h

* doc/dbus-specification.sgml:
Add information about how dicts are marshalled.

* test/data/invalid-messages/dict-with-nil-value.message:
* test/data/invalid-messages/too-short-dict.message:
* test/data/valid-messages/dict-simple.message:
* test/data/valid-messages/dict.message:
Add sample messages containing dicts.

13 files changed:
ChangeLog
dbus/dbus-marshal.c
dbus/dbus-marshal.h
dbus/dbus-message-builder.c
dbus/dbus-message.c
dbus/dbus-message.h
dbus/dbus-protocol.h
dbus/dbus.h
doc/dbus-specification.sgml
test/data/invalid-messages/dict-with-nil-value.message [new file with mode: 0644]
test/data/invalid-messages/too-short-dict.message [new file with mode: 0644]
test/data/valid-messages/dict-simple.message [new file with mode: 0644]
test/data/valid-messages/dict.message [new file with mode: 0644]

index 2020f1b..36f27b9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2003-03-10  Anders Carlsson  <andersca@codefactory.se>
+
+       * dbus/dbus-marshal.c: 
+       (_dbus_marshal_set_string):
+       Take a length argument so we can marshal the correct string
+       length.
+       
+       (_dbus_marshal_dict), (_dbus_demarshal_dict),
+       (_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg),
+       (_dbus_marshal_test):
+       * dbus/dbus-marshal.h:  
+       Add support for marshalling and demarshalling dicts.
+       
+       * dbus/dbus-message-builder.c: (_dbus_message_data_load):
+       Add support for TYPE DICT.
+       
+       * dbus/dbus-message.c: (set_string_field):
+       Adjust header padding.
+       
+       (dbus_message_append_args_valist), (dbus_message_append_dict),
+       (dbus_message_get_args_valist), (dbus_message_iter_get_arg_type),
+       (dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer),
+       (check_message_handling), (check_have_valid_message):
+       * dbus/dbus-message.h:
+       Add functions for setting and getting dicts.
+
+       * dbus/dbus-protocol.h:
+       Add DBUS_TYPE_DICT.
+       
+       * dbus/dbus.h:
+       Add dbus-dict.h
+       
+       * doc/dbus-specification.sgml:
+       Add information about how dicts are marshalled.
+       
+       * test/data/invalid-messages/dict-with-nil-value.message:
+       * test/data/invalid-messages/too-short-dict.message:
+       * test/data/valid-messages/dict-simple.message:
+       * test/data/valid-messages/dict.message:
+       Add sample messages containing dicts.
+
 2003-03-08  Anders Carlsson  <andersca@codefactory.se>
 
        * dbus/dbus-dict.h: Add DBUS_END_DECLS.
index f78757f..4c721f6 100644 (file)
@@ -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;
 }
@@ -496,6 +495,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,
+                                  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, value, len))
+             goto error;
+           
+           break;
+         }
+       default:
+         _dbus_warn ("unknwon 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.
  *
@@ -848,6 +1034,212 @@ _dbus_demarshal_string_array (const DBusString *str,
   return NULL;
 }
 
+/**
+ * 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
+ * @returns the demarshalled dict
+ */
+DBusDict *
+_dbus_demarshal_dict (const DBusString *str,
+                     int               byte_order,
+                     int               pos,
+                     int              *new_pos)
+{
+  char **keys;
+  int i, len;
+  DBusDict *dict;
+  
+  dict = dbus_dict_new ();
+  if (!dict)
+    return NULL;
+
+  keys = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len);
+  
+  if (!keys)
+    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;
+           
+           value = _dbus_demarshal_byte_array (str, byte_order, pos, &pos, &len);
+
+           if (!value)
+             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;
+           
+           value = _dbus_demarshal_int32_array (str, byte_order, pos, &pos, &len);
+
+           if (!value)
+             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;
+           
+           value = _dbus_demarshal_uint32_array (str, byte_order, pos, &pos, &len);
+
+           if (!value)
+             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;
+           
+           value = _dbus_demarshal_double_array (str, byte_order, pos, &pos, &len);
+
+           if (!value)
+             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_STRING_ARRAY:
+         {
+           char **value;
+           int len;
+           
+           value = _dbus_demarshal_string_array (str, byte_order, pos, &pos, &len);
+
+           if (!value)
+             goto error;
+
+           if (!dbus_dict_set_string_array (dict, keys[i], 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 dict;
+  
+ error:
+  dbus_free_string_array (keys);
+  dbus_dict_unref (dict);
+  return NULL;
+}
+
 /** 
  * Returns the position right after the end of an argument.  PERFORMS
  * NO VALIDATION WHATSOEVER. The message must have been previously
@@ -980,7 +1372,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");
@@ -1289,7 +1708,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;
@@ -1426,7 +1891,23 @@ _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))
     _dbus_assert_not_reached ("failed to init string");
@@ -1491,7 +1972,96 @@ _dbus_marshal_test (void)
   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);
+  
+  dict = _dbus_demarshal_dict (&str, DBUS_BIG_ENDIAN, pos, &pos);
+
+  if (!dbus_dict_get_boolean (dict, "boolean", &our_bool) ||
+      !our_bool)
+    _dbus_assert_not_reached ("could not get boolean value");
+
+  if (!dbus_dict_get_int32 (dict, "int32", &our_int) || our_int != 0x12345678)
+    _dbus_assert_not_reached ("could not get int32 value or int32 values differ");
+  
+  if (!dbus_dict_get_uint32 (dict, "uint32", &our_uint) || our_uint != 0x87654321)
+    _dbus_assert_not_reached ("could not get uint32 value or uint32 values differ");
+
+  if (!dbus_dict_get_double (dict, "double", &our_double)
+      || our_double != 3.14159)
+     _dbus_assert_not_reached ("could not get double value or double values differ");
+
+  if (!dbus_dict_get_string (dict, "string", &our_string) || strcmp (our_string, "test string") != 0)
+    _dbus_assert_not_reached ("could not get string value or string values differ");
+
+  if (!dbus_dict_get_boolean_array (dict, "boolean_array", &our_boolean_array, &len) ||
+      len != 4 || memcmp (boolean_array, our_boolean_array, 4) != 0)
+    _dbus_assert_not_reached ("could not get boolean array value or boolean array values differ");
+
+  if (!dbus_dict_get_int32_array (dict, "int32_array", &our_int32_array, &len) ||
+      len != 5 || memcmp (int32_array, our_int32_array, 5 * sizeof (dbus_int32_t)) != 0)
+    _dbus_assert_not_reached ("could not get int32 array value or int32 array values differ");
+
+  if (!dbus_dict_get_uint32_array (dict, "uint32_array", &our_uint32_array, &len) ||
+      len != 5 || memcmp (uint32_array, our_uint32_array, 5 * sizeof (dbus_uint32_t) ) != 0)
+    _dbus_assert_not_reached ("could not get uint32 array value or uint32 array values differ");
+
+  if (!dbus_dict_get_double_array (dict, "double_array", &our_double_array, &len) ||
+      len != 3 || memcmp (double_array, our_double_array, 3 * sizeof (double)) != 0)
+    _dbus_assert_not_reached ("could not get double array value or double array values differ");
+
+  if (!dbus_dict_get_string_array (dict, "string_array", &our_string_array, &len))
+    _dbus_assert_not_reached ("could not get string array value");
+
+  if (len != 4)
+    _dbus_assert_not_reached ("string array lengths differ");
+
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (our_string_array[i], string_array[i]) != 0)
+       _dbus_assert_not_reached ("string array fields differ");
+    }
+  
+  dbus_dict_unref (dict);
+  
   _dbus_string_free (&str);
   
       
index cedca6b..156ad09 100644 (file)
@@ -25,6 +25,7 @@
 #define DBUS_MARSHAL_H
 
 #include <config.h>
+#include <dbus/dbus-dict.h>
 #include <dbus/dbus-protocol.h>
 #include <dbus/dbus-types.h>
 #include <dbus/dbus-string.h>
@@ -88,7 +89,8 @@ void        _dbus_marshal_set_uint32 (DBusString       *str,
 dbus_bool_t _dbus_marshal_set_string (DBusString       *str,
                                       int               byte_order,
                                       int               offset,
-                                      const DBusString *value);
+                                      const DBusString *value,
+                                     int               len);
 
 
 dbus_bool_t _dbus_marshal_int32       (DBusString          *str,
@@ -123,48 +125,56 @@ dbus_bool_t _dbus_marshal_string_array (DBusString          *str,
                                        int                  byte_order,
                                        const char         **value,
                                        int                  len);
+dbus_bool_t _dbus_marshal_dict         (DBusString          *str,
+                                       int                  byte_order,
+                                       DBusDict            *dict);
 
 double         _dbus_demarshal_double       (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos);
 dbus_int32_t   _dbus_demarshal_int32        (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos);
 dbus_uint32_t  _dbus_demarshal_uint32       (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos);
 char *         _dbus_demarshal_string       (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos);
 unsigned char *_dbus_demarshal_byte_array   (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos,
-                                             int              *array_len);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos,
+                                            int              *array_len);
 dbus_int32_t * _dbus_demarshal_int32_array  (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos,
-                                             int              *array_len);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos,
+                                            int              *array_len);
 dbus_uint32_t *_dbus_demarshal_uint32_array (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos,
-                                             int              *array_len);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos,
+                                            int              *array_len);
 double *       _dbus_demarshal_double_array (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos,
-                                             int              *array_len);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos,
+                                            int              *array_len);
 char **        _dbus_demarshal_string_array (const DBusString *str,
-                                             int               byte_order,
-                                             int               pos,
-                                             int              *new_pos,
-                                             int              *array_len);
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos,
+                                            int              *array_len);
+DBusDict *     _dbus_demarshal_dict         (const DBusString *str,
+                                            int               byte_order,
+                                            int               pos,
+                                            int              *new_pos);
+
 
 
 dbus_bool_t _dbus_marshal_get_arg_end_pos (const DBusString *str,
index 3501da9..54b5de7 100644 (file)
@@ -648,6 +648,8 @@ _dbus_message_data_load (DBusString       *dest,
             code = DBUS_TYPE_DOUBLE;
           else if (_dbus_string_starts_with_c_str (&line, "STRING"))
             code = DBUS_TYPE_STRING;
+          else if (_dbus_string_starts_with_c_str (&line, "DICT"))
+            code = DBUS_TYPE_DICT;
           else
             {
               const char *s;
index db1b94b..a25480c 100644 (file)
@@ -493,15 +493,21 @@ set_string_field (DBusMessage *message,
       DBusString v;
       int old_len;
       int new_len;
+      int len;
+      
+      clear_header_padding (message);
       
       old_len = _dbus_string_get_length (&message->header);
 
+      len = strlen (value);
+      
       _dbus_string_init_const_len (&v, value,
-                                   strlen (value) + 1); /* include nul */
+                                  len + 1); /* include nul */
       if (!_dbus_marshal_set_string (&message->header,
                                      message->byte_order,
-                                     offset, &v))
-        return FALSE;
+                                     offset, &v,
+                                    len))
+        goto failed;
       
       new_len = _dbus_string_get_length (&message->header);
 
@@ -509,7 +515,19 @@ set_string_field (DBusMessage *message,
                             offset,
                             new_len - old_len);
 
+      if (!append_header_padding (message))
+       goto failed;
+      
       return TRUE;
+
+    failed:
+      /* this must succeed because it was allocated on function entry and
+       * DBusString doesn't ever realloc smaller
+       */
+      if (!append_header_padding (message))
+       _dbus_assert_not_reached ("failed to reappend header padding");
+
+      return FALSE;
     }
 }
 
@@ -1162,7 +1180,15 @@ dbus_message_append_args_valist (DBusMessage *message,
              goto enomem;
          }
          break;
-         
+       case DBUS_TYPE_DICT:
+         {
+           DBusDict *dict;
+
+           dict = va_arg (var_args, DBusDict *);
+
+           if (!dbus_message_append_dict (message, dict))
+             goto enomem;
+         }
        default:
          _dbus_warn ("Unknown field type %d\n", type);
        }
@@ -1485,6 +1511,31 @@ dbus_message_append_string_array (DBusMessage *message,
 }
 
 /**
+ * Appends a dict to the message.
+ *
+ * @param message the message
+ * @param dict the dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_append_dict (DBusMessage *message,
+                         DBusDict    *dict)
+{
+  _dbus_assert (!message->locked);
+
+  if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT))
+    return FALSE;
+
+  if (!_dbus_marshal_dict (&message->body, message->byte_order, dict))
+    {
+      _dbus_string_shorten (&message->body, 1);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/**
  * 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
@@ -1696,6 +1747,16 @@ dbus_message_get_args_valist (DBusMessage *message,
              return DBUS_RESULT_NO_MEMORY;
            break;
          }
+       case DBUS_TYPE_DICT:
+         {
+           DBusDict **dict;
+
+           dict = va_arg (var_args, DBusDict **);
+
+           if (!dbus_message_iter_get_dict (iter, dict))
+             return DBUS_RESULT_NO_MEMORY;
+           break;
+         }
        default:          
          _dbus_warn ("Unknown field type %d\n", spec_type);
        }
@@ -1850,7 +1911,7 @@ dbus_message_iter_get_arg_type (DBusMessageIter *iter)
 
   _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
 
-  if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
+  if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
     return *data;
 
   return DBUS_TYPE_INVALID;
@@ -2062,7 +2123,7 @@ dbus_message_iter_get_double_array  (DBusMessageIter *iter,
  * @param iter the iterator
  * @param value return location for array values
  * @param len return location for length of byte array
- * @returns the byte array
+ * @returns #TRUE on success
  */
 dbus_bool_t
 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
@@ -2093,7 +2154,7 @@ dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
  * @param iter the iterator
  * @param value return location for string values
  * @param len return location for length of byte array
- * @returns the byte array
+ * @returns #TRUE on success
  */
 dbus_bool_t
 dbus_message_iter_get_string_array (DBusMessageIter *iter,
@@ -2112,6 +2173,30 @@ dbus_message_iter_get_string_array (DBusMessageIter *iter,
 }
 
 /**
+ * Returns the dict that the iterator may point to.
+ * Note that you need to check that the iterator points
+ * to a dict prior to using this function.
+ *
+ * @param iter the iterator
+ * @param dict return location for dict
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_get_dict (DBusMessageIter *iter,
+                           DBusDict       **dict)
+{
+  _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT);
+
+  *dict = _dbus_demarshal_dict (&iter->message->body, iter->message->byte_order,
+                                iter->pos + 1, NULL);
+  
+  if (!*dict)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/**
  * Sets the message sender.
  *
  * @param message the message
@@ -2630,9 +2715,10 @@ _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
        */
       header_len = header_len_unsigned;
       body_len = body_len_unsigned;
-      
+
       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
         {
+         
           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
                          header_len);
           loader->corrupted = TRUE;
@@ -2654,8 +2740,8 @@ _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
           int next_arg;          
 
 #if 0
-         _dbus_verbose_bytes_of_string (&loader->data, 0, header_len);
-#endif
+         _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
+#endif   
          if (!decode_header_data (&loader->data, header_len, byte_order,
                                    fields, &header_padding))
            {
@@ -2899,7 +2985,7 @@ check_message_handling (DBusMessage *message)
   /* If we implement message_set_arg (message, n, value)
    * then we would want to test it here
    */
-  
+
   iter = dbus_message_get_args_iter (message);
   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
     {
@@ -2967,7 +3053,18 @@ check_message_handling (DBusMessage *message)
            dbus_free_string_array (values);
           }
           break;
-         
+
+       case DBUS_TYPE_DICT:
+         {
+           DBusDict *dict;
+
+           if (!dbus_message_iter_get_dict (iter, &dict))
+             return FALSE;
+
+           dbus_dict_unref (dict);
+         }
+         break;
+
        default:
          break;
         }
@@ -3025,6 +3122,7 @@ check_have_valid_message (DBusMessageLoader *loader)
  failed:
   if (message)
     dbus_message_unref (message);
+
   return retval;
 }
 
index bb2b620..4ea6306 100644 (file)
@@ -28,6 +28,7 @@
 #define DBUS_MESSAGE_H
 
 #include <dbus/dbus-macros.h>
+#include <dbus/dbus-dict.h>
 #include <dbus/dbus-types.h>
 #include <stdarg.h>
 
@@ -94,7 +95,8 @@ dbus_bool_t dbus_message_append_byte_array    (DBusMessage          *message,
 dbus_bool_t dbus_message_append_string_array  (DBusMessage          *message,
                                               const char          **value,
                                               int                   len);
-
+dbus_bool_t dbus_message_append_dict          (DBusMessage          *message,
+                                              DBusDict             *dict);
 
 DBusMessageIter *dbus_message_get_args_iter   (DBusMessage *message);
 DBusResultCode   dbus_message_get_args        (DBusMessage *message,
@@ -134,6 +136,8 @@ dbus_bool_t   dbus_message_iter_get_byte_array    (DBusMessageIter   *iter,
 dbus_bool_t   dbus_message_iter_get_string_array  (DBusMessageIter   *iter,
                                                   char            ***value,
                                                   int               *len);
+dbus_bool_t   dbus_message_iter_get_dict          (DBusMessageIter   *iter,
+                                                  DBusDict         **dict);
 
 DBUS_END_DECLS;
 
index 1a6fcb8..e0b0c98 100644 (file)
@@ -53,6 +53,7 @@ extern "C" {
 #define DBUS_TYPE_DOUBLE_ARRAY 10
 #define DBUS_TYPE_BYTE_ARRAY   11
 #define DBUS_TYPE_STRING_ARRAY 12
+#define DBUS_TYPE_DICT         13
   
 /* Header flags */
 #define DBUS_HEADER_FLAG_ERROR 0x1
index 025ccbb..1128d36 100644 (file)
@@ -29,6 +29,7 @@
 #include <dbus/dbus-address.h>
 #include <dbus/dbus-bus.h>
 #include <dbus/dbus-connection.h>
+#include <dbus/dbus-dict.h>
 #include <dbus/dbus-errors.h>
 #include <dbus/dbus-macros.h>
 #include <dbus/dbus-message.h>
index 0845d80..dba70ba 100644 (file)
                 <entry>UINT32 giving the number of values in the array, 
                   followed by the given number of STRING values.
                 </entry>
-              </row>
+              </row><row>
+               <entry>DICT</entry>
+               <entry>STRING_ARRAY with the keys, followed by the given
+                 number of values encoded as type code as a byte followed by the encoded value.
+                </entry>
+             </row>
             </tbody>
           </tgroup>
         </informaltable>
diff --git a/test/data/invalid-messages/dict-with-nil-value.message b/test/data/invalid-messages/dict-with-nil-value.message
new file mode 100644 (file)
index 0000000..8f89960
--- /dev/null
@@ -0,0 +1,12 @@
+# Message with lots of different argument types
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'nil', 'uint32' }
+TYPE NIL
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Body
diff --git a/test/data/invalid-messages/too-short-dict.message b/test/data/invalid-messages/too-short-dict.message
new file mode 100644 (file)
index 0000000..6df40b3
--- /dev/null
@@ -0,0 +1,11 @@
+# Message with lots of different argument types
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'int32', 'uint32' }
+TYPE UINT32
+UINT32 0x8765432
+END_LENGTH Body
diff --git a/test/data/valid-messages/dict-simple.message b/test/data/valid-messages/dict-simple.message
new file mode 100644 (file)
index 0000000..0b9d018
--- /dev/null
@@ -0,0 +1,11 @@
+# A simple dict
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'int32' }
+TYPE INT32
+INT32 0x12345678
+END_LENGTH Body
diff --git a/test/data/valid-messages/dict.message b/test/data/valid-messages/dict.message
new file mode 100644 (file)
index 0000000..0532e68
--- /dev/null
@@ -0,0 +1,29 @@
+# Dict with different values
+
+VALID_HEADER
+END_LENGTH Header
+ALIGN 8
+START_LENGTH Body
+TYPE DICT
+STRING_ARRAY { 'boolean', 'int32', 'uint32', 'double', 'string', 'boolean_array', 'int32_array', 'uint32_array', 'double_array', 'string_array' }
+TYPE BOOLEAN
+BYTE 1
+TYPE INT32
+INT32 0x12345678
+TYPE UINT32
+UINT32 0x8765432
+TYPE DOUBLE
+DOUBLE 3.141592653589
+TYPE STRING
+STRING 'This is a string'
+TYPE BOOLEAN_ARRAY
+BOOLEAN_ARRAY { true, false, false, true, false }
+TYPE INT32_ARRAY
+INT32_ARRAY { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10 }
+TYPE UINT32_ARRAY
+UINT32_ARRAY { 11, 12, 314, 1911, 57692, 1237, 2834 }
+TYPE DOUBLE_ARRAY
+DOUBLE_ARRAY { 0.1, 0.2, 3.1415926, 2.7183, 10.0, 9.99 }
+TYPE STRING_ARRAY
+STRING_ARRAY { 'Hello', 'This', 'Is', 'A', 'String', 'Array!' }
+END_LENGTH Body