add "types only" TypeReader, will move to use a vtable instead of a flag in a minute
authorHavoc Pennington <hp@redhat.com>
Fri, 31 Dec 2004 00:06:34 +0000 (00:06 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 31 Dec 2004 00:06:34 +0000 (00:06 +0000)
dbus/dbus-marshal-recursive.c
dbus/dbus-marshal-recursive.h

index f9dab4445208d613fcec9bc50a2055a63979ac7f..0037d63e24ef7b410976792b4582e66f4f19a47f 100644 (file)
@@ -62,6 +62,7 @@ element_type_get_alignment (const DBusString *str,
 
 static void
 reader_init (DBusTypeReader    *reader,
+             dbus_bool_t        types_only,
              int                byte_order,
              const DBusString  *type_str,
              int                type_pos,
@@ -69,6 +70,8 @@ reader_init (DBusTypeReader    *reader,
              int                value_pos)
 {
   reader->byte_order = byte_order;
+  reader->types_only = types_only != FALSE;
+  reader->finished = FALSE;
   reader->type_str = type_str;
   reader->type_pos = type_pos;
   reader->value_str = value_str;
@@ -81,6 +84,7 @@ base_reader_recurse (DBusTypeReader *sub,
 {  
   /* point subreader at the same place as parent */
   reader_init (sub,
+               parent->types_only,
                parent->byte_order,
                parent->type_str,
                parent->type_pos,
@@ -98,11 +102,12 @@ struct_reader_recurse (DBusTypeReader *sub,
                                        sub->type_pos) == DBUS_STRUCT_BEGIN_CHAR);
   
   sub->type_pos += 1;
+
+  if (sub->types_only)
+    return;
   
   /* struct has 8 byte alignment */
   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 8);
-  
-  sub->u.strct.finished = FALSE;
 }
 
 static void
@@ -119,6 +124,20 @@ array_reader_recurse (DBusTypeReader *sub,
   /* point type_pos at the array element type */
   sub->type_pos += 1;
 
+  sub->u.array.element_type = first_type_in_signature (sub->type_str,
+                                                       sub->type_pos);
+
+  if (sub->types_only)
+    {
+      sub->u.array.start_pos = -1;
+      sub->u.array.len = _DBUS_INT_MAX;
+      
+      _dbus_verbose ("    type reader %p array element type = %s\n",
+                     sub,
+                     _dbus_type_to_string (sub->u.array.element_type));
+      return;
+    }
+  
   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
       
   _dbus_demarshal_basic_type (sub->value_str,
@@ -133,9 +152,7 @@ array_reader_recurse (DBusTypeReader *sub,
                                           sub->type_pos);
       
   sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
-
-  sub->u.array.element_type = first_type_in_signature (sub->type_str,
-                                                       sub->type_pos);
+  
   sub->u.array.start_pos = sub->value_pos;
 
   _dbus_verbose ("    type reader %p array start = %d array len = %d array element type = %s\n",
@@ -152,6 +169,8 @@ variant_reader_recurse (DBusTypeReader *sub,
   int sig_len;
 
   _dbus_assert (!_dbus_type_reader_array_is_empty (parent));
+  /* you can't go into a variant types-only since the type is in the value */
+  _dbus_assert (!parent->types_only);
   
   base_reader_recurse (sub, parent);
 
@@ -190,7 +209,7 @@ struct_reader_get_current_type (DBusTypeReader *reader)
 {
   int t;
   
-  if (reader->u.strct.finished)
+  if (reader->finished)
     t = DBUS_TYPE_INVALID;
   else
     t = first_type_in_signature (reader->type_str,
@@ -203,21 +222,32 @@ static int
 array_reader_get_current_type (DBusTypeReader *reader)
 {
   int t;
-  int end_pos;
-  
-  /* return the array element type if elements remain, and
-   * TYPE_INVALID otherwise
-   */
-  
-  end_pos = reader->u.array.start_pos + reader->u.array.len;
-  
-  _dbus_assert (reader->value_pos <= end_pos);
-  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
-  
-  if (reader->value_pos < end_pos)
-    t = reader->u.array.element_type;
+
+  if (reader->types_only)
+    {
+      if (reader->finished)
+        t = DBUS_TYPE_INVALID;
+      else
+        t = reader->u.array.element_type;
+    }
   else
-    t = DBUS_TYPE_INVALID;
+    {
+      int end_pos;
+      
+      /* return the array element type if elements remain, and
+       * TYPE_INVALID otherwise
+       */
+      
+      end_pos = reader->u.array.start_pos + reader->u.array.len;
+      
+      _dbus_assert (reader->value_pos <= end_pos);
+      _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
+      
+      if (reader->value_pos < end_pos)
+        t = reader->u.array.element_type;
+      else
+        t = DBUS_TYPE_INVALID;
+    }
 
   return t;
 }
@@ -302,23 +332,29 @@ base_reader_next (DBusTypeReader *reader,
         
         /* Now we are at the end of this container */
         reader->type_pos = sub.type_pos;
-        reader->value_pos = sub.value_pos;
+
+        if (!reader->types_only)
+          reader->value_pos = sub.value_pos;
       }
       break;
       
     case DBUS_TYPE_ARRAY:
-      {
-        skip_array_values (first_type_in_signature (reader->type_str,
-                                                    reader->type_pos + 1),
-                           reader->value_str, &reader->value_pos, reader->byte_order);
+      {        
+        if (!reader->types_only)
+          skip_array_values (first_type_in_signature (reader->type_str,
+                                                      reader->type_pos + 1),
+                             reader->value_str, &reader->value_pos, reader->byte_order);
+
         skip_one_complete_type (reader->type_str, &reader->type_pos);
       }
       break;
       
     default:
-      _dbus_marshal_skip_basic_type (reader->value_str,
-                                     current_type, reader->byte_order,
-                                     &reader->value_pos);
+      if (!reader->types_only)
+        _dbus_marshal_skip_basic_type (reader->value_str,
+                                       current_type, reader->byte_order,
+                                       &reader->value_pos);
+      
       reader->type_pos += 1;
       break;
     }
@@ -341,7 +377,7 @@ struct_reader_next (DBusTypeReader *reader,
   if (t == DBUS_STRUCT_END_CHAR)
     {
       reader->type_pos += 1;
-      reader->u.strct.finished = TRUE;
+      reader->finished = TRUE;
     }
 }
 
@@ -349,49 +385,63 @@ static void
 array_reader_next (DBusTypeReader *reader,
                    int             current_type)
 {
-  /* Skip one array element */
-  int end_pos;
-
-  end_pos = reader->u.array.start_pos + reader->u.array.len;
-
-  _dbus_assert (reader->value_pos < end_pos);
-  _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
-
-  if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
+  if (reader->types_only)
     {
-      DBusTypeReader sub;
-          
-      /* Recurse into the struct */
-      _dbus_type_reader_recurse (reader, &sub);
-
-      /* Skip everything in this element */
-      while (_dbus_type_reader_next (&sub))
-        {
-          /* nothing */;
-        }
+      /* We have one "element" to be iterated over
+       * in each array, which is its element type.
+       * So the finished flag indicates whether we've
+       * iterated over it yet or not.
+       */
+      reader->finished = TRUE;
 
-      /* Now we are at the end of this element */
-      reader->value_pos = sub.value_pos;
-    }
-  else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
-    {
-      skip_array_values (first_type_in_signature (reader->type_str,
-                                                  reader->type_pos + 1),
-                         reader->value_str, &reader->value_pos, reader->byte_order);
+      return;
     }
   else
     {
-      _dbus_marshal_skip_basic_type (reader->value_str,
-                                     current_type, reader->byte_order,
-                                     &reader->value_pos);
-    }
+      /* Skip one array element */
+      int end_pos;
+      
+      end_pos = reader->u.array.start_pos + reader->u.array.len;
+      
+      _dbus_assert (reader->value_pos < end_pos);
+      _dbus_assert (reader->value_pos >= reader->u.array.start_pos);
+      
+      if (reader->u.array.element_type == DBUS_TYPE_STRUCT)
+        {
+          DBusTypeReader sub;
+          
+          /* Recurse into the struct */
+          _dbus_type_reader_recurse (reader, &sub);
+          
+          /* Skip everything in this element */
+          while (_dbus_type_reader_next (&sub))
+            {
+              /* nothing */;
+            }
+          
+          /* Now we are at the end of this element */
+          reader->value_pos = sub.value_pos;
+        }
+      else if (reader->u.array.element_type == DBUS_TYPE_ARRAY)
+        {
+          skip_array_values (first_type_in_signature (reader->type_str,
+                                                      reader->type_pos + 1),
+                             reader->value_str, &reader->value_pos, reader->byte_order);
+        }
+      else
+        {
+          _dbus_marshal_skip_basic_type (reader->value_str,
+                                         current_type, reader->byte_order,
+                                         &reader->value_pos);
+        }
 
-  _dbus_assert (reader->value_pos <= end_pos);
+      _dbus_assert (reader->value_pos <= end_pos);
       
-  if (reader->value_pos == end_pos)
-    {
-      skip_one_complete_type (reader->type_str,
-                              &reader->type_pos);
+      if (reader->value_pos == end_pos)
+        {
+          skip_one_complete_type (reader->type_str,
+                                  &reader->type_pos);
+        }
     }
 }
 
@@ -433,7 +483,7 @@ _dbus_type_reader_init (DBusTypeReader    *reader,
 {
   reader->klass = &body_reader_class;
   
-  reader_init (reader, byte_order, type_str, type_pos,
+  reader_init (reader, FALSE, byte_order, type_str, type_pos,
                value_str, value_pos);
   
   _dbus_verbose ("  type reader %p init type_pos = %d value_pos = %d remaining sig '%s'\n",
@@ -441,6 +491,21 @@ _dbus_type_reader_init (DBusTypeReader    *reader,
                  _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
 }
 
+void
+_dbus_type_reader_init_types_only (DBusTypeReader    *reader,
+                                   const DBusString  *type_str,
+                                   int                type_pos)
+{
+  reader->klass = &body_reader_class;
+  
+  reader_init (reader, TRUE, DBUS_COMPILER_BYTE_ORDER /* irrelevant */,
+               type_str, type_pos, NULL, _DBUS_INT_MAX /* crashes if we screw up */);
+  
+  _dbus_verbose ("  type reader %p init types only type_pos = %d remaining sig '%s'\n",
+                 reader, reader->type_pos,
+                 _dbus_string_get_const_data_len (reader->type_str, reader->type_pos, 0));
+}
+
 int
 _dbus_type_reader_get_current_type (DBusTypeReader *reader)
 {
@@ -466,8 +531,8 @@ _dbus_type_reader_array_is_empty (DBusTypeReader *reader)
   dbus_uint32_t array_len;
   int len_pos;
   
-  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY,
-                            TRUE);
+  _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_ARRAY);
+  _dbus_assert (!reader->types_only);
 
   len_pos = _DBUS_ALIGN_VALUE (reader->value_pos, 4);
   
@@ -486,6 +551,8 @@ _dbus_type_reader_read_basic (DBusTypeReader    *reader,
 {
   int t;
   int next;
+
+  _dbus_assert (!reader->types_only);
   
   t = _dbus_type_reader_get_current_type (reader);
   
@@ -507,7 +574,7 @@ _dbus_type_reader_read_array_of_basic (DBusTypeReader    *reader,
                                        void             **array,
                                        int               *array_len)
 {
-  
+  _dbus_assert (!reader->types_only);  
   
 }
 
index 8e50fdc98bb7ed5da254b880286b828fa58eb5f8..10108d1f3b1a357aa36cf51c3d7de1c69c6ae826 100644 (file)
@@ -38,7 +38,12 @@ typedef struct DBusTypeReaderClass DBusTypeReaderClass;
 struct DBusTypeReader
 {
   dbus_uint32_t byte_order : 8;
-  
+
+  dbus_uint32_t types_only : 1; /* iterate over types not values */
+
+  dbus_uint32_t finished : 1;   /* marks we're at end iterator for cases
+                                 * where we don't have another way to tell
+                                 */
   const DBusString *type_str;
   int type_pos;
   const DBusString *value_str;
@@ -52,10 +57,6 @@ struct DBusTypeReader
       dbus_uint32_t len;
       int element_type;
     } array;
-
-    struct {
-      dbus_uint32_t finished : 1;
-    } strct;
   } u;
 };
 
@@ -87,6 +88,9 @@ void        _dbus_type_reader_init                (DBusTypeReader    *reader,
                                                    int                type_pos,
                                                    const DBusString  *value_str,
                                                    int                value_pos);
+void        _dbus_type_reader_init_types_only     (DBusTypeReader    *reader,
+                                                   const DBusString  *type_str,
+                                                   int                type_pos);
 int         _dbus_type_reader_get_current_type    (DBusTypeReader    *reader);
 dbus_bool_t _dbus_type_reader_array_is_empty      (DBusTypeReader    *reader);
 void        _dbus_type_reader_read_basic          (DBusTypeReader    *reader,