Convert a{sv} helpers from Stats into generic utility code
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Mon, 24 Jun 2013 12:41:33 +0000 (13:41 +0100)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Tue, 25 Jun 2013 11:25:51 +0000 (12:25 +0100)
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54445
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
bus/stats.c
cmake/dbus/CMakeLists.txt
dbus/Makefile.am
dbus/dbus-asv-util.c [new file with mode: 0644]
dbus/dbus-asv-util.h [new file with mode: 0644]

index 78f27e9..0c71a54 100644 (file)
@@ -1,5 +1,8 @@
 /* stats.c - statistics from the bus driver
  *
+ * Copyright © 2011-2012 Nokia Corporation
+ * Copyright © 2012-2013 Collabora Ltd.
+ *
  * Licensed under the Academic Free License version 2.1
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,6 +24,7 @@
 #include <config.h>
 #include "stats.h"
 
+#include <dbus/dbus-asv-util.h>
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-connection-internal.h>
 
 
 #ifdef DBUS_ENABLE_STATS
 
-static DBusMessage *
-new_asv_reply (DBusMessage      *message,
-               DBusMessageIter  *iter,
-               DBusMessageIter  *arr_iter)
-{
-  DBusMessage *reply = dbus_message_new_method_return (message);
-
-  if (reply == NULL)
-    return NULL;
-
-  dbus_message_iter_init_append (reply, iter);
-
-  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}",
-                                         arr_iter))
-    {
-      dbus_message_unref (reply);
-      return NULL;
-    }
-
-  return reply;
-}
-
-static dbus_bool_t
-open_asv_entry (DBusMessageIter *arr_iter,
-                DBusMessageIter *entry_iter,
-                const char      *key,
-                const char      *type,
-                DBusMessageIter *var_iter)
-{
-  if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY,
-                                         NULL, entry_iter))
-    return FALSE;
-
-  if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key))
-    {
-      dbus_message_iter_abandon_container (arr_iter, entry_iter);
-      return FALSE;
-    }
-
-  if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT,
-                                         type, var_iter))
-    {
-      dbus_message_iter_abandon_container (arr_iter, entry_iter);
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-static dbus_bool_t
-close_asv_entry (DBusMessageIter *arr_iter,
-                 DBusMessageIter *entry_iter,
-                 DBusMessageIter *var_iter)
-{
-  if (!dbus_message_iter_close_container (entry_iter, var_iter))
-    {
-      dbus_message_iter_abandon_container (arr_iter, entry_iter);
-      return FALSE;
-    }
-
-  if (!dbus_message_iter_close_container (arr_iter, entry_iter))
-    return FALSE;
-
-  return TRUE;
-}
-
-static dbus_bool_t
-close_asv_reply (DBusMessageIter *iter,
-                 DBusMessageIter *arr_iter)
-{
-  return dbus_message_iter_close_container (iter, arr_iter);
-}
-
-static void
-abandon_asv_entry (DBusMessageIter *arr_iter,
-                   DBusMessageIter *entry_iter,
-                   DBusMessageIter *var_iter)
-{
-  dbus_message_iter_abandon_container (entry_iter, var_iter);
-  dbus_message_iter_abandon_container (arr_iter, entry_iter);
-}
-
-static void
-abandon_asv_reply (DBusMessageIter *iter,
-                 DBusMessageIter *arr_iter)
-{
-  dbus_message_iter_abandon_container (iter, arr_iter);
-}
-
-static dbus_bool_t
-asv_add_uint32 (DBusMessageIter *iter,
-                DBusMessageIter *arr_iter,
-                const char *key,
-                dbus_uint32_t value)
-{
-  DBusMessageIter entry_iter, var_iter;
-
-  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_UINT32_AS_STRING,
-                       &var_iter))
-    goto oom;
-
-  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32,
-                                       &value))
-    {
-      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
-      goto oom;
-    }
-
-  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
-    goto oom;
-
-  return TRUE;
-
-oom:
-  abandon_asv_reply (iter, arr_iter);
-  return FALSE;
-}
-
-static dbus_bool_t
-asv_add_string (DBusMessageIter *iter,
-                DBusMessageIter *arr_iter,
-                const char *key,
-                const char *value)
-{
-  DBusMessageIter entry_iter, var_iter;
-
-  if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_STRING_AS_STRING,
-                       &var_iter))
-    goto oom;
-
-  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING,
-                                       &value))
-    {
-      abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
-      goto oom;
-    }
-
-  if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
-    goto oom;
-
-  return TRUE;
-
-oom:
-  abandon_asv_reply (iter, arr_iter);
-  return FALSE;
-}
-
 dbus_bool_t
 bus_stats_handle_get_stats (DBusConnection *connection,
                             BusTransaction *transaction,
@@ -193,48 +50,50 @@ bus_stats_handle_get_stats (DBusConnection *connection,
 
   connections = bus_transaction_get_connections (transaction);
 
-  reply = new_asv_reply (message, &iter, &arr_iter);
+  reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
 
   if (reply == NULL)
     goto oom;
 
   /* Globals */
 
