structs, custom type

Olivier Andrieu oliv__a@users.sourceforge.net
Thu Mar 11 18:47:35 PST 2004


--5pXtTrWZSE
Content-Type: text/plain; charset=us-ascii
Content-Description: message body and .signature
Content-Transfer-Encoding: 7bit

Hi,

 Havoc Pennington [Wednesday 10 March 2004] :
 >
 > On Wed, 2004-03-10 at 13:51, Olivier Andrieu wrote:
 > > That's a weird idea (I think) : I thought the DBUS_TYPE_CUSTOM
 > > was intended for application-specific binary data. If you start
 > > to put dbus typecodes in the CUSTOM data that means apps (and
 > > bindings) will have to be aware of the dbus protocol (typecodes,
 > > data representation, etc.)
 > 
 > Type custom could be:
 >  name = org.freedesktop.Point
 >  type = struct of int, int
 >  data = 10, 20

OK. Actually right now it's quite easy to encode it just like a custom
(i.e. a name + a length + data) but with a succession of arguments in
place of a dumb byte array. It will probably be easier to move type
information at the beginning once this is done also for the whole
message.

The attached patch adds this API :

dbus_bool_t dbus_message_iter_init_tuple_iterator (DBusMessageIter   *iter,
						   DBusMessageIter   *tuple_iter,
						   char             **name);
dbus_bool_t dbus_message_iter_append_tuple        (DBusMessageIter      *iter,
						   DBusMessageIter      *tuple_iter,
						   const char           *name);

It also fixes a bug in _dbus_marshal_get_arg_end_pos for custom types
(it passed the test because the custom value happened to be the last
one in the message !).

-- 
   Olivier

--5pXtTrWZSE
Content-Type: text/plain
Content-Disposition: attachment;
	filename="dbus-tuple.patch"
Content-Transfer-Encoding: 7bit

Index: dbus/dbus-protocol.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-protocol.h,v
retrieving revision 1.25
diff -u -u -r1.25 dbus-protocol.h
--- dbus/dbus-protocol.h	2 Dec 2003 10:44:21 -0000	1.25
+++ dbus/dbus-protocol.h	11 Mar 2004 18:16:37 -0000
@@ -54,8 +54,9 @@
 #define DBUS_TYPE_ARRAY         ((int) 'a')
 #define DBUS_TYPE_DICT          ((int) 'm')
 #define DBUS_TYPE_OBJECT_PATH   ((int) 'o')
+#define DBUS_TYPE_TUPLE         ((int) 'p')
 
-#define DBUS_NUMBER_OF_TYPES    (13)
+#define DBUS_NUMBER_OF_TYPES    (14)
 
 /* Max length in bytes of a service or interface or member name */
 #define DBUS_MAXIMUM_NAME_LENGTH 256
Index: dbus/dbus-message.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.h,v
retrieving revision 1.49
diff -u -u -r1.49 dbus-message.h
--- dbus/dbus-message.h	2 Dec 2003 10:44:21 -0000	1.49
+++ dbus/dbus-message.h	11 Mar 2004 18:16:37 -0000
@@ -172,6 +172,9 @@
 void        dbus_message_iter_init_array_iterator (DBusMessageIter   *iter,
 						   DBusMessageIter   *array_iter,
 						   int               *array_type);
