Implement dbus_message_iter_get_element_count
authorChristian Dywan <christian.dywan@lanedo.com>
Thu, 23 Sep 2010 17:22:53 +0000 (19:22 +0200)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Wed, 13 May 2015 17:44:42 +0000 (18:44 +0100)
According unit tests are added to _dbus_message_test.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=30350
Reviewed-by: Havoc Pennington <hp@pobox.com>
dbus/dbus-message-util.c
dbus/dbus-message.c
dbus/dbus-message.h

index 0c0ab7c..ded7203 100644 (file)
@@ -1208,6 +1208,16 @@ _dbus_message_test (const char *test_data_dir)
   char **decomposed;
   DBusInitialFDs *initial_fds;
   dbus_bool_t ok;
+  char basic_types[] = DBUS_TYPE_BYTE_AS_STRING \
+                       DBUS_TYPE_BOOLEAN_AS_STRING \
+                       DBUS_TYPE_INT16_AS_STRING \
+                       DBUS_TYPE_INT32_AS_STRING \
+                       DBUS_TYPE_INT64_AS_STRING \
+                       DBUS_TYPE_UINT16_AS_STRING \
+                       DBUS_TYPE_UINT32_AS_STRING \
+                       DBUS_TYPE_UINT64_AS_STRING \
+                       DBUS_TYPE_DOUBLE_AS_STRING \
+                       DBUS_TYPE_STRING_AS_STRING;
 
   initial_fds = _dbus_check_fdleaks_enter ();
 
@@ -1598,6 +1608,52 @@ _dbus_message_test (const char *test_data_dir)
   _dbus_check_fdleaks_leave (initial_fds);
   initial_fds = _dbus_check_fdleaks_enter ();
 
+  /* Test enumeration of array elements */
+  for (i = strlen (basic_types) - 1; i > 0; i--)
+    {
+      int some;
+      char* signature = _dbus_strdup ("?");
+      signature[0] = basic_types[i];
+      s = "SomeThingToSay";
+      message = dbus_message_new_method_call ("de.ende.test",
+        "/de/ende/test", "de.ende.Test", "ArtistName");
+      _dbus_assert (message != NULL);
+      dbus_message_iter_init_append (message, &iter);
+      dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                        signature, &array_iter);
+      for (some = 0; some < 3; some++)
+        {
+          if (basic_types[i] == DBUS_TYPE_STRING)
+            dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &s);
+          else
+            dbus_message_iter_append_basic (&array_iter, basic_types[i], &some);
+        }
+      dbus_message_iter_close_container (&iter, &array_iter);
+      dbus_message_iter_init (message, &iter);
+      _dbus_assert (dbus_message_iter_get_element_count (&iter) == some);
+      dbus_message_unref (message);
+      dbus_free (signature);
+    }
+  /* Array of structs */
+  message = dbus_message_new_method_call ("de.ende.test",
+      "/de/ende/test", "de.ende.Test", "ArtistName");
+  _dbus_assert (message != NULL);
+  dbus_message_iter_init_append (message, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
+                                    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+                                    DBUS_TYPE_STRING_AS_STRING
+                                    DBUS_STRUCT_END_CHAR_AS_STRING, &array_iter);
+  dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT,
+                                    NULL, &struct_iter);
+  s = "SpamAndEggs";
+  dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &s);
+  dbus_message_iter_close_container (&array_iter, &struct_iter);
+  dbus_message_iter_close_container (&iter, &array_iter);
+  dbus_message_iter_init (message, &iter);
+  _dbus_assert (dbus_message_iter_get_element_count (&iter) == 1);
+  dbus_message_unref (message);
+  check_memleaks ();
+
   /* Check that we can abandon a container */
   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
                                          "/org/freedesktop/TestPath",
index d6fec0b..e14c264 100644 (file)
@@ -2325,20 +2325,55 @@ dbus_message_iter_get_basic (DBusMessageIter  *iter,
 }
 
 /**
+ * Returns the number of elements in the array-typed value pointed
+ * to by the iterator.
+ * Note that this function is O(1) for arrays of fixed-size types
+ * but O(n) for arrays of variable-length types such as strings,
+ * so it may be a bad idea to use it.
+ *
+ * @param iter the iterator
+ * @returns the number of elements in the array
+ */
+int dbus_message_iter_get_element_count (DBusMessageIter* iter)
+{
+  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
+  DBusTypeReader array;
+  int element_type;
+  int n_elements = 0;
+
+  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
+  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
+                            == DBUS_TYPE_ARRAY, 0);
+
+  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
+  _dbus_type_reader_recurse (&real->u.reader, &array);
+  if (dbus_type_is_fixed (element_type))
+    {
+      int alignment = _dbus_type_get_alignment (element_type);
+      int total_len = _dbus_type_reader_get_array_length (&array);
+      n_elements = total_len / alignment;
+    }
+  else
+    {
+      while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
+        {
+          ++n_elements;
+          _dbus_type_reader_next (&array);
+        }
+    }
+
+   return n_elements;
+}
+
+/**
  * Returns the number of bytes in the array as marshaled in the wire
  * protocol. The iterator must currently be inside an array-typed
  * value.
  *
  * This function is deprecated on the grounds that it is stupid.  Why
  * would you want to know how many bytes are in the array as marshaled
- * in the wire protocol?  For now, use the n_elements returned from
- * dbus_message_iter_get_fixed_array() instead, or iterate over the
- * array values and count them.
+ * in the wire protocol?  Use dbus_message_iter_get_element_count() instead.
  *
- * @todo introduce a variant of this get_n_elements that returns
- * the number of elements, though with a non-fixed array it will not
- * be very efficient, so maybe it's not good.
- * 
  * @param iter the iterator
  * @returns the number of bytes in the array
  */
index baa7d7b..3e33eb7 100644 (file)
@@ -226,6 +226,9 @@ void        dbus_message_iter_recurse          (DBusMessageIter *iter,
 DBUS_EXPORT
 void        dbus_message_iter_get_basic        (DBusMessageIter *iter,
                                                 void            *value);
+DBUS_EXPORT
+int         dbus_message_iter_get_element_count(DBusMessageIter *iter);
+
 #ifndef DBUS_DISABLE_DEPRECATED
 /* This function returns the wire protocol size of the array in bytes,
  * you do not want to know that probably