-  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
-    goto oom;
-
   _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
 
-  if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
-      !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
-                       in_free_list) ||
-      !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
-                       allocated))
-    goto oom;
+  if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolUsedBytes", in_use) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolCachedBytes", in_free_list) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "ListMemPoolAllocatedBytes", allocated))
+    {
+      _dbus_asv_abandon (&iter, &arr_iter);
+      goto oom;
+    }
 
   /* Connections */
 
-  if (!asv_add_uint32 (&iter, &arr_iter, "ActiveConnections",
+  if (!_dbus_asv_add_uint32 (&arr_iter, "ActiveConnections",
         bus_connections_get_n_active (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "IncompleteConnections",
+      !_dbus_asv_add_uint32 (&arr_iter, "IncompleteConnections",
         bus_connections_get_n_incomplete (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+      !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
         bus_connections_get_total_match_rules (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
         bus_connections_get_peak_match_rules (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRulesPerConnection",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRulesPerConnection",
         bus_connections_get_peak_match_rules_per_conn (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+      !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
         bus_connections_get_total_bus_names (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
         bus_connections_get_peak_bus_names (connections)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNamesPerConnection",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNamesPerConnection",
         bus_connections_get_peak_bus_names_per_conn (connections)))
-    goto oom;
+    {
+      _dbus_asv_abandon (&iter, &arr_iter);
+      goto oom;
+    }
 
   /* end */
 
-  if (!close_asv_reply (&iter, &arr_iter))
+  if (!_dbus_asv_close (&iter, &arr_iter))
     goto oom;
 
   if (!bus_transaction_send_from_driver (transaction, connection, reply))
@@ -290,25 +149,28 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
   stats_connection = bus_service_get_primary_owners_connection (service);
   _dbus_assert (stats_connection != NULL);
 
-  reply = new_asv_reply (message, &iter, &arr_iter);
+  reply = _dbus_asv_new_method_return (message, &iter, &arr_iter);
 
   if (reply == NULL)
     goto oom;
 
   /* Bus daemon per-connection stats */
 
-  if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++) ||
-      !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+  if (!_dbus_asv_add_uint32 (&arr_iter, "Serial", stats_serial++) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "MatchRules",
         bus_connection_get_n_match_rules (stats_connection)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakMatchRules",
         bus_connection_get_peak_match_rules (stats_connection)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+      !_dbus_asv_add_uint32 (&arr_iter, "BusNames",
         bus_connection_get_n_services_owned (stats_connection)) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakBusNames",
         bus_connection_get_peak_bus_names (stats_connection)) ||
-      !asv_add_string (&iter, &arr_iter, "UniqueName",
+      !_dbus_asv_add_uint32 (&arr_iter, "UniqueName",
         bus_connection_get_name (stats_connection)))
-    goto oom;
+    {
+      _dbus_asv_abandon (&iter, &arr_iter);
+      goto oom;
+    }
 
   /* DBusConnection per-connection stats */
 
@@ -318,21 +180,24 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
                               &out_messages, &out_bytes, &out_fds,
                               &out_peak_bytes, &out_peak_fds);
 
-  if (!asv_add_uint32 (&iter, &arr_iter, "IncomingMessages", in_messages) ||
-      !asv_add_uint32 (&iter, &arr_iter, "IncomingBytes", in_bytes) ||
-      !asv_add_uint32 (&iter, &arr_iter, "IncomingFDs", in_fds) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingFDs", in_peak_fds) ||
-      !asv_add_uint32 (&iter, &arr_iter, "OutgoingMessages", out_messages) ||
-      !asv_add_uint32 (&iter, &arr_iter, "OutgoingBytes", out_bytes) ||
-      !asv_add_uint32 (&iter, &arr_iter, "OutgoingFDs", out_fds) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
-      !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingFDs", out_peak_fds))
-    goto oom;
+  if (!_dbus_asv_add_uint32 (&arr_iter, "IncomingMessages", in_messages) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "IncomingBytes", in_bytes) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "IncomingFDs", in_fds) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakIncomingFDs", in_peak_fds) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "OutgoingMessages", out_messages) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "OutgoingBytes", out_bytes) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "OutgoingFDs", out_fds) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
+      !_dbus_asv_add_uint32 (&arr_iter, "PeakOutgoingFDs", out_peak_fds))
+    {
+      _dbus_asv_abandon (&iter, &arr_iter);
+      goto oom;
+    }
 
   /* end */
 
-  if (!close_asv_reply (&iter, &arr_iter))
+  if (!_dbus_asv_close (&iter, &arr_iter))
     goto oom;
 
   if (!bus_transaction_send_from_driver (transaction, caller_connection,
index 6b2d063..1d04d46 100644 (file)
@@ -149,6 +149,7 @@ set (DBUS_SHARED_HEADERS
 ### should be underscore-prefixed but don't really need 
 ### to be unless they move to DBUS_SHARED_SOURCES later)
 set (DBUS_UTIL_SOURCES
+       ${DBUS_DIR}/dbus-asv-util.c
        ${DBUS_DIR}/dbus-auth-script.c
        ${DBUS_DIR}/dbus-auth-util.c
        ${DBUS_DIR}/dbus-credentials-util.c
@@ -173,6 +174,7 @@ if (DBUS_BUILD_TESTS)
 endif (DBUS_BUILD_TESTS)
 
 set (DBUS_UTIL_HEADERS
+       ${DBUS_DIR}/dbus-asv-util.h
        ${DBUS_DIR}/dbus-auth-script.h
        ${DBUS_DIR}/dbus-mainloop.h
        ${DBUS_DIR}/dbus-message-factory.h
index 90c2c90..9628c83 100644 (file)
@@ -237,6 +237,8 @@ DBUS_SHARED_SOURCES=                                \
 ### should be underscore-prefixed but don't really need
 ### to be unless they move to DBUS_SHARED_SOURCES later)
 DBUS_UTIL_SOURCES=                             \
+       dbus-asv-util.c                         \
+       dbus-asv-util.h                         \
        dbus-auth-script.c                      \
        dbus-auth-script.h                      \
        dbus-auth-util.c                        \
diff --git a/dbus/dbus-asv-util.c b/dbus/dbus-asv-util.c
new file mode 100644 (file)
index 0000000..583e41f
--- /dev/null
@@ -0,0 +1,260 @@
+/* dbus-asv-util.c - utility functions for a{sv}
+ *
+ * Copyright © 2011-2012 Nokia Corporation
+ * Copyright © 2012-2013 Collabora Ltd.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <dbus/dbus.h>
+
+#include "dbus/dbus-asv-util.h"
+
+/**
+ * Convenience function to create a method-call reply whose type is a{sv}
+ * (map from string to variant).
+ *
+ * Append values with 0 or more sequences of _dbus_asv_open_entry(),
+ * appending a value to var_iter, and _dbus_asv_close_entry(),
+ * then close the a{sv} with _dbus_asv_close() or _dbus_asv_abandon().
+ *
+ * This must be paired with a call to _dbus_asv_close() or _dbus_asv_abandon().
+ *
+ * @param message a method call message
+ * @param iter an iterator which will be initialized to append to the message
+ * @param arr_iter an iterator which will be initialized to append to the array
+ * @returns a new message, or #NULL if not enough memory
+ */
+DBusMessage *
+_dbus_asv_new_method_return (DBusMessage      *message,
+                             DBusMessageIter  *iter,
+                             DBusMessageIter  *arr_iter)
+{
+  DBusMessage *reply = dbus_message_new_method_return (message);
+
+  if (reply == NULL)
+    return NULL;
+
+  dbus_message_iter_init_append (reply, iter);
+
+  if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}",
+                                         arr_iter))
+    {
+      dbus_message_unref (reply);
+      return NULL;
+    }
+
+  return reply;
+}
+
+/*
+ * Open a new entry in an a{sv} (map from string to variant).
+ *
+ * This must be paired with a call to either _dbus_asv_close_entry()
+ * or _dbus_asv_abandon_entry().
+ *
+ * If this function fails, the a{sv} must be abandoned, for instance
+ * with _dbus_asv_abandon().
+ *
+ * @param arr_iter the iterator which is appending to the array
+ * @param entry_iter will be initialized to append to the dict-entry
+ * @param key a UTF-8 key for the map
+ * @param type the type of the variant value, e.g. DBUS_TYPE_STRING_AS_STRING
+ * @param var_iter will be initialized to append (i.e. write) to the variant
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+static dbus_bool_t
+_dbus_asv_open_entry (DBusMessageIter *arr_iter,
+                      DBusMessageIter *entry_iter,
+                      const char      *key,
+                      const char      *type,
+                      DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY,
+                                         NULL, entry_iter))
+    return FALSE;
+
+  if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT,
+                                         type, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/*
+ * Closes an a{sv} entry after successfully appending the value.
+ *
+ * If this function fails, the a{sv} must be abandoned, for instance
+ * with _dbus_asv_abandon().
+ *
+ * @param arr_iter the iterator which is appending to the array
+ * @param entry_iter the iterator appending to the dict-entry, will be closed
+ * @param var_iter the iterator appending to the variant, will be closed
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+static dbus_bool_t
+_dbus_asv_close_entry (DBusMessageIter *arr_iter,
+                       DBusMessageIter *entry_iter,
+                       DBusMessageIter *var_iter)
+{
+  if (!dbus_message_iter_close_container (entry_iter, var_iter))
+    {
+      dbus_message_iter_abandon_container (arr_iter, entry_iter);
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_close_container (arr_iter, entry_iter))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Closes an a{sv} after successfully appending all values.
+ *
+ * If this function fails, you must abandon iter and whatever
+ * larger data structure (message, etc.) the a{sv} was embedded in.
+ *
+ * @param iter the iterator which is appending to the message or other data structure containing the a{sv}
+ * @param arr_iter the iterator appending to the array, will be closed
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_asv_close (DBusMessageIter *iter,
+                 DBusMessageIter *arr_iter)
+{
+  return dbus_message_iter_close_container (iter, arr_iter);
+}
+
+/*
+ * Closes an a{sv} entry after unsuccessfully appending a value.
+ * You must also abandon the a{sv} itself (for instance with
+ * _dbus_asv_abandon()), and abandon whatever larger data structure
+ * the a{sv} was embedded in.
+ *
+ * @param iter the iterator which is appending to the message or other data structure containing the a{sv}
+ * @param arr_iter the iterator appending to the array, will be closed
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+static void
+_dbus_asv_abandon_entry (DBusMessageIter *arr_iter,
+                         DBusMessageIter *entry_iter,
+                         DBusMessageIter *var_iter)
+{
+  dbus_message_iter_abandon_container (entry_iter, var_iter);
+  dbus_message_iter_abandon_container (arr_iter, entry_iter);
+}
+
+/**
+ * Closes an a{sv} after unsuccessfully appending a value.
+ *
+ * You must also abandon whatever larger data structure (message, etc.)
+ * the a{sv} was embedded in.
+ *
+ * @param iter the iterator which is appending to the message or other data structure containing the a{sv}
+ * @param arr_iter the iterator appending to the array, will be closed
+ */
+void
+_dbus_asv_abandon (DBusMessageIter *iter,
+                   DBusMessageIter *arr_iter)
+{
+  dbus_message_iter_abandon_container (iter, arr_iter);
+}
+
+/**
+ * Create a new entry in an a{sv} (map from string to variant)
+ * with a 32-bit unsigned integer value.
+ *
+ * If this function fails, the a{sv} must be abandoned, for instance
+ * with _dbus_asv_abandon().
+ *
+ * @param arr_iter the iterator which is appending to the array
+ * @param key a UTF-8 key for the map
+ * @param value the value
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_asv_add_uint32 (DBusMessageIter *arr_iter,
+                      const char *key,
+                      dbus_uint32_t value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key,
+                             DBUS_TYPE_UINT32_AS_STRING, &var_iter))
+    return FALSE;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32,
+                                       &value))
+    {
+      _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter);
+      return FALSE;
+    }
+
+  if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter))
+    return FALSE;
+
+  return TRUE;
+}
+
+/**
+ * Create a new entry in an a{sv} (map from string to variant)
+ * with a UTF-8 string value.
+ *
+ * If this function fails, the a{sv} must be abandoned, for instance
+ * with _dbus_asv_abandon().
+ *
+ * @param arr_iter the iterator which is appending to the array
+ * @param key a UTF-8 key for the map
+ * @param value the value
+ * @returns #TRUE on success, or #FALSE if not enough memory
+ */
+dbus_bool_t
+_dbus_asv_add_string (DBusMessageIter *arr_iter,
+                      const char *key,
+                      const char *value)
+{
+  DBusMessageIter entry_iter, var_iter;
+
+  if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key,
+                             DBUS_TYPE_STRING_AS_STRING, &var_iter))
+    return FALSE;
+
+  if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING,
+                                       &value))
+    {
+      _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter);
+      return FALSE;
+    }
+
+  if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter))
+    return FALSE;
+
+  return TRUE;
+}
diff --git a/dbus/dbus-asv-util.h b/dbus/dbus-asv-util.h
new file mode 100644 (file)
index 0000000..0337260
--- /dev/null
@@ -0,0 +1,46 @@
+/* dbus-asv-util.h - utility functions for a{sv}
+ *
+ * Copyright © 2011-2012 Nokia Corporation
+ * Copyright © 2012-2013 Collabora Ltd.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef DBUS_ASV_UTIL_H
+#define DBUS_ASV_UTIL_H
+
+#include <dbus/dbus-internals.h>
+
+DBUS_BEGIN_DECLS
+
+DBusMessage *_dbus_asv_new_method_return (DBusMessage      *message,
+                                          DBusMessageIter  *iter,
+                                          DBusMessageIter  *arr_iter);
+dbus_bool_t  _dbus_asv_close             (DBusMessageIter *iter,
+                                          DBusMessageIter *arr_iter);
+void         _dbus_asv_abandon           (DBusMessageIter *iter,
+                                          DBusMessageIter *arr_iter);
+
+dbus_bool_t  _dbus_asv_add_uint32        (DBusMessageIter *arr_iter,
+                                          const char      *key,
+                                          dbus_uint32_t    value);
+dbus_bool_t  _dbus_asv_add_string        (DBusMessageIter *arr_iter,
+                                          const char      *key,
+                                          const char      *value);
+
+#endif