+dbus_bool_t dbus_message_iter_init_tuple_iterator (DBusMessageIter   *iter,
+						   DBusMessageIter   *tuple_iter,
+						   char             **name);
 void        dbus_message_iter_init_dict_iterator  (DBusMessageIter   *iter,
 						   DBusMessageIter   *dict_iter);
 dbus_bool_t dbus_message_iter_get_byte_array      (DBusMessageIter   *iter,
@@ -235,6 +238,9 @@
 dbus_bool_t dbus_message_iter_append_array         (DBusMessageIter      *iter,
 						    DBusMessageIter      *array_iter,
 						    int                   element_type);
+dbus_bool_t dbus_message_iter_append_tuple         (DBusMessageIter      *iter,
+						    DBusMessageIter      *tuple_iter,
+						    const char           *name);
 dbus_bool_t dbus_message_iter_append_dict          (DBusMessageIter      *iter,
 						    DBusMessageIter      *dict_iter);
 
Index: dbus/dbus-message.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.c,v
retrieving revision 1.119
diff -u -u -r1.119 dbus-message.c
--- dbus/dbus-message.c	8 Mar 2004 10:29:16 -0000	1.119
+++ dbus/dbus-message.c	11 Mar 2004 18:16:38 -0000
@@ -111,7 +111,8 @@
 enum {
   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
   DBUS_MESSAGE_ITER_TYPE_ARRAY,
-  DBUS_MESSAGE_ITER_TYPE_DICT
+  DBUS_MESSAGE_ITER_TYPE_DICT,
+  DBUS_MESSAGE_ITER_TYPE_TUPLE
 };
 
 /** typedef for internals of message iterator */
@@ -2440,6 +2441,7 @@
   switch (iter->type)
     {
     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
+    case DBUS_MESSAGE_ITER_TYPE_TUPLE:
       data = _dbus_string_get_const_data_len (&iter->message->body,
 					      iter->pos, 1);
       if (_dbus_type_is_valid (*data))
@@ -2584,6 +2586,7 @@
   
   switch (iter->type)
     {
+    case DBUS_MESSAGE_ITER_TYPE_TUPLE:
     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
       _array_type_pos = iter->pos + 1;
       break;
@@ -2989,6 +2992,58 @@
 
 
 /**
+ * Initializes an iterator for the tuple that the iterator
+ * may point to. Note that you need to check that the iterator
+ * points to a tuple prior to using this function.
+ *
+ * @param iter the iterator
+ * @param tuple_iter pointer to an iterator to initialize
+ * @param name return location for the name of the tuple
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_init_tuple_iterator (DBusMessageIter *iter,
+				       DBusMessageIter *tuple_iter,
+				       char **name)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *tuple_real = (DBusMessageRealIter *)tuple_iter;
+  int type, pos, len_pos, len;
+  char *_name;
+
+  _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
+
+  pos = dbus_message_iter_get_data_start (real, &type);
+  
+  _dbus_assert (type == DBUS_TYPE_TUPLE);
+
+  _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
+				  pos, &pos);
+
+  if (_name == NULL)
+    return FALSE;
+  if (name)
+    *name = _name;
+
+  len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
+  len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
+				pos, &pos);
+  
+  tuple_real->parent_iter = real;
+  tuple_real->message = real->message;
+  tuple_real->changed_stamp = real->message->changed_stamp;
+  
+  tuple_real->type = DBUS_MESSAGE_ITER_TYPE_TUPLE;
+  tuple_real->pos = pos;
+  tuple_real->end = pos + len;
+  
+  tuple_real->container_start = pos;
+  tuple_real->container_length_pos = len_pos;
+
+  return TRUE;
+}
+
+/**
  * Initializes an iterator for the dict that the iterator
  * may point to. Note that you need to check that the iterator
  * points to a dict prior to using this function.
@@ -3456,6 +3511,7 @@
   const char *data;
   switch (iter->type)
     {
+    case DBUS_MESSAGE_ITER_TYPE_TUPLE:
     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
       if (!_dbus_string_append_byte (&iter->message->signature, type))
         return FALSE;
@@ -3508,6 +3564,7 @@
 
   /* Set container length */
   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
+      iter->type == DBUS_MESSAGE_ITER_TYPE_TUPLE ||
       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
     _dbus_marshal_set_uint32 (&iter->message->body,
 			      iter->message->byte_order,
@@ -4016,6 +4073,61 @@
   return TRUE;
 }
 
+
+/**
+ * Appends an tuple to the message and initializes an iterator that
+ * can be used to append to the tuple.
+ *
+ * @param iter an iterator pointing to the end of the message
+ * @param tuple_iter pointer to an iter that will be initialized
+ * @param name the name of the tuple
+ * @returns #TRUE on success
+ */
+dbus_bool_t
+dbus_message_iter_append_tuple (DBusMessageIter      *iter,
+				DBusMessageIter      *tuple_iter,
+				const char           *name)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusMessageRealIter *tuple_real = (DBusMessageRealIter *)tuple_iter;
+  int len_pos;
+
+  _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
+
+  if (!dbus_message_iter_append_type (real, DBUS_TYPE_TUPLE))
+    return FALSE;
+
+  if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+   
+  len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
+
+  /* Empty length for now, backfill later */
+  if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
+    {
+      _dbus_string_set_length (&real->message->body, real->pos);
+      return FALSE;
+    }
+  
+  tuple_real->parent_iter = real;
+  tuple_real->message = real->message;
+  tuple_real->changed_stamp = real->message->changed_stamp;
+  
+  tuple_real->type = DBUS_MESSAGE_ITER_TYPE_TUPLE;
+  tuple_real->pos = _dbus_string_get_length (&real->message->body);
+  tuple_real->end = tuple_real->end;
+  
+  tuple_real->container_start = tuple_real->pos;
+  tuple_real->container_length_pos = len_pos;
+
+  dbus_message_iter_append_done (tuple_real);
+  
+  return TRUE;
+}
+
 /**
  * Appends a dict to the message and initializes an iterator that
  * can be used to append to the dict.
@@ -5860,6 +5972,57 @@
   if (!dbus_message_iter_next (&iter))
     _dbus_assert_not_reached ("Reached end of arguments");
   
+  /* tuple */
+  {
+    DBusMessageIter tuple;
+
+    if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_TUPLE)
+      _dbus_assert_not_reached ("not tuple type");
+
+    dbus_message_iter_init_tuple_iterator (&iter, &tuple, &str);
+
+    if (strcmp (str, "org.freedesktop.DBus.TestTuple") != 0)
+      _dbus_assert_not_reached ("Wrong tuple name");
+    dbus_free (str);
+
+    str = dbus_message_iter_get_string (&tuple);
+    if (strcmp (str, "Test string") != 0)
+      _dbus_assert_not_reached ("Strings differ");
+    dbus_free (str);
+
+    if (!dbus_message_iter_next (&tuple))
+      _dbus_assert_not_reached ("Reached end of arguments");
+
+    if (dbus_message_iter_get_arg_type (&tuple) != DBUS_TYPE_INT32)
+      _dbus_assert_not_reached ("Argument type isn't int32");
+    
+    if (dbus_message_iter_get_int32 (&tuple) != -0x12345678)
+      _dbus_assert_not_reached ("Signed integers differ");
+
+    if (!dbus_message_iter_next (&tuple))
+      _dbus_assert_not_reached ("Reached end of fields");
+  
+    if (dbus_message_iter_get_arg_type (&tuple) != DBUS_TYPE_UINT32)
+      _dbus_assert_not_reached ("Argument type isn't int32");
+
+    if (dbus_message_iter_get_uint32 (&tuple) != 0xedd1e)
+      _dbus_assert_not_reached ("Unsigned integers differ");
+
+    if (!dbus_message_iter_next (&tuple))
+      _dbus_assert_not_reached ("Reached end of arguments");
+
+    if (dbus_message_iter_get_arg_type (&tuple) != DBUS_TYPE_DOUBLE)
+      _dbus_assert_not_reached ("Argument type isn't double");
+
+    if (dbus_message_iter_get_double (&tuple) != 3.14159)
+      _dbus_assert_not_reached ("Doubles differ");
+
+    if (dbus_message_iter_next (&tuple))
+      _dbus_assert_not_reached ("Didn't reach end of tuple");
+
+    if (!dbus_message_iter_next (&iter))
+      _dbus_assert_not_reached ("Reached end of arguments");
+  }
 
   /* dict */
 
@@ -6003,6 +6166,12 @@
   dbus_free (str);
   dbus_free (data);
   
+  if (!dbus_message_iter_next (&iter))
+    _dbus_assert_not_reached ("Reached end of arguments after custom");
+
+  if (dbus_message_iter_get_byte (&iter) != 0xF0)
+    _dbus_assert_not_reached ("wrong value after custom");
+
   if (dbus_message_iter_next (&iter))
     _dbus_assert_not_reached ("Didn't reach end of arguments");
 }
