Merge branch 'dbus-1.4'
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Thu, 24 Feb 2011 17:17:36 +0000 (17:17 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Thu, 24 Feb 2011 17:17:36 +0000 (17:17 +0000)
NEWS
bus/driver.c
dbus/dbus-string-util.c
dbus/dbus-string.c

diff --git a/NEWS b/NEWS
index b378246..d869b51 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,13 @@
+D-Bus 1.5.0 (UNRELEASED)
+==
+
+  • Let the bus daemon implement more than one interface (fd.o #33757,
+    Simon McVittie)
+  • Optimize _dbus_string_replace_len to reduce waste (fd.o #21261,
+    Roberto Guido)
+  • Include _dbus_path_is_absolute in libdbus on Windows, fixing compilation
+    (fd.o #32805, Mark Brand)
+
 D-Bus 1.4.6 (2010-02-17)
 ==
 
index cc8d1f2..1e9573e 100644 (file)
@@ -1644,11 +1644,7 @@ bus_driver_handle_get_id (DBusConnection *connection,
   return FALSE;
 }
 
-/* For speed it might be useful to sort this in order of
- * frequency of use (but doesn't matter with only a few items
- * anyhow)
- */
-static struct
+typedef struct
 {
   const char *name;
   const char *in_args;
@@ -1657,7 +1653,13 @@ static struct
                            BusTransaction *transaction,
                            DBusMessage    *message,
                            DBusError      *error);
-} message_handlers[] = {
+} MessageHandler;
+
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+static const MessageHandler dbus_message_handlers[] = {
   { "Hello",
     "",
     DBUS_TYPE_STRING_AS_STRING,
@@ -1729,7 +1731,41 @@ static struct
   { "GetId",
     "",
     DBUS_TYPE_STRING_AS_STRING,
-    bus_driver_handle_get_id }
+    bus_driver_handle_get_id },
+  { NULL, NULL, NULL, NULL }
+};
+
+static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
+    BusTransaction *, DBusMessage *, DBusError *);
+
+static const MessageHandler introspectable_message_handlers[] = {
+  { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+  { NULL, NULL, NULL, NULL }
+};
+
+typedef struct {
+  const char *name;
+  const MessageHandler *message_handlers;
+  const char *extra_introspection;
+} InterfaceHandler;
+
+/* These should ideally be sorted by frequency of use, although it
+ * probably doesn't matter with this few items */
+static InterfaceHandler interface_handlers[] = {
+  { DBUS_INTERFACE_DBUS, dbus_message_handlers,
+    "    <signal name=\"NameOwnerChanged\">\n"
+    "      <arg type=\"s\"/>\n"
+    "      <arg type=\"s\"/>\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n"
+    "    <signal name=\"NameLost\">\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n"
+    "    <signal name=\"NameAcquired\">\n"
+    "      <arg type=\"s\"/>\n"
+    "    </signal>\n" },
+  { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+  { NULL, NULL, NULL }
 };
 
 static dbus_bool_t
@@ -1770,86 +1806,43 @@ write_args_for_direction (DBusString *xml,
 dbus_bool_t
 bus_driver_generate_introspect_string (DBusString *xml)
 {
-  int i;
+  const InterfaceHandler *ih;
+  const MessageHandler *mh;
 
   if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
     return FALSE;
   if (!_dbus_string_append (xml, "<node>\n"))
     return FALSE;
-  if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
-    return FALSE;
-  if (!_dbus_string_append (xml, "    <method name=\"Introspect\">\n"))
-    return FALSE;
-  if (!_dbus_string_append_printf (xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
-    return FALSE;
-  if (!_dbus_string_append (xml, "    </method>\n"))
-    return FALSE;
-  if (!_dbus_string_append (xml, "  </interface>\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n",
-                                   DBUS_INTERFACE_DBUS))
-    return FALSE;
 
-  i = 0;
-  while (i < _DBUS_N_ELEMENTS (message_handlers))
+  for (ih = interface_handlers; ih->name != NULL; ih++)
     {
-
-      if (!_dbus_string_append_printf (xml, "    <method name=\"%s\">\n",
-                                       message_handlers[i].name))
+      if (!_dbus_string_append_printf (xml, "  <interface name=\"%s\">\n",
+                                       ih->name))
         return FALSE;
 
-      if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
-       return FALSE;
-
-      if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
-       return FALSE;
-
-      if (!_dbus_string_append (xml, "    </method>\n"))
-       return FALSE;
-
-      ++i;
-    }
-
-  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameOwnerChanged\">\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
-    return FALSE;
-
-
-
-  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameLost\">\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
-    return FALSE;
-
-  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
-    return FALSE;
-
+      for (mh = ih->message_handlers; mh->name != NULL; mh++)
+        {
+          if (!_dbus_string_append_printf (xml, "    <method name=\"%s\">\n",
+                                           mh->name))
+            return FALSE;
 
+          if (!write_args_for_direction (xml, mh->in_args, TRUE))
+            return FALSE;
 
-  if (!_dbus_string_append_printf (xml, "    <signal name=\"NameAcquired\">\n"))
-    return FALSE;
+          if (!write_args_for_direction (xml, mh->out_args, FALSE))
+            return FALSE;
 
-  if (!_dbus_string_append_printf (xml, "      <arg type=\"s\"/>\n"))
-    return FALSE;
+          if (!_dbus_string_append (xml, "    </method>\n"))
+            return FALSE;
+        }
 
-  if (!_dbus_string_append_printf (xml, "    </signal>\n"))
-    return FALSE;
+      if (ih->extra_introspection != NULL &&
+          !_dbus_string_append (xml, ih->extra_introspection))
+        return FALSE;
 
-  if (!_dbus_string_append (xml, "  </interface>\n"))
-    return FALSE;
+      if (!_dbus_string_append (xml, "  </interface>\n"))
+        return FALSE;
+    }
 
   if (!_dbus_string_append (xml, "</node>\n"))
     return FALSE;
@@ -1926,7 +1919,8 @@ bus_driver_handle_message (DBusConnection *connection,
                            DBusError      *error)
 {
   const char *name, *sender, *interface;
-  int i;
+  const InterfaceHandler *ih;
+  const MessageHandler *mh;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -1944,57 +1938,48 @@ bus_driver_handle_message (DBusConnection *connection,
       return TRUE; /* we just ignore this */
     }
 
-  if (dbus_message_is_method_call (message,
-                                   DBUS_INTERFACE_INTROSPECTABLE,
-                                   "Introspect"))
-    return bus_driver_handle_introspect (connection, transaction, message, error);
-
+  /* may be NULL, which means "any interface will do" */
   interface = dbus_message_get_interface (message);
-  if (interface == NULL)
-    interface = DBUS_INTERFACE_DBUS;
 
   _dbus_assert (dbus_message_get_member (message) != NULL);
 
   name = dbus_message_get_member (message);
   sender = dbus_message_get_sender (message);
 
-  if (strcmp (interface,
-              DBUS_INTERFACE_DBUS) != 0)
-    {
-      _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
-                     interface);
-      goto unknown;
-    }
-
   _dbus_verbose ("Driver got a method call: %s\n",
                 dbus_message_get_member (message));
 
   /* security checks should have kept this from getting here */
   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
 
-  i = 0;
-  while (i < _DBUS_N_ELEMENTS (message_handlers))
+  for (ih = interface_handlers; ih->name != NULL; ih++)
     {
-      if (strcmp (message_handlers[i].name, name) == 0)
+      if (interface != NULL && strcmp (interface, ih->name) != 0)
+        continue;
+
+      for (mh = ih->message_handlers; mh->name != NULL; mh++)
         {
+          if (strcmp (mh->name, name) != 0)
+            continue;
+
           _dbus_verbose ("Found driver handler for %s\n", name);
 
-          if (!dbus_message_has_signature (message, message_handlers[i].in_args))
+          if (!dbus_message_has_signature (message, mh->in_args))
             {
               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
               _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
                              name, dbus_message_get_signature (message),
-                             message_handlers[i].in_args);
+                             mh->in_args);
 
               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
                               "Call to %s has wrong args (%s, expected %s)\n",
                               name, dbus_message_get_signature (message),
-                              message_handlers[i].in_args);
+                              mh->in_args);
               _DBUS_ASSERT_ERROR_IS_SET (error);
               return FALSE;
             }
 
-          if ((* message_handlers[i].handler) (connection, transaction, message, error))
+          if ((* mh->handler) (connection, transaction, message, error))
             {
               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
               _dbus_verbose ("Driver handler succeeded\n");
@@ -2007,8 +1992,6 @@ bus_driver_handle_message (DBusConnection *connection,
               return FALSE;
             }
         }
-
-      ++i;
     }
 
  unknown:
index 4d42bb0..b31703c 100644 (file)
@@ -266,7 +266,7 @@ _dbus_string_test (void)
 {
   DBusString str;
   DBusString other;
-  int i, end;
+  int i, a, end;
   long v;
   double d;
   int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
@@ -513,10 +513,94 @@ _dbus_string_test (void)
   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
   _dbus_assert (_dbus_string_equal_c_str (&other,
                                           "HelloHello WorldWorle"));
-  
+
   _dbus_string_free (&str);
   _dbus_string_free (&other);
+
+  /* Different tests are provided because different behaviours are
+   * implemented in _dbus_string_replace_len() in function of replacing and
+   * replaced lengths
+   */
+
+  if (!_dbus_string_init (&str))
+    _dbus_assert_not_reached ("failed to init string");
   
+  if (!_dbus_string_append (&str, "Hello World"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  i = _dbus_string_get_length (&str);
+  
+  if (!_dbus_string_init (&other))
+    _dbus_assert_not_reached ("could not init string");
+
+  if (!_dbus_string_append (&other, "Foo String"))
+    _dbus_assert_not_reached ("could not append to string");
+
+  a = _dbus_string_get_length (&other);
+
+  if (!_dbus_string_replace_len (&str, 0, 6,
+                                 &other, 4, 0))
+    _dbus_assert_not_reached ("could not replace 0 length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String"));
+
+  if (!_dbus_string_replace_len (&str, 5, 6,
+                                 &other,
+                                 _dbus_string_get_length (&other),
+                                 0))
+    _dbus_assert_not_reached ("could not replace at the end");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String World"));
+
+  if (!_dbus_string_replace_len (&str, 0, 5,
+                                 &other,
+                                 _dbus_string_get_length (&other) - 5,
+                                 5))
+    _dbus_assert_not_reached ("could not replace same length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo Hello String Hello"));
+
+  if (!_dbus_string_replace_len (&str, 6, 5,
+                                 &other, 4, 12))
+    _dbus_assert_not_reached ("could not replace with shorter string");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 5);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "Foo World Hello"));
+
+  if (!_dbus_string_replace_len (&str, 0, 1,
+                                 &other, 0, 3))
+    _dbus_assert_not_reached ("could not replace at the beginning");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "H World Hello"));
+
+  if (!_dbus_string_replace_len (&str, 6, 5,
+                                 &other,
+                                 _dbus_string_get_length (&other) - 5,
+                                 5))
+    _dbus_assert_not_reached ("could not replace same length");
+
+  _dbus_assert (_dbus_string_get_length (&str) == i);
+  _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+  _dbus_assert (_dbus_string_equal_c_str (&other,
+                                          "H World World"));
+
+  _dbus_string_free (&str);
+  _dbus_string_free (&other);
+
   /* Check append/get unichar */
   
   if (!_dbus_string_init (&str))
