mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-02 07:36:17 +01:00
4b94c0831e
Back in the far-off twentieth century, it was normal on unix workstations for U+0060 GRAVE ACCENT to be drawn as "‛" and for U+0027 APOSTROPHE to be drawn as "’". This led to the convention of using them as poor-man's ‛smart quotes’ in ASCII-only text. However, "'" is now universally drawn as a vertical line, and "`" at a 45-degree angle, making them an `odd couple' when used together. Unfortunately, there are lots of very old strings in glib, and also lots of new strings in which people have kept up the old tradition, perhaps entirely unaware that it used to not look stupid. Fix this by just using 'dumb quotes' everywhere. https://bugzilla.gnome.org/show_bug.cgi?id=700746
399 lines
13 KiB
C
399 lines
13 KiB
C
#include <gio/gio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static GDBusNodeInfo *introspection_data = NULL;
|
|
static GDBusInterfaceInfo *manager_interface_info = NULL;
|
|
static GDBusInterfaceInfo *block_interface_info = NULL;
|
|
static GDBusInterfaceInfo *partition_interface_info = NULL;
|
|
|
|
/* Introspection data for the service we are exporting */
|
|
static const gchar introspection_xml[] =
|
|
"<node>"
|
|
" <interface name='org.gtk.GDBus.Example.Manager'>"
|
|
" <method name='Hello'>"
|
|
" <arg type='s' name='greeting' direction='in'/>"
|
|
" <arg type='s' name='response' direction='out'/>"
|
|
" </method>"
|
|
" </interface>"
|
|
" <interface name='org.gtk.GDBus.Example.Block'>"
|
|
" <method name='Hello'>"
|
|
" <arg type='s' name='greeting' direction='in'/>"
|
|
" <arg type='s' name='response' direction='out'/>"
|
|
" </method>"
|
|
" <property type='i' name='Major' access='read'/>"
|
|
" <property type='i' name='Minor' access='read'/>"
|
|
" <property type='s' name='Notes' access='readwrite'/>"
|
|
" </interface>"
|
|
" <interface name='org.gtk.GDBus.Example.Partition'>"
|
|
" <method name='Hello'>"
|
|
" <arg type='s' name='greeting' direction='in'/>"
|
|
" <arg type='s' name='response' direction='out'/>"
|
|
" </method>"
|
|
" <property type='i' name='PartitionNumber' access='read'/>"
|
|
" <property type='s' name='Notes' access='readwrite'/>"
|
|
" </interface>"
|
|
"</node>";
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
manager_method_call (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *method_name,
|
|
GVariant *parameters,
|
|
GDBusMethodInvocation *invocation,
|
|
gpointer user_data)
|
|
{
|
|
const gchar *greeting;
|
|
gchar *response;
|
|
|
|
g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Manager");
|
|
g_assert_cmpstr (method_name, ==, "Hello");
|
|
|
|
g_variant_get (parameters, "(&s)", &greeting);
|
|
|
|
response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
|
|
interface_name,
|
|
method_name,
|
|
(const gchar *) user_data,
|
|
object_path,
|
|
greeting);
|
|
g_dbus_method_invocation_return_value (invocation,
|
|
g_variant_new ("(s)", response));
|
|
g_free (response);
|
|
}
|
|
|
|
const GDBusInterfaceVTable manager_vtable =
|
|
{
|
|
manager_method_call,
|
|
NULL, /* get_property */
|
|
NULL /* set_property */
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
block_method_call (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *method_name,
|
|
GVariant *parameters,
|
|
GDBusMethodInvocation *invocation,
|
|
gpointer user_data)
|
|
{
|
|
g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Block");
|
|
|
|
if (g_strcmp0 (method_name, "Hello") == 0)
|
|
{
|
|
const gchar *greeting;
|
|
gchar *response;
|
|
|
|
g_variant_get (parameters, "(&s)", &greeting);
|
|
|
|
response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
|
|
interface_name,
|
|
method_name,
|
|
(const gchar *) user_data,
|
|
object_path,
|
|
greeting);
|
|
g_dbus_method_invocation_return_value (invocation,
|
|
g_variant_new ("(s)", response));
|
|
g_free (response);
|
|
}
|
|
else if (g_strcmp0 (method_name, "DoStuff") == 0)
|
|
{
|
|
g_dbus_method_invocation_return_dbus_error (invocation,
|
|
"org.gtk.GDBus.TestSubtree.Error.Failed",
|
|
"This method intentionally always fails");
|
|
}
|
|
else
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static GVariant *
|
|
block_get_property (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *property_name,
|
|
GError **error,
|
|
gpointer user_data)
|
|
{
|
|
GVariant *ret;
|
|
const gchar *node;
|
|
gint major;
|
|
gint minor;
|
|
|
|
node = strrchr (object_path, '/') + 1;
|
|
if (g_str_has_prefix (node, "sda"))
|
|
major = 8;
|
|
else
|
|
major = 9;
|
|
if (strlen (node) == 4)
|
|
minor = node[3] - '0';
|
|
else
|
|
minor = 0;
|
|
|
|
ret = NULL;
|
|
if (g_strcmp0 (property_name, "Major") == 0)
|
|
{
|
|
ret = g_variant_new_int32 (major);
|
|
}
|
|
else if (g_strcmp0 (property_name, "Minor") == 0)
|
|
{
|
|
ret = g_variant_new_int32 (minor);
|
|
}
|
|
else if (g_strcmp0 (property_name, "Notes") == 0)
|
|
{
|
|
g_set_error (error,
|
|
G_IO_ERROR,
|
|
G_IO_ERROR_FAILED,
|
|
"Hello %s. I thought I said reading this property "
|
|
"always results in an error. kthxbye",
|
|
sender);
|
|
}
|
|
else
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static gboolean
|
|
block_set_property (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *property_name,
|
|
GVariant *value,
|
|
GError **error,
|
|
gpointer user_data)
|
|
{
|
|
/* TODO */
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
const GDBusInterfaceVTable block_vtable =
|
|
{
|
|
block_method_call,
|
|
block_get_property,
|
|
block_set_property,
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
partition_method_call (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *method_name,
|
|
GVariant *parameters,
|
|
GDBusMethodInvocation *invocation,
|
|
gpointer user_data)
|
|
{
|
|
const gchar *greeting;
|
|
gchar *response;
|
|
|
|
g_assert_cmpstr (interface_name, ==, "org.gtk.GDBus.Example.Partition");
|
|
g_assert_cmpstr (method_name, ==, "Hello");
|
|
|
|
g_variant_get (parameters, "(&s)", &greeting);
|
|
|
|
response = g_strdup_printf ("Method %s.%s with user_data '%s' on object path %s called with arg '%s'",
|
|
interface_name,
|
|
method_name,
|
|
(const gchar *) user_data,
|
|
object_path,
|
|
greeting);
|
|
g_dbus_method_invocation_return_value (invocation,
|
|
g_variant_new ("(s)", response));
|
|
g_free (response);
|
|
}
|
|
|
|
const GDBusInterfaceVTable partition_vtable =
|
|
{
|
|
partition_method_call,
|
|
//partition_get_property,
|
|
//partition_set_property
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static gchar **
|
|
subtree_enumerate (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
gpointer user_data)
|
|
{
|
|
gchar **nodes;
|
|
GPtrArray *p;
|
|
|
|
p = g_ptr_array_new ();
|
|
g_ptr_array_add (p, g_strdup ("sda"));
|
|
g_ptr_array_add (p, g_strdup ("sda1"));
|
|
g_ptr_array_add (p, g_strdup ("sda2"));
|
|
g_ptr_array_add (p, g_strdup ("sda3"));
|
|
g_ptr_array_add (p, g_strdup ("sdb"));
|
|
g_ptr_array_add (p, g_strdup ("sdb1"));
|
|
g_ptr_array_add (p, g_strdup ("sdc"));
|
|
g_ptr_array_add (p, g_strdup ("sdc1"));
|
|
g_ptr_array_add (p, NULL);
|
|
nodes = (gchar **) g_ptr_array_free (p, FALSE);
|
|
|
|
return nodes;
|
|
}
|
|
|
|
static GDBusInterfaceInfo **
|
|
subtree_introspect (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *node,
|
|
gpointer user_data)
|
|
{
|
|
GPtrArray *p;
|
|
|
|
p = g_ptr_array_new ();
|
|
if (node == NULL)
|
|
{
|
|
g_ptr_array_add (p, g_dbus_interface_info_ref (manager_interface_info));
|
|
}
|
|
else
|
|
{
|
|
g_ptr_array_add (p, g_dbus_interface_info_ref (block_interface_info));
|
|
if (strlen (node) == 4)
|
|
g_ptr_array_add (p,
|
|
g_dbus_interface_info_ref (partition_interface_info));
|
|
}
|
|
|
|
g_ptr_array_add (p, NULL);
|
|
|
|
return (GDBusInterfaceInfo **) g_ptr_array_free (p, FALSE);
|
|
}
|
|
|
|
static const GDBusInterfaceVTable *
|
|
subtree_dispatch (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *node,
|
|
gpointer *out_user_data,
|
|
gpointer user_data)
|
|
{
|
|
const GDBusInterfaceVTable *vtable_to_return;
|
|
gpointer user_data_to_return;
|
|
|
|
if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Manager") == 0)
|
|
{
|
|
user_data_to_return = "The Root";
|
|
vtable_to_return = &manager_vtable;
|
|
}
|
|
else
|
|
{
|
|
if (strlen (node) == 4)
|
|
user_data_to_return = "A partition";
|
|
else
|
|
user_data_to_return = "A block device";
|
|
|
|
if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Block") == 0)
|
|
vtable_to_return = &block_vtable;
|
|
else if (g_strcmp0 (interface_name, "org.gtk.GDBus.Example.Partition") == 0)
|
|
vtable_to_return = &partition_vtable;
|
|
else
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
*out_user_data = user_data_to_return;
|
|
|
|
return vtable_to_return;
|
|
}
|
|
|
|
const GDBusSubtreeVTable subtree_vtable =
|
|
{
|
|
subtree_enumerate,
|
|
subtree_introspect,
|
|
subtree_dispatch
|
|
};
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
static void
|
|
on_bus_acquired (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
guint registration_id;
|
|
|
|
registration_id = g_dbus_connection_register_subtree (connection,
|
|
"/org/gtk/GDBus/TestSubtree/Devices",
|
|
&subtree_vtable,
|
|
G_DBUS_SUBTREE_FLAGS_NONE,
|
|
NULL, /* user_data */
|
|
NULL, /* user_data_free_func */
|
|
NULL); /* GError** */
|
|
g_assert (registration_id > 0);
|
|
}
|
|
|
|
static void
|
|
on_name_acquired (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
}
|
|
|
|
static void
|
|
on_name_lost (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
exit (1);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
guint owner_id;
|
|
GMainLoop *loop;
|
|
|
|
/* We are lazy here - we don't want to manually provide
|
|
* the introspection data structures - so we just build
|
|
* them from XML.
|
|
*/
|
|
introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
|
|
g_assert (introspection_data != NULL);
|
|
|
|
manager_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Manager");
|
|
block_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Block");
|
|
partition_interface_info = g_dbus_node_info_lookup_interface (introspection_data, "org.gtk.GDBus.Example.Partition");
|
|
g_assert (manager_interface_info != NULL);
|
|
g_assert (block_interface_info != NULL);
|
|
g_assert (partition_interface_info != NULL);
|
|
|
|
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
|
"org.gtk.GDBus.TestSubtree",
|
|
G_BUS_NAME_OWNER_FLAGS_NONE,
|
|
on_bus_acquired,
|
|
on_name_acquired,
|
|
on_name_lost,
|
|
NULL,
|
|
NULL);
|
|
|
|
loop = g_main_loop_new (NULL, FALSE);
|
|
g_main_loop_run (loop);
|
|
|
|
g_bus_unown_name (owner_id);
|
|
|
|
g_dbus_node_info_unref (introspection_data);
|
|
|
|
return 0;
|
|
}
|