@@ -6117,6 +6286,25 @@
 	  }
       }
       break;
+    case DBUS_TYPE_TUPLE:
+      {
+	char *name;
+	int entry_type;
+	dbus_message_iter_init_tuple_iterator (iter, &child_iter, &name);
+
+	while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
+	  {
+	    if (!check_message_handling_type (&child_iter, entry_type))
+	      {
+		_dbus_warn ("error in tuple element\n");
+		return FALSE;
+	      }
+	  
+	    if (!dbus_message_iter_next (&child_iter))
+	      break;
+	  }
+      }
+      break;
       
     default:
       _dbus_warn ("unknown type %d\n", type);
@@ -7108,6 +7296,13 @@
   dbus_message_iter_append_double (&child_iter, 1.5);
   dbus_message_iter_append_double (&child_iter, 2.5);
 
+  /* tuple */
+  dbus_message_iter_append_tuple (&iter, &child_iter, "org.freedesktop.DBus.TestTuple");
+  dbus_message_iter_append_string (&child_iter, "Test string");
+  dbus_message_iter_append_int32 (&child_iter, -0x12345678);
+  dbus_message_iter_append_uint32 (&child_iter, 0xedd1e);
+  dbus_message_iter_append_double (&child_iter, 3.14159);
+
   /* dict */
   dbus_message_iter_append_dict (&iter, &child_iter);
   dbus_message_iter_append_dict_key (&child_iter, "test");