index e2eb93b..2471f46 100644 (file)
@@ -1635,15 +1635,6 @@ _dbus_string_copy_len (const DBusString *source,
 /**
  * Replaces a segment of dest string with a segment of source string.
  *
- * @todo optimize the case where the two lengths are the same, and
- * avoid memmoving the data in the trailing part of the string twice.
- *
- * @todo avoid inserting the source into dest, then deleting
- * the replaced chunk of dest (which creates a potentially large
- * intermediate string). Instead, extend the replaced chunk
- * of dest with padding to the same size as the source chunk,
- * then copy in the source bytes.
- * 
  * @param source the source string
  * @param start where to start copying the source string
  * @param len length of segment to copy
@@ -1669,11 +1660,37 @@ _dbus_string_replace_len (const DBusString *source,
   _dbus_assert (replace_at <= real_dest->len);
   _dbus_assert (replace_len <= real_dest->len - replace_at);
 
-  if (!copy (real_source, start, len,
-             real_dest, replace_at))
-    return FALSE;
+  if (len == replace_len)
+    {
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, len);
+    }
+  else if (len < replace_len)
+    {
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, len);
+      delete (real_dest, replace_at + len,
+              replace_len - len);
+    }
+  else
+    {
+      int diff;
 
-  delete (real_dest, replace_at + len, replace_len);
+      _dbus_assert (len > replace_len);
+
+      diff = len - replace_len;
+
+      /* First of all we check if destination string can be enlarged as
+       * required, then we overwrite previous bytes
+       */
+
+      if (!copy (real_source, start + replace_len, diff,
+                 real_dest, replace_at + replace_len))
+        return FALSE;
+
+      memmove (real_dest->str + replace_at,
+               real_source->str + start, replace_len);
+    }
 
   return TRUE;
 }