@@ -7139,7 +7334,9 @@
 
   dbus_message_iter_append_custom (&iter, "MyTypeName",
                                    "data", 5);
-  
+
+  dbus_message_iter_append_byte (&iter, 0xF0);
+
   message_iter_test (message);
   
   /* Message loader test */
Index: dbus/dbus-marshal.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-marshal.c,v
retrieving revision 1.47
diff -u -u -r1.47 dbus-marshal.c
--- dbus/dbus-marshal.c	2 Dec 2003 10:44:21 -0000	1.47
+++ dbus/dbus-marshal.c	11 Mar 2004 18:16:38 -0000
@@ -1643,6 +1643,7 @@
       break;
 
     case DBUS_TYPE_CUSTOM:
+    case DBUS_TYPE_TUPLE:
       {
 	int len;
 	
@@ -1652,23 +1653,13 @@
 	*end_pos = pos + len + 1;
 	
 	/* Demarshal the data length */
-	len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
+	len = _dbus_demarshal_uint32 (str, byte_order, *end_pos, &pos);
 
 	*end_pos = pos + len;
       }
       break;
       
     case DBUS_TYPE_ARRAY:
-      {
-	int len;
-
-	/* Demarshal the length  */
-	len = _dbus_demarshal_uint32 (str, byte_order, pos, &pos);
-	
-	*end_pos = pos + len;
-      }
-      break;
-
     case DBUS_TYPE_DICT:
       {
 	int len;
@@ -1841,6 +1832,7 @@
     case DBUS_TYPE_CUSTOM:
     case DBUS_TYPE_ARRAY:
     case DBUS_TYPE_DICT:
+    case DBUS_TYPE_TUPLE:
       /* This clean recursion to validate_arg is what we
        * are doing logically for all types, but we don't
        * really want to call validate_arg for every byte
@@ -2197,6 +2189,52 @@
 	*end_pos = pos;
       }
       break;
+
+    case DBUS_TYPE_TUPLE:
+      {
+	int el_type;
+	int len;
+	int end;
+	
+	/* Demarshal the string length, which does NOT include
+         * nul termination
+         */
+	len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
+
+        if (!validate_string (str, pos, len, &pos))
+          return FALSE;
+
+	len = demarshal_and_validate_len (str, byte_order, pos, &pos);
+        if (len < 0)
+          return FALSE;
+
+	end = pos + len;
+	
+	while (pos < end)
+	  {
+	    if (!_dbus_marshal_validate_type (str, pos, &el_type, &pos))
+	      {
+		_dbus_verbose ("invalid tuple entry type at offset %d\n", pos);
+		return FALSE;
+	      }
+	    
+	    /* Validate element */
+	    if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
+					     el_type, -1, pos, &pos))
+	      return FALSE;
+	  }
+	
+	if (pos > end)
+	  {
+	    _dbus_verbose ("tuple contents exceed stated tuple length\n");
+	    return FALSE;
+	  }
+        
+	*end_pos = pos;
+      }
+      break;
       
     default:
       _dbus_verbose ("Unknown message arg type %d\n", type);
@@ -2232,6 +2270,7 @@
     case DBUS_TYPE_ARRAY:
     case DBUS_TYPE_DICT:
     case DBUS_TYPE_OBJECT_PATH:
+    case DBUS_TYPE_TUPLE:
       return TRUE;
       
     default:

--5pXtTrWZSE--




More information about the dbus mailing list