summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2009-02-07 15:59:47 -0500
committerDavid Zeuthen <davidz@redhat.com>2009-02-07 15:59:47 -0500
commit66fc98c4f1ace8a5dd412ee218d95f416ba0a2a0 (patch)
tree699005277defa35e37259e5f0bf480e7063b81f7
parentdbbf8a652de24a6263e400f05c10eb380b8b8b4a (diff)
introduce the concept of complete types
To generate proper docs, and in the future to simplify the struct handling, we introduce the concept of complete types. This means that we now know, at binding generation, the complete type of an argument or a property. Previously, we only knew the D-Bus signature. This change breaks existing eggdbus users. The org.gtk.EggDBus.Type annotation needs to be used for disamgiuation, e.g. if there are two defined structures with signature (sa{sv}), use <arg name="foo" type="(sa{sv})"> <annotation name="org.gtk.EggDBus.Type" value="Identity"/> </arg> <arg name="bar" type="a(sa{sv})"> <annotation name="org.gtk.EggDBus.Type" value="Array<Identity>"/> </arg> <arg name="baz" type="a{s(sa{sv})}"> <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Subject>"/> </arg> where both Identity and Subject are structs with the signature (sa{sv}). The format of org.gtk.EggDBus.Type is straightforward, it's roughly like this type = Byte | Int16 | UInt16 | Int32 | UInt32 | Int64 | UInt64 | Double | Variant | String | ObjectPath | Signature | Struct<type0,type1,...,typeN> | Dict<type,type> | Array<type> | struct_type | enum_type | flag_type With this change we can know generate proper docbook docs. Previously we couldn't do that since we didn't know how to break down e.g. a(sa{sv}). Thus, we could only generate docs like this GetIdentities (OUT Array<Struct<String,Dict<String,Variant>>>) Now we can do GetIdentites (OUT Array<Identity>) which is much nicer. In addition, this paves the way for getting rid of the structural type equivalence mess in EggDBusStructure. The plan for doing this is roughly like this - Turn EggDBusStructure into a GInterface - Create a EggDBusAnonymousStructure subclass that implements this - Generated structure classes simply implement EggDBusStructure and derive directly from GObject - User provided structure wrappers just implement this interface - notably existing classes can do this; e.g. if you want to put some existing program on D-Bus just make the types you want to use as structs implement EggDBusStructure. - Make egg_dbus_message_extract_structure() take a GType for what structure type to extract to. Ditto for egg_dbus_variant_get_structure(). - Provide versions egg_dbus_message_extract_structure() and egg_dbus_message_append_structure() that takes function pointers instead of a EggDBusStructure pointer. - ditto for EggDBusVariant. - With this change we should be able to generate Plain Old C structures instead of GObject based ones. This may be desirable for some structs passed over D-Bus. Also use the proper type for enum/flag types in properties and signals. Add test cases for this too.
-rw-r--r--docs/eggdbus/Makefile.am1
-rw-r--r--docs/eggdbus/eggdbus-docs.xml1
-rw-r--r--src/eggdbus/Makefile.am26
-rw-r--r--src/eggdbus/completetype.c666
-rw-r--r--src/eggdbus/completetype.h137
-rw-r--r--src/eggdbus/completetypetest.c255
-rw-r--r--src/eggdbus/docbook.c285
-rw-r--r--src/eggdbus/eggdbusbindingtool.c548
-rw-r--r--src/eggdbus/eggdbusbindingtool.h11
-rw-r--r--src/eggdbus/eggdbusinterface.c35
-rw-r--r--src/eggdbus/eggdbusmessage.c15
-rw-r--r--src/eggdbus/eggdbusprivate.h4
-rw-r--r--src/eggdbus/enum.c86
-rw-r--r--src/eggdbus/enum.h3
-rw-r--r--src/eggdbus/interface.c65
-rw-r--r--src/eggdbus/org.freedesktop.DBus.xml4
-rw-r--r--src/eggdbus/struct.c177
-rw-r--r--src/eggdbus/struct.h16
-rw-r--r--src/tests/com.example.Frob.xml108
-rw-r--r--src/tests/com.example.Tweak.xml33
-rw-r--r--src/tests/com.example.Twiddle.xml5
-rw-r--r--src/tests/testclient.c38
-rw-r--r--src/tests/testtweakimpl.c27
23 files changed, 2163 insertions, 383 deletions
diff --git a/docs/eggdbus/Makefile.am b/docs/eggdbus/Makefile.am
index 1b85490..94c00bf 100644
--- a/docs/eggdbus/Makefile.am
+++ b/docs/eggdbus/Makefile.am
@@ -73,6 +73,7 @@ content_files = \
../../src/tests/docbook-struct-Point.xml \
../../src/tests/docbook-struct-DescribedPair.xml \
../../src/tests/docbook-struct-DescribedPoint.xml \
+ ../../src/tests/docbook-struct-ExtendedDescribedPoint.xml \
../../src/tests/docbook-struct-StructWithVariant.xml \
../../src/tests/docbook-interface-com.example.Frob.xml \
../../src/tests/docbook-interface-com.example.Tweak.xml \
diff --git a/docs/eggdbus/eggdbus-docs.xml b/docs/eggdbus/eggdbus-docs.xml
index 4fd9522..f16aec9 100644
--- a/docs/eggdbus/eggdbus-docs.xml
+++ b/docs/eggdbus/eggdbus-docs.xml
@@ -146,6 +146,7 @@
<xi:include href="../../src/tests/docbook-struct-DescribedPair.xml"/>
<xi:include href="../../src/tests/docbook-struct-DescribedPoint.xml"/>
<xi:include href="../../src/tests/docbook-struct-StructWithVariant.xml"/>
+ <xi:include href="../../src/tests/docbook-struct-ExtendedDescribedPoint.xml"/>
<xi:include href="../../src/tests/docbook-interface-com.example.Frob.xml"/>
<xi:include href="../../src/tests/docbook-interface-com.example.Tweak.xml"/>
<xi:include href="../../src/tests/docbook-interface-com.example.Twiddle.xml"/>
diff --git a/src/eggdbus/Makefile.am b/src/eggdbus/Makefile.am
index b0c7f2e..aebb984 100644
--- a/src/eggdbus/Makefile.am
+++ b/src/eggdbus/Makefile.am
@@ -78,6 +78,7 @@ eggdbus_binding_tool_SOURCES = \
struct.c struct.h \
enum.c enum.h \
docbook.c docbook.h \
+ completetype.c completetype.h \
$(NULL)
eggdbus_binding_tool_CFLAGS = \
@@ -223,6 +224,31 @@ EXTRA_DIST = \
org.freedesktop.DBus.Introspectable.xml \
$(NULL)
+###########################################################################
+
+TESTS = completetypetest
+
+check_PROGRAMS = completetypetest
+
+completetypetest_SOURCES = \
+ completetypetest.c \
+ completetype.c completetype.h \
+ $(NULL)
+
+completetypetest_CFLAGS = \
+ -D_EGG_DBUS_COMPILATION \
+ $(GLIB_CFLAGS) \
+ $(DBUS_GLIB_CFLAGS) \
+ $(NULL)
+
+completetypetest_LDADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_GLIB_LIBS) \
+ libeggdbus-1.la \
+ $(NULL)
+
+###########################################################################
+
dist-hook :
(for i in $(egg_dbus_built_sources) $(BUILT_SOURCES) ; do rm -f $(distdir)/$$i ; done)
diff --git a/src/eggdbus/completetype.c b/src/eggdbus/completetype.c
new file mode 100644
index 0000000..1e5b4e0
--- /dev/null
+++ b/src/eggdbus/completetype.c
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include "config.h"
+
+#include <dbus/dbus.h>
+#include <string.h>
+
+#include "eggdbuserror.h"
+#include "completetype.h"
+
+static gchar **
+type_parser_split (const gchar *list_of_types,
+ GError **error)
+{
+ guint start;
+ guint n;
+ GPtrArray *p;
+ gchar *s;
+ gboolean ret;
+ gint bracket_depth;
+
+ ret = TRUE;
+
+ p = g_ptr_array_new ();
+ start = 0;
+
+ bracket_depth = 0;
+ for (n = 0; list_of_types[n] != '\0'; n++)
+ {
+ if (list_of_types[n] == '<')
+ bracket_depth++;
+
+ if (list_of_types[n] == '>')
+ bracket_depth--;
+
+ if (bracket_depth != 0)
+ continue;
+
+ if (list_of_types[n] == ',')
+ {
+ /* do the split */
+ s = g_strndup (list_of_types + start, n - start);
+ g_ptr_array_add (p, s);
+ start = n + 1;
+ }
+ }
+
+ /* last one */
+ s = g_strndup (list_of_types + start, n - start);
+ g_ptr_array_add (p, s);
+
+ if (ret)
+ {
+ g_ptr_array_add (p, NULL);
+ return (gchar **) g_ptr_array_free (p, FALSE);
+ }
+ else
+ {
+ g_ptr_array_free (p, TRUE);
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Unable to split '%s': bracket count mismatch",
+ list_of_types);
+ return NULL;
+ }
+}
+
+static CompleteType *
+complete_type_from_string_real (const gchar *string,
+ CompleteTypeParserCallback callback,
+ gpointer user_data,
+ GError **error,
+ gint depth)
+{
+ CompleteType *ret;
+
+ ret = NULL;
+
+ if (depth > 20)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Max depth reached. Aborting.");
+ goto out;
+ }
+
+ if (strcmp (string, "Byte") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("y");
+ goto out;
+ }
+ else if (strcmp (string, "Boolean") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("b");
+ goto out;
+ }
+ else if (strcmp (string, "Int16") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("n");
+ goto out;
+ }
+ else if (strcmp (string, "UInt16") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("q");
+ goto out;
+ }
+ else if (strcmp (string, "Int32") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("i");
+ goto out;
+ }
+ else if (strcmp (string, "UInt32") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("u");
+ goto out;
+ }
+ else if (strcmp (string, "Int64") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("x");
+ goto out;
+ }
+ else if (strcmp (string, "UInt64") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("t");
+ goto out;
+ }
+ else if (strcmp (string, "Double") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("d");
+ goto out;
+ }
+ else if (strcmp (string, "String") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("s");
+ goto out;
+ }
+ else if (strcmp (string, "ObjectPath") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("o");
+ goto out;
+ }
+ else if (strcmp (string, "Signature") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("g");
+ goto out;
+ }
+ else if (strcmp (string, "Variant") == 0)
+ {
+ ret = g_new0 (CompleteType, 1);
+ ret->signature = g_strdup ("v");
+ goto out;
+ }
+ else if (g_str_has_prefix (string, "Array<") && g_str_has_suffix (string, ">"))
+ {
+ gchar *contained_string;
+
+ contained_string = g_strndup (string + 6, strlen (string) - 6 - 1);
+
+ ret = g_new0 (CompleteType, 1);
+ ret->contained_types = g_new0 (CompleteType *, 1);
+ ret->contained_types[0] = complete_type_from_string_real (contained_string, callback, user_data, error, depth + 1);
+ g_free (contained_string);
+
+ if (ret->contained_types[0] == NULL)
+ {
+ complete_type_free (ret);
+ ret = NULL;
+ goto out;
+ }
+ ret->num_contained_types = 1;
+ ret->signature = g_strdup_printf ("a%s", ret->contained_types[0]->signature);
+ goto out;
+ }
+ else if (g_str_has_prefix (string, "Struct<") && g_str_has_suffix (string, ">"))
+ {
+ gchar **elems;
+ gchar *contained_string;
+ guint n;
+ GString *s;
+
+ contained_string = g_strndup (string + 7, strlen (string) - 7 - 1);
+ elems = type_parser_split (contained_string, error);
+ g_free (contained_string);
+
+ if (elems == NULL)
+ goto out;
+
+ ret = g_new0 (CompleteType, 1);
+ ret->contained_types = g_new0 (CompleteType *, g_strv_length (elems));
+
+ s = g_string_new ("(");
+ for (n = 0; elems[n] != NULL; n++)
+ {
+ ret->contained_types[n] = complete_type_from_string_real (elems[n], callback, user_data, error, depth + 1);
+ if (ret->contained_types[n] == NULL)
+ {
+ g_string_free (s, TRUE);
+ complete_type_free (ret);
+ ret = NULL;
+ goto out;
+ }
+ g_string_append (s, ret->contained_types[n]->signature);
+ ret->num_contained_types += 1;
+ }
+ g_string_append_c (s, ')');
+ ret->signature = g_string_free (s, FALSE);
+ goto out;
+ }
+ else if (g_str_has_prefix (string, "Dict<") && g_str_has_suffix (string, ">"))
+ {
+ gchar **elems;
+ gchar *contained_string;
+ guint n;
+ GString *s;
+
+ contained_string = g_strndup (string + 5, strlen (string) - 5 - 1);
+ elems = type_parser_split (contained_string, error);
+ g_free (contained_string);
+
+ if (elems == NULL)
+ goto out;
+
+ if (g_strv_length (elems) != 2)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Wrong number of arguments in Dict for '%s'",
+ string);
+ g_strfreev (elems);
+ goto out;
+ }
+
+ ret = g_new0 (CompleteType, 1);
+ ret->contained_types = g_new0 (CompleteType *, g_strv_length (elems));
+
+ s = g_string_new ("a{");
+ for (n = 0; elems[n] != NULL; n++)
+ {
+ ret->contained_types[n] = complete_type_from_string_real (elems[n], callback, user_data, error, depth + 1);
+ if (ret->contained_types[n] == NULL)
+ {
+ complete_type_free (ret);
+ g_string_free (s, TRUE);
+ ret = NULL;
+ goto out;
+ }
+ g_string_append (s, ret->contained_types[n]->signature);
+ ret->num_contained_types += 1;
+ }
+ g_string_append_c (s, '}');
+ ret->signature = g_string_free (s, FALSE);
+ goto out;
+ }
+ else
+ {
+ if (callback != NULL)
+ {
+ gchar *broken_down;
+
+ broken_down = callback (string, user_data, error);
+ if (broken_down == NULL)
+ {
+ ret = NULL;
+ goto out;
+ }
+ ret = complete_type_from_string_real (broken_down, callback, user_data, error, depth + 1);
+ if (ret == NULL)
+ goto out;
+ ret->user_type = g_strdup (string);
+ g_free (broken_down);
+ goto out;
+ }
+ }
+
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Error parsing '%s'",
+ string);
+
+ out:
+
+ return ret;
+}
+
+CompleteType *
+complete_type_from_string (const gchar *string,
+ CompleteTypeParserCallback callback,
+ gpointer user_data,
+ GError **error)
+{
+ return complete_type_from_string_real (string,
+ callback,
+ user_data,
+ error,
+ 0);
+}
+
+gchar *
+complete_type_to_string (CompleteType *type,
+ gboolean expand_user_types)
+{
+ gchar *ret;
+
+ ret = NULL;
+
+ if (!expand_user_types)
+ {
+ if (type->user_type != NULL)
+ {
+ ret = g_strdup (type->user_type);
+ goto out;
+ }
+ }
+
+ switch (type->signature[0])
+ {
+ case 'y':
+ ret = g_strdup ("Byte");
+ break;
+
+ case 'b':
+ ret = g_strdup ("Boolean");
+ break;
+
+ case 'n':
+ ret = g_strdup ("Int16");
+ break;
+
+ case 'q':
+ ret = g_strdup ("UInt16");
+ break;
+
+ case 'i':
+ ret = g_strdup ("Int32");
+ break;
+
+ case 'u':
+ ret = g_strdup ("UInt32");
+ break;
+
+ case 'x':
+ ret = g_strdup ("Int64");
+ break;
+
+ case 't':
+ ret = g_strdup ("UInt64");
+ break;
+
+ case 'd':
+ ret = g_strdup ("Double");
+ break;
+
+ case 's':
+ ret = g_strdup ("String");
+ break;
+
+ case 'o':
+ ret = g_strdup ("ObjectPath");
+ break;
+
+ case 'g':
+ ret = g_strdup ("Signature");
+ break;
+
+ case 'v':
+ ret = g_strdup ("Variant");
+ break;
+
+ case 'a':
+ if (type->signature[1] == '{')
+ {
+ ret = g_strdup_printf ("Dict<%s,%s>",
+ complete_type_to_string (type->contained_types[0], expand_user_types),
+ complete_type_to_string (type->contained_types[1], expand_user_types));
+ }
+ else
+ {
+ ret = g_strdup_printf ("Array<%s>",
+ complete_type_to_string (type->contained_types[0], expand_user_types));
+ }
+ break;
+
+ case '(':
+ {
+ GString *s;
+ guint n;
+
+ s = g_string_new ("Struct<");
+ for (n = 0; n < type->num_contained_types; n++)
+ {
+ if (n > 0)
+ g_string_append_c (s, ',');
+ g_string_append (s, complete_type_to_string (type->contained_types[n], expand_user_types));
+ }
+ g_string_append_c (s, '>');
+ ret = g_string_free (s, FALSE);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ out:
+ return ret;
+}
+
+gchar *
+complete_type_name_from_signature (const gchar *signature,
+ CompleteTypeSignatureParserCallback callback,
+ gpointer user_data,
+ GError **error)
+{
+ gchar *ret;
+ DBusError derror;
+ DBusSignatureIter iter;
+ int type;
+
+ ret = NULL;
+
+ dbus_error_init (&derror);
+ if (!dbus_signature_validate (signature, &derror))
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Signature '%s' not valid: %s: %s",
+ signature,
+ derror.name,
+ derror.message);
+ dbus_error_free (&derror);
+ goto out;
+ }
+
+ if (callback != NULL)
+ {
+ GError *local_error;
+
+ local_error = NULL;
+ ret = callback (signature, user_data, &local_error);
+
+ if (ret != NULL)
+ goto out;
+
+ if (local_error != NULL)
+ {
+ g_propagate_error (error, local_error);
+ goto out;
+ }
+ }
+
+ dbus_signature_iter_init (&iter, signature);
+
+ type = dbus_signature_iter_get_current_type (&iter);
+
+ switch (type)
+ {
+ case 'y':
+ ret = g_strdup ("Byte");
+ break;
+
+ case 'b':
+ ret = g_strdup ("Boolean");
+ break;
+
+ case 'n':
+ ret = g_strdup ("Int16");
+ break;
+
+ case 'q':
+ ret = g_strdup ("UInt16");
+ break;
+
+ case 'i':
+ ret = g_strdup ("Int32");
+ break;
+
+ case 'u':
+ ret = g_strdup ("UInt32");
+ break;
+
+ case 'x':
+ ret = g_strdup ("Int64");
+ break;
+
+ case 't':
+ ret = g_strdup ("UInt64");
+ break;
+
+ case 'd':
+ ret = g_strdup ("Double");
+ break;
+
+ case 's':
+ ret = g_strdup ("String");
+ break;
+
+ case 'o':
+ ret = g_strdup ("ObjectPath");
+ break;
+
+ case 'g':
+ ret = g_strdup ("Signature");
+ break;
+
+ case 'v':
+ ret = g_strdup ("Variant");
+ break;
+
+ case DBUS_TYPE_ARRAY:
+ if (signature[1] == '{')
+ {
+ guint n;
+ GString *s;
+ DBusSignatureIter sub_iter;
+ DBusSignatureIter sub_sub_iter;
+
+ dbus_signature_iter_recurse (&iter, &sub_iter);
+ dbus_signature_iter_recurse (&sub_iter, &sub_sub_iter);
+
+ n = 0;
+ s = g_string_new ("Dict<");
+ do
+ {
+ char *contained;
+ gchar *name;
+
+ if (n > 0)
+ g_string_append_c (s, ',');
+
+ contained = dbus_signature_iter_get_signature (&sub_sub_iter);
+ name = complete_type_name_from_signature (contained, callback, user_data, error);
+ dbus_free (contained);
+ if (name == NULL)
+ {
+ g_string_free (s, TRUE);
+ goto out;
+ }
+
+ g_string_append (s, name);
+ g_free (name);
+
+ n++;
+ }
+ while (dbus_signature_iter_next (&sub_sub_iter));
+
+ g_string_append_c (s, '>');
+
+ ret = g_string_free (s, FALSE);
+ }
+ else
+ {
+ gchar *name;
+
+ name = complete_type_name_from_signature (signature + 1, callback, user_data, error);
+ if (name == NULL)
+ goto out;
+
+ ret = g_strdup_printf ("Array<%s>", name);
+
+ g_free (name);
+ }
+ break;
+
+ case DBUS_TYPE_STRUCT:
+ {
+ guint n;
+ GString *s;
+ DBusSignatureIter sub_iter;
+
+ dbus_signature_iter_recurse (&iter, &sub_iter);
+
+ n = 0;
+ s = g_string_new ("Struct<");
+ do
+ {
+ char *contained;
+ gchar *name;
+
+ if (n > 0)
+ g_string_append_c (s, ',');
+
+ contained = dbus_signature_iter_get_signature (&sub_iter);
+ name = complete_type_name_from_signature (contained, callback, user_data, error);
+ dbus_free (contained);
+ if (name == NULL)
+ {
+ g_string_free (s, TRUE);
+ goto out;
+ }
+
+ g_string_append (s, name);
+ g_free (name);
+
+ n++;
+ }
+ while (dbus_signature_iter_next (&sub_iter));
+
+ g_string_append_c (s, '>');
+
+ ret = g_string_free (s, FALSE);
+ }
+ break;
+
+ default:
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Don't know how to parse signature '%s'",
+ signature);
+ break;
+ }
+
+ out:
+ return ret;
+}
+
+
+void
+complete_type_free (CompleteType *type)
+{
+ guint n;
+
+ g_free (type->signature);
+ g_free (type->user_type);
+ for (n = 0; n < type->num_contained_types; n++)
+ complete_type_free (type->contained_types[n]);
+ g_free (type->contained_types);
+ g_free (type);
+}
diff --git a/src/eggdbus/completetype.h b/src/eggdbus/completetype.h
new file mode 100644
index 0000000..ed2e34f
--- /dev/null
+++ b/src/eggdbus/completetype.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#ifndef __COMPLETE_TYPE_H
+#define __COMPLETE_TYPE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/**
+ * CompleteTypeParserCallback:
+ * @user_type: A user-defined type.
+ * @user_data: User data.
+ * @error: Return location for error.
+ *
+ * Callback function used in complete_type_from_string() for breaking @user_type
+ * into other types.
+ *
+ * Returns: %NULL if @error is set, otherwise a broken down type string for @user_type (that
+ * must be freeded with g_free()).
+ */
+typedef gchar *(*CompleteTypeParserCallback) (const gchar *user_type,
+ gpointer user_data,
+ GError **error);
+
+/**
+ * CompleteTypeSignatureParserCallback:
+ * @signature: The signature to resolve.
+ * @user_data: User data.
+ * @error: Return location for error.
+ *
+ * Callback function used in complete_type_from_signature() for inferring
+ * a user defined type from @signature.
+ *
+ * Returns: %NULL if @error is set, otherwise a user defined type for @signature (that must
+ * be freed with g_free()) or %NULL if there is no such user defined type.
+ */
+typedef gchar *(*CompleteTypeSignatureParserCallback) (const gchar *signature,
+ gpointer user_data,
+ GError **error);
+
+struct CompleteType;
+typedef struct CompleteType CompleteType;
+
+/**
+ * CompleteType:
+ * @signature: The D-Bus signature of the type.
+ * @user_type: The name of the user supplied type or %NULL.
+ * @num_contained_type: Number of elements in @contained_types.
+ * @contained_types: Contained types (for structs, arrays and dicts).
+ *
+ * This structure represents a recursive complete type.
+ */
+struct CompleteType
+{
+ gchar *signature;
+ gchar *user_type;
+ guint num_contained_types;
+ CompleteType **contained_types;
+};
+
+/**
+ * complete_type_free:
+ * @type: The #CompleteType instance to free.
+ *
+ * Frees @type and all contained types.
+ */
+void complete_type_free (CompleteType *type);
+
+/**
+ * complete_type_from_string:
+ * @string: The string to parse.
+ * @callback: A #CompleteTypeParserCallback to break down user defined types or %NULL.
+ * @user_data: User data to pass to @callback.
+ * @error: Return location for error.
+ *
+ * Parses @string and returns a #CompleteType instance.
+ *
+ * Returns: A #CompleteType instance or %NULL if @error is set.
+ */
+CompleteType *complete_type_from_string (const gchar *string,
+ CompleteTypeParserCallback callback,
+ gpointer user_data,
+ GError **error);
+
+/**
+ * complete_type_name_from_signature:
+ * @signature: The string to parse.
+ * @out_signature: A string builder to append the D-Bus signature to.
+ * @callback: A #CompleteTypeSignatureParserCallback to get user defined types or %NULL.
+ * @user_data: User data to pass to @callback.
+ * @error: Return location for error.
+ *
+ * Parses @string and returns a complete type name that can be used
+ * with complete_type_from_string().
+ *
+ * Returns: The type name or %NULL if @error is set.
+ */
+gchar *complete_type_name_from_signature (const gchar *signature,
+ CompleteTypeSignatureParserCallback callback,
+ gpointer user_data,
+ GError **error);
+
+/**
+ * complete_type_to_string:
+ * @type: A #CompleteType.
+ * @expand_user_types: %TRUE if user defined types should be expanded to native D-Bus types.
+ *
+ * Constructs a human readable string representation of @type.
+ *
+ * Returns: The string representation of @type. Free with g_free().
+ */
+gchar *complete_type_to_string (CompleteType *type,
+ gboolean expand_user_types);
+
+G_END_DECLS
+
+#endif /* __COMPLETE_TYPE_H */
diff --git a/src/eggdbus/completetypetest.c b/src/eggdbus/completetypetest.c
new file mode 100644
index 0000000..1f5ee69
--- /dev/null
+++ b/src/eggdbus/completetypetest.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "eggdbuserror.h"
+#include "completetype.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static const struct {
+ const gchar *string;
+ const gchar *signature;
+ const gchar *expanded;
+ const gchar *expected_error;
+} tests[] =
+{
+ { "Byte", "y", "Byte", NULL },
+ { "Boolean", "b", "Boolean", NULL },
+ { "Int16", "n", "Int16", NULL },
+ { "UInt16", "q", "UInt16", NULL },
+ { "Int32", "i", "Int32", NULL },
+ { "UInt32", "u", "UInt32", NULL },
+ { "Int64", "x", "Int64", NULL },
+ { "UInt64", "t", "UInt64", NULL },
+ { "Double", "d", "Double", NULL },
+ { "String", "s", "String", NULL },
+ { "ObjectPath", "o", "ObjectPath", NULL },
+ { "Signature", "g", "Signature", NULL },
+
+ { "Array<Byte>", "ay", "Array<Byte>", NULL },
+ { "Array<Boolean>", "ab", "Array<Boolean>", NULL },
+ { "Array<Int16>", "an", "Array<Int16>", NULL },
+
+ { "Struct<Byte,Boolean,Int16>", "(ybn)", "Struct<Byte,Boolean,Int16>", NULL },
+ { "Struct<Array<String>,Array<Int32>>", "(asai)", "Struct<Array<String>,Array<Int32>>", NULL },
+
+ { "Struct<String,Struct<Int32,Int32>>", "(s(ii))", "Struct<String,Struct<Int32,Int32>>", NULL },
+
+ { "Dict<String,String>", "a{ss}", "Dict<String,String>", NULL },
+
+ { "Dict<String,Struct<Int32,Int32,Struct<String,Byte>>>", "a{s(ii(sy))}", "Dict<String,Struct<Int32,Int32,Struct<String,Byte>>>", NULL },
+
+ { "TimeStamp", "i", "Int32", NULL },
+
+ { "Authorization", "(i(sa{sv})(sa{sv}))", "Struct<Int32,Struct<String,Dict<String,Variant>>,Struct<String,Dict<String,Variant>>>", NULL },
+
+ { "Struct<String,Authorization,Array<Identity>>", "(s(i(sa{sv})(sa{sv}))a(sa{sv}))", "Struct<String,Struct<Int32,Struct<String,Dict<String,Variant>>,Struct<String,Dict<String,Variant>>>,Array<Struct<String,Dict<String,Variant>>>>", NULL },
+
+ { "Int323", NULL, NULL, "Unknown type 'Int323'"},
+
+ { "Dict<Int323,String>", NULL, NULL, "Unknown type 'Int323'"},
+
+ { NULL, NULL, NULL, NULL },
+};
+
+static gchar *
+test_cb (const gchar *user_type,
+ gpointer user_data,
+ GError **error)
+{
+ gchar *ret;
+
+ ret = NULL;
+
+ if (strcmp (user_type, "Identity") == 0)
+ {
+ ret = g_strdup ("Struct<String,Dict<String,Variant>>");
+ }
+ else if (strcmp (user_type, "Subject") == 0)
+ {
+ ret = g_strdup ("Struct<String,Dict<String,Variant>>");
+ }
+ else if (strcmp (user_type, "Authorization") == 0)
+ {
+ ret = g_strdup ("Struct<TimeStamp,Identity,Subject>");
+ }
+ else if (strcmp (user_type, "TimeStamp") == 0)
+ {
+ ret = g_strdup ("Int32");
+ }
+ else
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Unknown type '%s'",
+ user_type);
+ }
+
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static const struct {
+ const gchar *signature;
+ const gchar *type_name;
+ const gchar *expected_error;
+} tests2[] =
+{
+ { "y", "Byte", NULL },
+ { "b", "Boolean", NULL },
+ { "n", "Int16", NULL },
+ { "q", "UInt16", NULL },
+ { "i", "Int32", NULL },
+ { "u", "UInt32", NULL },
+ { "x", "Int64", NULL },
+ { "t", "UInt64", NULL },
+ { "d", "Double", NULL },
+ { "s", "String", NULL },
+ { "o", "ObjectPath", NULL },
+ { "g", "Signature", NULL },
+
+ { "ay", "Array<Byte>", NULL },
+ { "ab", "Array<Boolean>", NULL },
+ { "an", "Array<Int16>", NULL },
+
+ { "(ybn)", "Struct<Byte,Boolean,Int16>", NULL },
+ { "(asai)", "Struct<Array<String>,Array<Int32>>", NULL },
+
+ { "(s(ii))", "Struct<String,Struct<Int32,Int32>>", NULL },
+
+ { "a{ss}", "Dict<String,String>", NULL },
+
+ { "a{s(ii(sy))}", "Dict<String,Struct<Int32,Int32,Struct<String,Byte>>>", NULL },
+
+ { "(ssa{sv})", "SomeStruct", NULL },
+
+ { "a(ssa{sv})", "Array<SomeStruct>", NULL },
+
+ { "a{s(ssa{sv})}", "Dict<String,SomeStruct>", NULL },
+
+ { "(ss(ssa{sv}))", "SomeOtherStruct", NULL },
+
+ { "(sa{sv})", NULL, "Cannot disambiguate '(sa{sv})'. Please specify the complete type." },
+
+ { NULL, NULL, NULL },
+};
+
+
+static gchar *
+test_sig_cb (const gchar *signature,
+ gpointer user_data,
+ GError **error)
+{
+ gchar *ret;
+
+ ret = NULL;
+
+ if (strcmp (signature, "(ssa{sv})") == 0)
+ {
+ ret = g_strdup ("SomeStruct");
+ }
+ else if (strcmp (signature, "(ss(ssa{sv}))") == 0)
+ {
+ ret = g_strdup ("SomeOtherStruct");
+ }
+ else if (strcmp (signature, "(sa{sv})") == 0)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Cannot disambiguate '(sa{sv})'. Please specify the complete type.");
+ }
+
+ return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+ guint n;
+
+ for (n = 0; tests[n].string != NULL; n++)
+ {
+ GError *error;
+ CompleteType *type;
+
+ error = NULL;
+ type = complete_type_from_string (tests[n].string, test_cb, NULL, &error);
+
+ if (tests[n].expected_error != NULL)
+ {
+ g_assert (type == NULL);
+ g_assert_error (error, EGG_DBUS_ERROR, EGG_DBUS_ERROR_FAILED);
+ g_assert_cmpstr (error->message, ==, tests[n].expected_error);
+ g_error_free (error);
+ }
+ else
+ {
+ gchar *s;
+
+ g_assert_no_error (error);
+ g_assert_cmpstr (type->signature, ==, tests[n].signature);
+
+ s = complete_type_to_string (type, FALSE);
+ g_assert_cmpstr (tests[n].string, ==, s);
+ g_free (s);
+
+ s = complete_type_to_string (type, TRUE);
+ g_assert_cmpstr (tests[n].expanded, ==, s);
+ g_free (s);
+
+ complete_type_free (type);
+ }
+ }
+
+ for (n = 0; tests2[n].signature != NULL; n++)
+ {
+ GError *error;
+ gchar *s;
+
+ error = NULL;
+ s = complete_type_name_from_signature (tests2[n].signature,
+ test_sig_cb,
+ NULL,
+ &error);
+ if (tests2[n].expected_error != NULL)
+ {
+ g_assert (s == NULL);
+ g_assert_error (error, EGG_DBUS_ERROR, EGG_DBUS_ERROR_FAILED);
+ g_assert_cmpstr (error->message, ==, tests2[n].expected_error);
+ g_error_free (error);
+ }
+ else
+ {
+ g_assert_no_error (error);
+ g_assert_cmpstr (s, ==, tests2[n].type_name);
+ g_free (s);
+ }
+ }
+
+ return 0;
+}
diff --git a/src/eggdbus/docbook.c b/src/eggdbus/docbook.c
index 53efb3a..a8d4712 100644
--- a/src/eggdbus/docbook.c
+++ b/src/eggdbus/docbook.c
@@ -30,199 +30,181 @@
#include "eggdbusbindingtool.h"
#include "docbook.h"
+#include "completetype.h"
static void
-get_type_name_for_sig_iter (DBusSignatureIter *sig_iter,
- gchar **out_raw,
- gchar **out_name)
+pretty_print_type_name (CompleteType *type,
+ GString *name,
+ GString *link)
{
- GString *ret_raw;
- GString *ret;
- gchar *s;
- gchar *s_raw;
- gchar *s1;
- gchar *s1_raw;
guint n;
- DBusSignatureIter sub_sig_iter;
- int cur_type;
+ StructData *struct_data;
+ EnumData *enum_data;
- ret_raw = NULL;
- ret = g_string_new (NULL);
-
- cur_type = dbus_signature_iter_get_current_type (sig_iter);
+ if (type->user_type != NULL)
+ {
+ struct_data = find_struct_by_name (type->user_type);
+ if (struct_data != NULL)
+ {
+ g_string_append_printf (name, "%s", struct_data->name);
+ g_string_append_printf (link, "<link linkend=\"eggdbus-struct-%s\">%s</link>",
+ struct_data->name,
+ struct_data->name);
+ }
+ else
+ {
+ enum_data = find_enum_by_name (type->user_type);
+ if (enum_data != NULL)
+ {
+ g_string_append_printf (name, "%s", enum_data->name);
+ g_string_append_printf (link, "<link linkend=\"eggdbus-enum-%s\">%s</link>",
+ enum_data->name,
+ enum_data->name);
+ }
+ else
+ {
+ g_string_append (name, type->user_type);
+ g_string_append (link, type->user_type);
+ }
+ }
+ goto out;
+ }
- switch (cur_type)
+ switch (type->signature[0])
{
case DBUS_TYPE_BYTE:
- g_string_append (ret, "Byte");
+ g_string_append (name, "Byte");
+ g_string_append (link, "Byte");
break;
case DBUS_TYPE_BOOLEAN:
- g_string_append (ret, "Boolean");
+ g_string_append (name, "Boolean");
+ g_string_append (link, "Boolean");
break;
case DBUS_TYPE_INT16:
- g_string_append (ret, "Int16");
+ g_string_append (name, "Int16");
+ g_string_append (link, "Int16");
break;
case DBUS_TYPE_UINT16:
- g_string_append (ret, "UInt16");
+ g_string_append (name, "UInt16");
+ g_string_append (link, "UInt16");
break;
case DBUS_TYPE_INT32:
- g_string_append (ret, "Int32");
+ g_string_append (name, "Int32");
+ g_string_append (link, "Int32");
break;
case DBUS_TYPE_UINT32:
- g_string_append (ret, "UInt32");
+ g_string_append (name, "UInt32");
+ g_string_append (link, "UInt32");
break;
case DBUS_TYPE_INT64:
- g_string_append (ret, "Int64");
+ g_string_append (name, "Int64");
+ g_string_append (link, "Int64");
break;
case DBUS_TYPE_UINT64:
- g_string_append (ret, "UInt64");
+ g_string_append (name, "UInt64");
+ g_string_append (link, "UInt64");
break;
case DBUS_TYPE_DOUBLE:
- g_string_append (ret, "Double");
+ g_string_append (name, "Double");
+ g_string_append (link, "Double");
break;
case DBUS_TYPE_STRING:
- g_string_append (ret, "String");
+ g_string_append (name, "String");
+ g_string_append (link, "String");
break;
case DBUS_TYPE_OBJECT_PATH:
- g_string_append (ret, "ObjectPath");
+ g_string_append (name, "ObjectPath");
+ g_string_append (link, "ObjectPath");
break;
case DBUS_TYPE_SIGNATURE:
- g_string_append (ret, "Signature");
+ g_string_append (name, "Signature");
+ g_string_append (link, "Signature");
break;
case DBUS_TYPE_VARIANT:
- g_string_append (ret, "Variant");
- break;
-
- case DBUS_TYPE_DICT_ENTRY:
- ret_raw = g_string_new (NULL);
-
- dbus_signature_iter_recurse (sig_iter, &sub_sig_iter);
- get_type_name_for_sig_iter (&sub_sig_iter, &s_raw, &s);
- g_assert (dbus_signature_iter_next (&sub_sig_iter) == TRUE);
- get_type_name_for_sig_iter (&sub_sig_iter, &s1_raw, &s1);
- g_assert (dbus_signature_iter_next (&sub_sig_iter) == FALSE);
- g_string_append_printf (ret_raw, "Dict<%s_%s>", s_raw, s1_raw);
- g_string_append_printf (ret, "Dict&lt;%s&#x2192;%s&gt;", s, s1); /* U+2192 RIGHTWARDS ARROW */
- g_free (s_raw);
- g_free (s);
- g_free (s1_raw);
- g_free (s1);
- break;
-
- case DBUS_TYPE_STRUCT:
- ret_raw = g_string_new (NULL);
-
- g_string_append (ret_raw, "[");
- g_string_append (ret, "[");
- dbus_signature_iter_recurse (sig_iter, &sub_sig_iter);
- n = 0;
- do
- {
- get_type_name_for_sig_iter (&sub_sig_iter, &s_raw, &s);
- if (n != 0)
- {
- g_string_append (ret_raw, ",");
- g_string_append (ret, ",");
- }
- g_string_append_printf (ret_raw, "%s", s_raw);
- g_string_append_printf (ret, "%s", s);
- g_free (s_raw);
- g_free (s);
- n++;
- }
- while (dbus_signature_iter_next (&sub_sig_iter));
- g_string_append (ret_raw, "]");
- g_string_append (ret, "]");
+ g_string_append (name, "Variant");
+ g_string_append (link, "Variant");
break;
case DBUS_TYPE_ARRAY:
- ret_raw = g_string_new (NULL);
-
- dbus_signature_iter_recurse (sig_iter, &sub_sig_iter);
- get_type_name_for_sig_iter (&sub_sig_iter, &s_raw, &s);
- if (g_str_has_prefix (s, "Dict&lt;"))
+ if (type->signature[1] == '{')
{
- g_string_append (ret_raw, s_raw);
- g_string_append (ret, s);
+ g_string_append (name, "Dict<");
+ g_string_append (link, "Dict&lt;");
+ pretty_print_type_name (type->contained_types[0], name, link);
+ g_string_append (name, ",");
+ g_string_append (link, ",");
+ pretty_print_type_name (type->contained_types[1], name, link);
+ g_string_append (name, ">");
+ g_string_append (link, "&gt;");
}
else
{
- g_string_append_printf (ret_raw, "Array<%s>", s_raw);
- g_string_append_printf (ret, "Array&lt;%s&gt;", s);
+ g_string_append (name, "Array<");
+ g_string_append (link, "Array&lt;");
+ pretty_print_type_name (type->contained_types[0], name, link);
+ g_string_append (name, ">");
+ g_string_append (link, "&gt;");
+ }
+ break;
+
+ case '(':
+ g_string_append (name, "Struct<");
+ g_string_append (link, "Struct&lt;");
+ for (n = 0; n < type->num_contained_types; n++)
+ {
+ if (n > 0)
+ {
+ g_string_append (name, ",");
+ g_string_append (link, ",");
+ }
+ pretty_print_type_name (type->contained_types[n], name, link);
}
- g_free (s);
+ g_string_append (name, ">");
+ g_string_append (link, "&gt;");
break;
default:
- g_warning ("Unable to handle %s", dbus_signature_iter_get_signature (sig_iter));
g_assert_not_reached ();
break;
}
-
- s = g_string_free (ret, FALSE);
-
- if (ret_raw != NULL)
- s_raw = g_string_free (ret_raw, FALSE);
- else
- s_raw = g_strdup (s);
-
- if (out_raw != NULL)
- {
- *out_raw = s_raw;
- s_raw = NULL;
- }
-
- if (out_name != NULL)
- {
- *out_name = s;
- s = NULL;
- }
-
- g_free (s);
- g_free (s_raw);
+ out:
+ ;
}
static void
-docbook_get_typename_for_signature (const gchar *signature,
+docbook_get_typename_for_signature (CompleteType *type,
gchar **out_name,
gchar **out_link)
{
- DBusSignatureIter iter;
- gchar *name;
- gchar *name_link;
+ GString *name_str;
+ GString *link_str;
- name = NULL;
- name_link = NULL;
+ name_str = g_string_new (NULL);
+ link_str = g_string_new (NULL);
- dbus_signature_iter_init (&iter, signature);
- get_type_name_for_sig_iter (&iter, &name, &name_link);
+ pretty_print_type_name (type, name_str, link_str);
if (out_name != NULL)
- {
- *out_name = name;
- name = NULL;
- }
+ *out_name = g_string_free (name_str, FALSE);
+ else
+ g_string_free (name_str, TRUE);
if (out_link != NULL)
- {
- *out_link = name_link;
- name_link = NULL;
- }
-
- g_free (name);
- g_free (name_link);
+ *out_link = g_string_free (link_str, FALSE);
+ else
+ g_string_free (link_str, TRUE);
}
static void
@@ -233,7 +215,9 @@ docbook_print_arg (const EggDBusInterfaceArgInfo *arg,
gchar *arg_type_name;
gchar *arg_type_link;
- docbook_get_typename_for_signature (arg->signature, &arg_type_name, &arg_type_link);
+ docbook_get_typename_for_signature (get_complete_type_for_arg (arg),
+ &arg_type_name,
+ &arg_type_link);
g_print ("%s%s%*s%s",
arg_prefix,
@@ -259,7 +243,9 @@ docbook_get_max_arg_len_for_method (const EggDBusInterfaceMethodInfo *method)
gchar *arg_type_name;
guint arg_len;
- docbook_get_typename_for_signature (arg->signature, &arg_type_name, NULL);
+ docbook_get_typename_for_signature (get_complete_type_for_arg (arg),
+ &arg_type_name,
+ NULL);
arg_len = strlen (arg_type_name);
g_free (arg_type_name);
@@ -273,7 +259,9 @@ docbook_get_max_arg_len_for_method (const EggDBusInterfaceMethodInfo *method)
gchar *arg_type_name;
guint arg_len;
- docbook_get_typename_for_signature (arg->signature, &arg_type_name, NULL);
+ docbook_get_typename_for_signature (get_complete_type_for_arg (arg),
+ &arg_type_name,
+ NULL);
arg_len = strlen (arg_type_name);
g_free (arg_type_name);
@@ -298,7 +286,9 @@ docbook_get_max_arg_len_for_signal (const EggDBusInterfaceSignalInfo *signal)
gchar *arg_type_name;
guint arg_len;
- docbook_get_typename_for_signature (arg->signature, &arg_type_name, NULL);
+ docbook_get_typename_for_signature (get_complete_type_for_arg (arg),
+ &arg_type_name,
+ NULL);
arg_len = strlen (arg_type_name);
g_free (arg_type_name);
@@ -453,7 +443,9 @@ docbook_print_property_prototype (const EggDBusInterfaceInfo *interface
g_print (" ");
}
- docbook_get_typename_for_signature (property->signature, NULL, &arg_type_link);
+ docbook_get_typename_for_signature (get_complete_type_for_property (property),
+ NULL,
+ &arg_type_link);
g_print (" %s\n", arg_type_link);
@@ -469,7 +461,9 @@ docbook_print_arg_in_list (const gchar *prefix,
arg_doc_string = get_doc (arg->annotations, DOC_TYPE_DOCBOOK);
- docbook_get_typename_for_signature (arg->signature, NULL, &arg_type_link);
+ docbook_get_typename_for_signature (get_complete_type_for_arg (arg),
+ NULL,
+ &arg_type_link);
g_print (" <varlistentry>\n");
g_print (" <term><literal>%s%s <parameter>%s</parameter></literal>:</term>\n",
@@ -920,7 +914,6 @@ enum_generate_docbook (EnumData *enum_data,
guint n;
guint len;
guint max_len;
- guint m;
gboolean has_none_elem;
gchar *title;
@@ -1016,11 +1009,9 @@ enum_generate_docbook (EnumData *enum_data,
g_print ("{\n");
- m = 0;
if (!flags_has_none_value_already (enum_data))
{
g_print (" None %*s= 0x00000000", max_len - 4, "");
- m = 1;
has_none_elem = FALSE;
}
@@ -1030,16 +1021,8 @@ enum_generate_docbook (EnumData *enum_data,
if (n != 0 || !has_none_elem)
g_print (",\n");
- if (elem->value != -1)
- m = elem->value;
-
len = strlen (elem->name);
- g_print (" %s %*s= 0x%08x", elem->name, max_len - len, "", m);
-
- if (m == 0)
- m = 1;
- else
- m *= 2;
+ g_print (" %s %*s= 0x%08x", elem->name, max_len - len, "", elem->value);
}
g_print ("\n"
"}\n");
@@ -1056,20 +1039,14 @@ enum_generate_docbook (EnumData *enum_data,
}
g_print ("{\n");
- m = 0;
for (n = 0; n < enum_data->num_elements; n++)
{
EnumElemData *elem = enum_data->elements[n];
if (n != 0)
g_print (",\n");
- if (elem->value != -1)
- m = elem->value;
-
len = strlen (elem->name);
- g_print (" %s %*s= %d", elem->name, max_len - len, "", m);
-
- m++;
+ g_print (" %s %*s= %d", elem->name, max_len - len, "", elem->value);
}
g_print ("\n"
"}\n");
@@ -1198,7 +1175,9 @@ struct_generate_docbook (StructData *struct_data,
guint type_len;
gchar *type_name;
- docbook_get_typename_for_signature (elem->signature, &type_name, NULL);
+ docbook_get_typename_for_signature (elem->type,
+ &type_name,
+ NULL);
type_len = strlen (type_name);
g_free (type_name);
@@ -1216,7 +1195,9 @@ struct_generate_docbook (StructData *struct_data,
if (n > 0)
g_print (",\n");
- docbook_get_typename_for_signature (elem->signature, &type_name, &type_name_link);
+ docbook_get_typename_for_signature (elem->type,
+ &type_name,
+ &type_name_link);
type_len = strlen (type_name);
g_print (" %s%*s %s",
@@ -1243,7 +1224,9 @@ struct_generate_docbook (StructData *struct_data,
gchar *type_name_link;
struct_doc_string = get_doc (elem->annotations, DOC_TYPE_DOCBOOK);
- docbook_get_typename_for_signature (elem->signature, NULL, &type_name_link);
+ docbook_get_typename_for_signature (elem->type,
+ NULL,
+ &type_name_link);
g_print (" <varlistentry>\n");
g_print (" <term><literal>%s <structfield>%s</structfield></literal></term>\n", type_name_link, elem->name);
diff --git a/src/eggdbus/eggdbusbindingtool.c b/src/eggdbus/eggdbusbindingtool.c
index c53cd55..ce5c72a 100644
--- a/src/eggdbus/eggdbusbindingtool.c
+++ b/src/eggdbus/eggdbusbindingtool.c
@@ -28,11 +28,14 @@
#include <eggdbus/eggdbusinterface.h>
#include <dbus/dbus.h>
+#include "eggdbusprivate.h"
+
#include "eggdbusbindingtool.h"
#include "interface.h"
#include "struct.h"
#include "enum.h"
#include "docbook.h"
+#include "completetype.h"
static char **opt_xml = NULL;
static gboolean opt_iface_only = FALSE;
@@ -78,6 +81,72 @@ static GSList *marshallers_to_generate = NULL;
/* ---------------------------------------------------------------------------------------------------- */
+EnumData *
+find_enum_by_name (const gchar *name)
+{
+ GSList *l;
+ EnumData *ret;
+
+ ret = NULL;
+ for (l = enum_data_list; l != NULL; l = l->next)
+ {
+ EnumData *s = (EnumData *) l->data;
+
+ if (strcmp (s->name, name) == 0)
+ {
+ ret = s;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+StructData *
+find_struct_by_name (const gchar *name)
+{
+ GSList *l;
+ StructData *ret;
+
+ ret = NULL;
+ for (l = struct_data_list; l != NULL; l = l->next)
+ {
+ StructData *s = (StructData *) l->data;
+
+ if (strcmp (s->name, name) == 0)
+ {
+ ret = s;
+ goto out;
+ }
+ }
+
+ out:
+ return ret;
+}
+
+static GSList *
+find_struct_by_signature (const gchar *signature)
+{
+ GSList *ret;
+ GSList *l;
+
+ ret = NULL;
+
+ for (l = struct_data_list; l != NULL; l = l->next)
+ {
+ StructData *s = (StructData *) l->data;
+
+ if (strcmp (s->signature, signature) == 0)
+ ret = g_slist_prepend (ret, s);
+ }
+
+ return ret;
+}
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
GSList *
get_enums_declared_in_interface (const EggDBusInterfaceInfo *interface)
{
@@ -200,21 +269,18 @@ create_link_regexs (GError **error)
{
id = g_strdup_printf ("#%s", enum_data->maximal_dbus_prefix);
id[strlen(id) - 1] = '\0';
- docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-enummain-%s\">%s* Error Domain</link>",
- enum_data->name,
+ docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-errordomain-%s\">%s* Error Domain</link>",
+ enum_data->maximal_dbus_prefix,
enum_data->maximal_dbus_prefix);
}
else
{
id = g_strdup_printf ("#%s", enum_data->name);
- docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-enummain-%s\">%s</link>.",
+ docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-enum-%s\">%s</link>.",
enum_data->name,
enum_data->name);
}
gtkdoc_val = g_strdup_printf ("#%s%s", name_space, enum_data->name);
- docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-enummain-%s\">%s</link>",
- enum_data->name,
- enum_data->name);
g_hash_table_insert (gtkdoc_links, id, gtkdoc_val);
g_hash_table_insert (docbook_links, id, docbook_val);
@@ -222,8 +288,8 @@ create_link_regexs (GError **error)
{
id = g_strdup_printf ("#%s.", enum_data->maximal_dbus_prefix);
id[strlen(id) - 1] = '\0';
- docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-enum-%s\">%s* Error Domain</link>.",
- enum_data->name,
+ docbook_val = g_strdup_printf ("<link linkend=\"eggdbus-errordomain-%s\">%s* Error Domain</link>.",
+ enum_data->maximal_dbus_prefix,
enum_data->maximal_dbus_prefix);
}
else
@@ -528,43 +594,6 @@ get_doc_summary (const EggDBusInterfaceAnnotationInfo *annotations,
/* ---------------------------------------------------------------------------------------------------- */
-static StructData *
-lookup_struct_for_signature (const gchar *signature,
- const gchar *required_struct_type)
-{
- StructData *ret;
- GSList *l;
-
- ret = NULL;
-
- for (l = struct_data_list; l != NULL; l = l->next)
- {
- StructData *struct_data = l->data;
-
- if (strcmp (signature, struct_data->signature) == 0)
- {
- if (required_struct_type == NULL)
- {
- ret = struct_data;
- goto out;
- }
- else
- {
- if (strcmp (required_struct_type, struct_data->name) == 0)
- {
- ret = struct_data;
- goto out;
- }
- }
- }
- }
-
- out:
- return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
void
print_includes (const gchar *name_space, gboolean is_c_file)
{
@@ -635,6 +664,9 @@ get_c_marshaller_name_for_args (const EggDBusInterfaceArgInfo *args, guint num_a
{
const EggDBusInterfaceArgInfo *arg = args + n;
const char *type_name;
+ CompleteType *type;
+
+ type = get_complete_type_for_arg (arg);
switch (arg->signature[0])
{
@@ -659,7 +691,21 @@ get_c_marshaller_name_for_args (const EggDBusInterfaceArgInfo *args, guint num_a
break;
case DBUS_TYPE_UINT32:
- type_name = "UINT";
+ if (type->user_type != NULL)
+ {
+ EnumData *enum_data;
+ enum_data = find_enum_by_name (type->user_type);
+ if (enum_data != NULL && enum_data->type == ENUM_DATA_TYPE_ENUM)
+ type_name = "ENUM";
+ else if (enum_data != NULL && enum_data->type == ENUM_DATA_TYPE_FLAGS)
+ type_name = "FLAGS";
+ else
+ type_name = "UINT";
+ }
+ else
+ {
+ type_name = "UINT";
+ }
break;
case DBUS_TYPE_INT64:
@@ -772,39 +818,57 @@ get_type_names_for_signature (const gchar *signature,
char *ret;
const char *free_function_name;
const char *gvalue_set_func_name;
- const gchar *required_struct_type;
+ const gchar *type;
gchar *required_c_type;
- const gchar *required_flags_type;
- const gchar *required_enum_type;
char *gtype_name;
+ EnumData *enum_data;
ret = NULL;
gtype_name = NULL;
free_function_name = NULL;
gvalue_set_func_name = NULL;
- required_struct_type = egg_dbus_interface_annotation_info_lookup (annotations,
- "org.gtk.EggDBus.StructType");
+ type = egg_dbus_interface_annotation_info_lookup (annotations, "org.gtk.EggDBus.Type");
- required_c_type = g_strdup (egg_dbus_interface_annotation_info_lookup (annotations,
- "org.gtk.EggDBus.CType"));
+ required_c_type = g_strdup (egg_dbus_interface_annotation_info_lookup (annotations, "org.gtk.EggDBus.CType"));
- required_flags_type = egg_dbus_interface_annotation_info_lookup (annotations,
- "org.gtk.EggDBus.FlagsType");
+ if (type != NULL)
+ {
+ enum_data = find_enum_by_name (type);
- required_enum_type = egg_dbus_interface_annotation_info_lookup (annotations,
- "org.gtk.EggDBus.EnumType");
+ if (enum_data != NULL)
+ {
+ gchar *name_space_uscore;
+ gchar *name_space_uscore_upper;
- if (required_flags_type != NULL)
- {
- g_free (required_c_type);
- required_c_type = g_strdup_printf ("%s%s", name_space, required_flags_type);
- }
+ name_space_uscore = egg_dbus_utils_camel_case_to_uscore (name_space);
+ name_space_uscore_upper = g_ascii_strup (name_space_uscore, -1);
- if (required_enum_type != NULL)
- {
- g_free (required_c_type);
- required_c_type = g_strdup_printf ("%s%s", name_space, required_enum_type);
+ g_free (required_c_type);
+ required_c_type = g_strdup_printf ("%s%s", name_space, type);
+ /* TODO: set the correct gtype etc. */
+
+ /* enums only work on uint32 */
+ if (signature[0] != DBUS_TYPE_UINT32)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "You can only use enumerations on uint32 types.");
+ goto out;
+ }
+
+ ret = g_strdup_printf ("%s%s ", name_space, enum_data->name);
+ if (enum_data->type == ENUM_DATA_TYPE_FLAGS)
+ gvalue_set_func_name = "g_value_set_flags";
+ else if (enum_data->type == ENUM_DATA_TYPE_ENUM)
+ gvalue_set_func_name = "g_value_set_enum";
+ gtype_name = g_strdup_printf ("%s_TYPE_%s", name_space_uscore_upper, enum_data->name_uscore_upper);
+
+ g_free (name_space_uscore);
+ g_free (name_space_uscore_upper);
+ goto done;
+ }
}
/* .CType only works on integral types */
@@ -920,27 +984,24 @@ get_type_names_for_signature (const gchar *signature,
char *name_space_uscore;
char *name_space_uscore_upper;
- /* TODO: cope with this and just return a EggDBusStructure */
- struct_data = lookup_struct_for_signature (signature, required_struct_type);
+ /* TODO: support anonymous structs */
+ if (type == NULL)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No org.gtk.EggDBus.Type annotation.");
+ goto out;
+ }
+
+ struct_data = find_struct_by_name (type);
if (struct_data == NULL)
{
- if (required_struct_type != NULL)
- {
- g_set_error (error,
- EGG_DBUS_ERROR,
- EGG_DBUS_ERROR_FAILED,
- "No struct interface for signature '%s' with required type %s.",
- signature,
- required_struct_type);
- }
- else
- {
- g_set_error (error,
- EGG_DBUS_ERROR,
- EGG_DBUS_ERROR_FAILED,
- "No struct interface for signature '%s'.",
- signature);
- }
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No struct with name %s.",
+ type);
goto out;
}
@@ -1063,6 +1124,7 @@ get_type_names_for_signature (const gchar *signature,
goto out;
}
+ done:
if (out_free_function_name != NULL)
*out_free_function_name = free_function_name;
@@ -1996,6 +2058,313 @@ generate_dbus_interfaces (GError **error)
/* ---------------------------------------------------------------------------------------------------- */
+static GSList *complete_types = NULL;
+
+CompleteType *
+get_complete_type_for_arg (const EggDBusInterfaceArgInfo *arg)
+{
+ return (CompleteType *) g_dataset_get_data (arg, "complete-type");
+}
+
+CompleteType *
+get_complete_type_for_property (const EggDBusInterfacePropertyInfo *property)
+{
+ return (CompleteType *) g_dataset_get_data (property, "complete-type");
+}
+
+static gchar *
+break_down_type_cb (const gchar *user_type,
+ gpointer user_data,
+ GError **error)
+{
+ StructData *struct_data;
+ EnumData *enum_data;
+ gchar *ret;
+
+ ret = NULL;
+
+ /* user type may be a struct */
+ struct_data = find_struct_by_name (user_type);
+ if (struct_data != NULL)
+ {
+ ret = g_strdup (struct_data->type_string);
+ goto out;
+ }
+
+ /* ... or an enumeration */
+ enum_data = find_enum_by_name (user_type);
+ if (enum_data != NULL)
+ {
+ /* error domains can't be used */
+ if (enum_data->type == ENUM_DATA_TYPE_FLAGS ||
+ enum_data->type == ENUM_DATA_TYPE_ENUM)
+ {
+ ret = g_strdup ("UInt32");
+ goto out;
+ }
+ }
+
+
+ if (ret == NULL)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Unknown type %s",
+ user_type);
+ }
+
+ out:
+ return ret;
+}
+
+static gchar *
+infer_complete_type_cb (const gchar *signature,
+ gpointer user_data,
+ GError **error)
+{
+ gchar *ret;
+
+ ret = NULL;
+
+ if (signature[0] == '(')
+ {
+ GSList *matches;
+ StructData *struct_data;
+
+ matches = find_struct_by_signature (signature);
+ if (matches == NULL)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No declared structs with signature '%s'. If you really want an anonymous structure, "
+ "please specify it in a org.gtk.EggDBus.Type annotation.",
+ signature);
+ goto out;
+ }
+
+ if (g_slist_length (matches) > 1)
+ {
+ g_slist_free (matches);
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Multiple structs with signature '%s' exists. Please use org.gtk.EggDBus.Type "
+ "annotation to disambiguate.",
+ signature);
+ goto out;
+ }
+
+ struct_data = matches->data;
+ ret = g_strdup (struct_data->name);
+ g_slist_free (matches);
+ }
+
+ out:
+ return ret;
+}
+
+static CompleteType *
+determine_and_validate_type (EggDBusInterfaceAnnotationInfo **annotations,
+ const gchar *expected_signature,
+ GError **error)
+{
+ const gchar *type_string;
+ CompleteType *type;
+
+ type = NULL;
+
+ /* if the user specified the complete type, verify that it matches the signature */
+ type_string = egg_dbus_interface_annotation_info_lookup (*annotations, "org.gtk.EggDBus.Type");
+ if (type_string != NULL)
+ {
+ type = complete_type_from_string (type_string,
+ break_down_type_cb,
+ NULL,
+ error);
+ if (type == NULL)
+ goto out;
+
+ if (strcmp (type->signature, expected_signature) != 0)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Signature of the complete type %s is %s and it doesn't match the given signature %s",
+ type_string,
+ type->signature,
+ expected_signature);
+ complete_type_free (type);
+ type = NULL;
+ goto out;
+ }
+ }
+ else
+ {
+ gchar *s;
+ /* user didn't specify complete type, let's see if we can infer it */
+ s = complete_type_name_from_signature (expected_signature,
+ infer_complete_type_cb,
+ NULL,
+ error);
+ if (s == NULL)
+ goto out;
+
+ _egg_dbus_interface_annotation_info_set ((EggDBusInterfaceAnnotationInfo **) annotations,
+ "org.gtk.EggDBus.Type",
+ (gpointer) s);
+
+ type = complete_type_from_string (s,
+ break_down_type_cb,
+ NULL,
+ error);
+ if (type == NULL)
+ goto out;
+
+ }
+
+ out:
+ return type;
+}
+
+static gboolean
+determine_and_validate_arg (const EggDBusInterfaceArgInfo *arg,
+ GError **error)
+{
+ CompleteType *type;
+
+ type = determine_and_validate_type ((EggDBusInterfaceAnnotationInfo **) &(arg->annotations),
+ arg->signature,
+ error);
+
+ if (type != NULL)
+ {
+ g_dataset_set_data (arg, "complete-type", type);
+ complete_types = g_slist_prepend (complete_types, type);
+ }
+
+ return type != NULL;
+}
+
+static gboolean
+determine_and_validate_property (const EggDBusInterfacePropertyInfo *property,
+ GError **error)
+{
+ CompleteType *type;
+
+ type = determine_and_validate_type ((EggDBusInterfaceAnnotationInfo **) &(property->annotations),
+ property->signature,
+ error);
+
+ if (type != NULL)
+ {
+ g_dataset_set_data (property, "complete-type", type);
+ complete_types = g_slist_prepend (complete_types, type);
+ }
+
+ return type != NULL;
+}
+
+static gboolean
+determine_and_validate_complete_types (GError **error)
+{
+ gboolean ret;
+ const gchar *iface_name;
+ EggDBusInterfaceInfo *interface;
+ GHashTableIter hash_iter;
+ guint n;
+ guint m;
+ GSList *l;
+
+ ret = FALSE;
+
+ /* foreach struct */
+ for (l = struct_data_list; l != NULL; l = l->next)
+ {
+ StructData *struct_data = l->data;
+ if (!struct_data_compute_types_and_signatures (struct_data, error))
+ goto out;
+ }
+
+ /* foreach interface */
+ g_hash_table_iter_init (&hash_iter, all_dbus_interfaces);
+ while (g_hash_table_iter_next (&hash_iter, (gpointer) &iface_name, (gpointer) &interface))
+ {
+ /* foreach method */
+ for (n = 0; n < interface->num_methods; n++)
+ {
+ const EggDBusInterfaceMethodInfo *method = interface->methods + n;
+ for (m = 0; m < method->in_num_args; m++)
+ {
+ const EggDBusInterfaceArgInfo *arg = method->in_args + m;
+ if (!determine_and_validate_arg (arg, error))
+ {
+ g_prefix_error (error,
+ "When handling in-arg %d in on method %s.%s: ",
+ m,
+ interface->name,
+ method->name);
+ goto out;
+ }
+ }
+ for (m = 0; m < method->out_num_args; m++)
+ {
+ const EggDBusInterfaceArgInfo *arg = method->out_args + m;
+ if (!determine_and_validate_arg (arg, error))
+ {
+ g_prefix_error (error,
+ "When handling out-arg %d in on method %s.%s: ",
+ m,
+ interface->name,
+ method->name);
+ goto out;
+ }
+ }
+ }
+
+ /* foreach signal */
+ for (n = 0; n < interface->num_signals; n++)
+ {
+ const EggDBusInterfaceSignalInfo *signal = interface->signals + n;
+ for (m = 0; m < signal->num_args; m++)
+ {
+ const EggDBusInterfaceArgInfo *arg = signal->args + m;
+ if (!determine_and_validate_arg (arg, error))
+ {
+ g_prefix_error (error,
+ "When handling arg %d in on signal %s::%s: ",
+ m,
+ interface->name,
+ signal->name);
+ goto out;
+ }
+ }
+ }
+
+ /* foreach property */
+ for (n = 0; n < interface->num_properties; n++)
+ {
+ const EggDBusInterfacePropertyInfo *property = interface->properties + n;
+ if (!determine_and_validate_property (property, error))
+ {
+ g_prefix_error (error,
+ "When handling property %s:%s: ",
+ interface->name,
+ property->name);
+ goto out;
+ }
+ }
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gboolean
parse (char **xml_files,
GError **error)
@@ -2038,9 +2407,13 @@ parse (char **xml_files,
if (!parse_interfaces_enums_and_structs (nodes, error))
goto out;
+ /* now that we have enums/structs in place, we can determine/validate the complete type of each signature */
+ if (!determine_and_validate_complete_types (error))
+ goto out;
+
/* then generate... */
- /* ... regular expression for Docbook links */
+ /* ... regular expression for Docbook/gtkdoc links */
if (!create_link_regexs (error))
goto out;
@@ -2110,6 +2483,9 @@ parse (char **xml_files,
g_slist_foreach (generated_files, (GFunc) g_free, NULL);
g_slist_free (generated_files);
+ g_slist_foreach (complete_types, (GFunc) complete_type_free, NULL);
+ g_slist_free (complete_types);
+
return ret;
}
diff --git a/src/eggdbus/eggdbusbindingtool.h b/src/eggdbus/eggdbusbindingtool.h
index fbf1e84..b827dfe 100644
--- a/src/eggdbus/eggdbusbindingtool.h
+++ b/src/eggdbus/eggdbusbindingtool.h
@@ -24,6 +24,9 @@
#include <glib-object.h>
#include <eggdbus/eggdbusinterface.h>
+#include "completetype.h"
+#include "struct.h"
+#include "enum.h"
G_BEGIN_DECLS
@@ -68,6 +71,14 @@ GSList *get_enums_declared_in_interface (const EggDBusInterfaceInfo *interface);
GSList *get_structs_declared_in_interface (const EggDBusInterfaceInfo *interface);
+CompleteType *get_complete_type_for_arg (const EggDBusInterfaceArgInfo *arg);
+
+CompleteType *get_complete_type_for_property (const EggDBusInterfacePropertyInfo *property);
+
+StructData *find_struct_by_name (const gchar *name);
+
+EnumData *find_enum_by_name (const gchar *name);
+
G_END_DECLS
#endif /* __DBUS2GOBJECT_H */
diff --git a/src/eggdbus/eggdbusinterface.c b/src/eggdbus/eggdbusinterface.c
index 32b0029..ee0402b 100644
--- a/src/eggdbus/eggdbusinterface.c
+++ b/src/eggdbus/eggdbusinterface.c
@@ -24,6 +24,7 @@
#endif
#include <string.h>
#include "eggdbusinterface.h"
+#include "eggdbusprivate.h"
/**
* SECTION:eggdbusinterface
@@ -84,7 +85,6 @@ egg_dbus_interface_get_type (void)
*
* Returns: A string. Do not free, it is owned by @annotations.
**/
-/* ---------------------------------------------------------------------------------------------------- */
const gchar *
egg_dbus_interface_annotation_info_lookup (const EggDBusInterfaceAnnotationInfo *annotations,
const gchar *annotation_name)
@@ -107,6 +107,39 @@ egg_dbus_interface_annotation_info_lookup (const EggDBusInterfaceAnnotationInfo
return ret;
}
+void
+_egg_dbus_interface_annotation_info_set (EggDBusInterfaceAnnotationInfo **annotations,
+ const gchar *annotation_name,
+ gpointer value)
+{
+ guint n;
+
+ /* TODO: handle value == NULL by removing the annotation */
+
+ for (n = 0; *annotations != NULL && (*annotations)[n].key != NULL; n++)
+ {
+ if (strcmp ((*annotations)[n].key, annotation_name) == 0)
+ {
+ g_free ((gchar *) (*annotations)[n].value);
+ (*annotations)[n].value = value;
+ goto out;
+ }
+ }
+
+ *annotations = g_realloc (*annotations, sizeof (EggDBusInterfaceAnnotationInfo) * (n + 2));
+
+ (*annotations)[n].key = g_strdup (annotation_name);
+ (*annotations)[n].value = value;
+ (*annotations)[n].annotations = NULL;
+
+ (*annotations)[n + 1].key = NULL;
+ (*annotations)[n + 1].value = NULL;
+ (*annotations)[n + 1].annotations = NULL;
+
+ out:
+ ;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
/**
diff --git a/src/eggdbus/eggdbusmessage.c b/src/eggdbus/eggdbusmessage.c
index 51631d3..ed747a5 100644
--- a/src/eggdbus/eggdbusmessage.c
+++ b/src/eggdbus/eggdbusmessage.c
@@ -2615,6 +2615,7 @@ egg_dbus_append_value_to_iter (DBusMessageIter *iter,
ret = FALSE;
+ /* TODO: we could probably speed this up a great bit by accessing the GValue directly */
if (strcmp (signature, DBUS_TYPE_STRING_AS_STRING) == 0)
{
const char *val = g_value_get_string (value);
@@ -2663,7 +2664,19 @@ egg_dbus_append_value_to_iter (DBusMessageIter *iter,
}
else if (strcmp (signature, DBUS_TYPE_UINT32_AS_STRING) == 0)
{
- dbus_uint32_t val = g_value_get_uint (value);
+ dbus_uint32_t val;
+ if (value->g_type == G_TYPE_UINT)
+ {
+ val = g_value_get_uint (value);
+ }
+ else if (G_TYPE_IS_ENUM (value->g_type))
+ {
+ val = g_value_get_enum (value);
+ }
+ else if (G_TYPE_IS_FLAGS (value->g_type))
+ {
+ val = g_value_get_flags (value);
+ }
dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &val);
}
else if (strcmp (signature, DBUS_TYPE_INT64_AS_STRING) == 0)
diff --git a/src/eggdbus/eggdbusprivate.h b/src/eggdbus/eggdbusprivate.h
index b4ddee7..3161b65 100644
--- a/src/eggdbus/eggdbusprivate.h
+++ b/src/eggdbus/eggdbusprivate.h
@@ -79,6 +79,10 @@ void _egg_dbus_interface_proxy_handle_property_changed (EggDBusInterfaceProxy *i
void _egg_dbus_interface_proxy_invalidate_properties (EggDBusInterfaceProxy *interface_proxy);
+void _egg_dbus_interface_annotation_info_set (EggDBusInterfaceAnnotationInfo **annotations,
+ const gchar *annotation_name,
+ gpointer value);
+
G_END_DECLS
#endif /* __EGG_DBUS_PRIVATE_H */
diff --git a/src/eggdbus/enum.c b/src/eggdbus/enum.c
index c4eb2de..842e93b 100644
--- a/src/eggdbus/enum.c
+++ b/src/eggdbus/enum.c
@@ -79,6 +79,7 @@ enum_data_new_from_annotation_for_error_domain (const EggDBusInterfaceAnnotation
GPtrArray *elems;
guint n;
gchar *maximal_dbus_prefix;
+ guint next_value;
enum_data = g_new0 (EnumData, 1);
enum_data->type = ENUM_DATA_TYPE_ERROR_DOMAIN;
@@ -91,6 +92,7 @@ enum_data_new_from_annotation_for_error_domain (const EggDBusInterfaceAnnotation
maximal_dbus_prefix = NULL;
+ next_value = 0;
for (n = 0; annotation->annotations != NULL && annotation->annotations[n].key != NULL; n++)
{
const EggDBusInterfaceAnnotationInfo *embedded_annotation = annotation->annotations + n;
@@ -136,11 +138,13 @@ enum_data_new_from_annotation_for_error_domain (const EggDBusInterfaceAnnotation
value_str);
goto fail;
}
+ next_value = elem_data->value;
}
else
{
- elem_data->value = -1;
+ elem_data->value = next_value;
}
+ next_value += 1;
if (maximal_dbus_prefix == NULL)
{
@@ -206,6 +210,17 @@ enum_data_new_from_annotation_for_error_domain (const EggDBusInterfaceAnnotation
enum_data->maximal_dbus_prefix = maximal_dbus_prefix;
enum_data->num_elements = elems->len;
+
+ if (enum_data->num_elements == 0)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No members in error domain %s",
+ enum_data->name);
+ goto fail;
+ }
+
enum_data->elements = (EnumElemData **) g_ptr_array_free (elems, FALSE);
return enum_data;
@@ -243,6 +258,7 @@ enum_data_new_from_annotation_for_flags (const EggDBusInterfaceAnnotationInfo *
EnumData *enum_data;
GPtrArray *elems;
guint n;
+ guint next_value;
enum_data = g_new0 (EnumData, 1);
enum_data->type = ENUM_DATA_TYPE_FLAGS;
@@ -253,6 +269,7 @@ enum_data_new_from_annotation_for_flags (const EggDBusInterfaceAnnotationInfo *
elems = g_ptr_array_new ();
+ next_value = 1;
for (n = 0; annotation->annotations != NULL && annotation->annotations[n].key != NULL; n++)
{
const EggDBusInterfaceAnnotationInfo *embedded_annotation = annotation->annotations + n;
@@ -297,12 +314,16 @@ enum_data_new_from_annotation_for_flags (const EggDBusInterfaceAnnotationInfo *
value_str);
goto fail;
}
+ next_value = elem_data->value;
}
else
{
- elem_data->value = -1;
+ elem_data->value = next_value;
}
-
+ if (next_value == 0)
+ next_value = 1;
+ else
+ next_value *= 2;
name_uscore = egg_dbus_utils_camel_case_to_uscore (elem_data->name);
elem_data->g_name_uscore_upper = g_ascii_strup (name_uscore, -1);
@@ -313,6 +334,17 @@ enum_data_new_from_annotation_for_flags (const EggDBusInterfaceAnnotationInfo *
}
enum_data->num_elements = elems->len;
+
+ if (enum_data->num_elements == 0)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No members in flag enumeration %s",
+ enum_data->name);
+ goto fail;
+ }
+
enum_data->elements = (EnumElemData **) g_ptr_array_free (elems, FALSE);
return enum_data;
@@ -352,6 +384,7 @@ enum_data_new_from_annotation_for_enum (const EggDBusInterfaceAnnotationInfo *a
EnumData *enum_data;
GPtrArray *elems;
guint n;
+ guint next_value;
enum_data = g_new0 (EnumData, 1);
enum_data->type = ENUM_DATA_TYPE_ENUM;
@@ -362,6 +395,7 @@ enum_data_new_from_annotation_for_enum (const EggDBusInterfaceAnnotationInfo *a
elems = g_ptr_array_new ();
+ next_value = 0;
for (n = 0; annotation->annotations != NULL && annotation->annotations[n].key != NULL; n++)
{
const EggDBusInterfaceAnnotationInfo *embedded_annotation = annotation->annotations + n;
@@ -406,12 +440,13 @@ enum_data_new_from_annotation_for_enum (const EggDBusInterfaceAnnotationInfo *a
value_str);
goto fail;
}
+ next_value = elem_data->value;
}
else
{
- elem_data->value = -1;
+ elem_data->value = next_value;
}
-
+ next_value += 1;
name_uscore = egg_dbus_utils_camel_case_to_uscore (elem_data->name);
elem_data->g_name_uscore_upper = g_ascii_strup (name_uscore, -1);
@@ -422,6 +457,17 @@ enum_data_new_from_annotation_for_enum (const EggDBusInterfaceAnnotationInfo *a
}
enum_data->num_elements = elems->len;
+
+ if (enum_data->num_elements == 0)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "No members in enumeration %s",
+ enum_data->name);
+ goto fail;
+ }
+
enum_data->elements = (EnumElemData **) g_ptr_array_free (elems, FALSE);
return enum_data;
@@ -478,7 +524,6 @@ enum_generate_h_file (EnumData *enum_data,
gchar *enum_summary_doc_string;
gchar *enum_doc_string;
guint n;
- guint m;
ret = FALSE;
@@ -555,7 +600,6 @@ enum_generate_h_file (EnumData *enum_data,
name_space_uscore_upper,
enum_data->name_uscore_upper);
}
- m = 1;
}
for (n = 0; n < enum_data->num_elements; n++)
@@ -588,28 +632,19 @@ enum_generate_h_file (EnumData *enum_data,
name_space_uscore_upper,
enum_data->name_uscore_upper);
}
- m = 1;
- }
- else
- {
- m = 0;
}
-
for (n = 0; n < enum_data->num_elements; n++)
{
EnumElemData *elem = enum_data->elements[n];
- if (elem->value != -1)
- m = elem->value;
-
if (enum_data->type == ENUM_DATA_TYPE_ERROR_DOMAIN)
{
g_print (" %s_%s_%s = %d, /*< nick=%s >*/\n",
name_space_uscore_upper,
enum_data->name_uscore_upper,
elem->g_name_uscore_upper,
- m,
+ elem->value,
elem->name);
}
else if (enum_data->type == ENUM_DATA_TYPE_FLAGS)
@@ -618,7 +653,7 @@ enum_generate_h_file (EnumData *enum_data,
name_space_uscore_upper,
enum_data->name_uscore_upper,
elem->g_name_uscore_upper,
- m);
+ elem->value);
}
else if (enum_data->type == ENUM_DATA_TYPE_ENUM)
{
@@ -626,20 +661,7 @@ enum_generate_h_file (EnumData *enum_data,
name_space_uscore_upper,
enum_data->name_uscore_upper,
elem->g_name_uscore_upper,
- m);
- }
-
- if (enum_data->type == ENUM_DATA_TYPE_ERROR_DOMAIN ||
- enum_data->type == ENUM_DATA_TYPE_ENUM)
- {
- m++;
- }
- else if (enum_data->type == ENUM_DATA_TYPE_FLAGS)
- {
- if (m == 0)
- m = 1;
- else
- m *= 2;
+ elem->value);
}
}
diff --git a/src/eggdbus/enum.h b/src/eggdbus/enum.h
index 4649fb8..776cb0b 100644
--- a/src/eggdbus/enum.h
+++ b/src/eggdbus/enum.h
@@ -68,8 +68,7 @@ struct _EnumElemData
/* the G name of the value (without enum prefix) */
gchar *g_name_uscore_upper;
- /* -1 means not set */
- gint value;
+ guint value;
const EggDBusInterfaceAnnotationInfo *annotations;
};
diff --git a/src/eggdbus/interface.c b/src/eggdbus/interface.c
index 03fa5d6..372f3b4 100644
--- a/src/eggdbus/interface.c
+++ b/src/eggdbus/interface.c
@@ -2008,8 +2008,9 @@ interface_generate_iface_c_file (const EggDBusInterfaceInfo *interface,
for (n = 0; n < interface->num_properties; n++)
{
const EggDBusInterfacePropertyInfo *prop = interface->properties + n;
- const char *access_string;
+ const gchar *access_string;
gchar *prop_doc_string;
+ CompleteType *type;
if ((prop->flags & EGG_DBUS_INTERFACE_PROPERTY_INFO_FLAGS_READABLE) &&
(prop->flags & EGG_DBUS_INTERFACE_PROPERTY_INFO_FLAGS_WRITABLE))
@@ -2040,6 +2041,8 @@ interface_generate_iface_c_file (const EggDBusInterfaceInfo *interface,
prop->g_name,
prop_doc_string);
+ type = get_complete_type_for_property (prop);
+
if (prop->signature[0] == DBUS_STRUCT_BEGIN_CHAR)
{
gchar *type_name;
@@ -2074,16 +2077,56 @@ interface_generate_iface_c_file (const EggDBusInterfaceInfo *interface,
}
else
{
- g_print (" g_object_interface_install_property (g_iface,\n"
- " egg_dbus_param_spec_for_signature (\n"
- " \"%s\",\n"
- " \"%s\",\n"
- " \"%s\",\n"
- " \"%s\",\n",
- prop->g_name,
- prop->name,
- prop_doc_string,
- prop->signature);
+ EnumData *enum_data;
+
+ if (type->user_type != NULL)
+ enum_data = find_enum_by_name (type->user_type);
+ else
+ enum_data = NULL;
+
+ if (enum_data != NULL && enum_data->type == ENUM_DATA_TYPE_ENUM)
+ {
+ g_print (" g_object_interface_install_property (g_iface,\n"
+ " g_param_spec_enum (\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " %s_TYPE_%s,\n"
+ " %d,\n",
+ prop->g_name,
+ prop->name,
+ prop_doc_string,
+ name_space_uscore_upper, enum_data->name_uscore_upper,
+ enum_data->elements[0]->value);
+ }
+ else if (enum_data != NULL && enum_data->type == ENUM_DATA_TYPE_FLAGS)
+ {
+ g_print (" g_object_interface_install_property (g_iface,\n"
+ " g_param_spec_flags (\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " %s_TYPE_%s,\n"
+ " %d,\n",
+ prop->g_name,
+ prop->name,
+ prop_doc_string,
+ name_space_uscore_upper, enum_data->name_uscore_upper,
+ enum_data->elements[0]->value);
+ }
+ else
+ {
+ g_print (" g_object_interface_install_property (g_iface,\n"
+ " egg_dbus_param_spec_for_signature (\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " \"%s\",\n"
+ " \"%s\",\n",
+ prop->g_name,
+ prop->name,
+ prop_doc_string,
+ prop->signature);
+ }
}
g_print (" %s |\n"
diff --git a/src/eggdbus/org.freedesktop.DBus.xml b/src/eggdbus/org.freedesktop.DBus.xml
index bf52594..e5d2a53 100644
--- a/src/eggdbus/org.freedesktop.DBus.xml
+++ b/src/eggdbus/org.freedesktop.DBus.xml
@@ -105,10 +105,12 @@
<annotation name="org.gtk.EggDBus.DocString" value="Name to request."/>
</arg>
<arg direction="in" type="u" name="flags">
+ <annotation name="org.gtk.EggDBus.Type" value="RequestNameFlags"/>
<annotation name="org.gtk.EggDBus.FlagsType" value="RequestNameFlags"/>
<annotation name="org.gtk.EggDBus.DocString" value="Flags."/>
</arg>
<arg direction="out" type="u" name="value">
+ <annotation name="org.gtk.EggDBus.Type" value="RequestNameReply"/>
<annotation name="org.gtk.EggDBus.EnumType" value="RequestNameReply"/>
<annotation name="org.gtk.EggDBus.DocString" value="Return value."/>
</arg>
@@ -121,6 +123,7 @@
<annotation name="org.gtk.EggDBus.DocString" value="Name to release."/>
</arg>
<arg direction="out" type="u" name="value">
+ <annotation name="org.gtk.EggDBus.Type" value="ReleaseNameReply"/>
<annotation name="org.gtk.EggDBus.EnumType" value="ReleaseNameReply"/>
<annotation name="org.gtk.EggDBus.DocString" value="Return value."/>
</arg>
@@ -136,6 +139,7 @@
<annotation name="org.gtk.EggDBus.DocString" value="Flags (currently not used)."/>
</arg>
<arg direction="out" type="u" name="value">
+ <annotation name="org.gtk.EggDBus.Type" value="StartServiceByNameReply"/>
<annotation name="org.gtk.EggDBus.EnumType" value="StartServiceByNameReply"/>
<annotation name="org.gtk.EggDBus.DocString" value="Reply"/>
</arg>
diff --git a/src/eggdbus/struct.c b/src/eggdbus/struct.c
index c764ed0..c66f837 100644
--- a/src/eggdbus/struct.c
+++ b/src/eggdbus/struct.c
@@ -34,6 +34,9 @@ static void
struct_elem_data_free (StructElemData *struct_elem_data)
{
g_free (struct_elem_data->name);
+ g_free (struct_elem_data->type_string);
+ if (struct_elem_data->type != NULL)
+ complete_type_free (struct_elem_data->type);
g_free (struct_elem_data->signature);
g_free (struct_elem_data);
}
@@ -55,6 +58,126 @@ struct_data_free (StructData *struct_data)
g_free (struct_data);
}
+static gchar *
+break_down_type_cb (const gchar *user_type,
+ gpointer user_data,
+ GError **error)
+{
+ StructData *struct_data;
+ EnumData *enum_data;
+ gchar *ret;
+
+ ret = NULL;
+
+ /* user type may be a struct */
+ struct_data = find_struct_by_name (user_type);
+ if (struct_data != NULL)
+ {
+ ret = g_strdup (struct_data->type_string);
+ goto out;
+ }
+
+ /* ... or an enumeration */
+ enum_data = find_enum_by_name (user_type);
+ if (enum_data != NULL)
+ {
+ /* error domains can't be used */
+ if (enum_data->type == ENUM_DATA_TYPE_FLAGS ||
+ enum_data->type == ENUM_DATA_TYPE_ENUM)
+ {
+ ret = g_strdup ("UInt32");
+ goto out;
+ }
+ }
+
+
+ if (ret == NULL)
+ {
+ g_set_error (error,
+ EGG_DBUS_ERROR,
+ EGG_DBUS_ERROR_FAILED,
+ "Unknown type %s",
+ user_type);
+ }
+
+ out:
+ return ret;
+}
+
+gboolean
+struct_data_compute_types_and_signatures (StructData *struct_data,
+ GError **error)
+{
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (struct_data->signature != NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+
+ if (struct_data->user_supplied)
+ {
+ CompleteType *type;
+
+ type = complete_type_from_string (struct_data->type_string,
+ break_down_type_cb,
+ NULL,
+ error);
+
+ if (type == NULL)
+ goto out;
+
+ struct_data->signature = g_strdup (type->signature);
+ complete_type_free (type);
+ }
+ else
+ {
+ guint n;
+ GString *signature;
+ GString *type_string;
+
+ type_string = g_string_new ("Struct<");
+ signature = g_string_new ("(");
+
+ for (n = 0; n < struct_data->num_elements; n++)
+ {
+ StructElemData *elem = struct_data->elements[n];
+
+ elem->type = complete_type_from_string (elem->type_string,
+ break_down_type_cb,
+ NULL,
+ error);
+
+ if (elem->type == NULL)
+ {
+ g_string_free (signature, TRUE);
+ goto out;
+ }
+
+ /* this is a little redundant */
+ elem->signature = g_strdup (elem->type->signature);
+
+ if (n > 0)
+ g_string_append_c (type_string, ',');
+ g_string_append (type_string, elem->type_string);
+ g_string_append (signature, elem->type->signature);
+ }
+
+ g_string_append_c (type_string, '>');
+ g_string_append_c (signature, ')');
+ struct_data->signature = g_string_free (signature, FALSE);
+ struct_data->type_string = g_string_free (type_string, FALSE);
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
/* Structs specified through annotations are of this form
*
* <annotation name="org.gtk.EggDBus.DeclareStruct" value="DescribedPoint">
@@ -80,9 +203,7 @@ struct_data_new_from_annotation (const EggDBusInterfaceAnnotationInfo *annotati
GError **error)
{
StructData *struct_data;
- DBusError derror;
GPtrArray *elems;
- GString *signature;
const gchar *user_supplied;
guint n;
@@ -93,38 +214,18 @@ struct_data_new_from_annotation (const EggDBusInterfaceAnnotationInfo *annotati
struct_data->annotations = annotation->annotations;
elems = NULL;
- signature = NULL;
- /* check for user supplied struct GInterfaces */
+ /* check for user supplied structs */
user_supplied = egg_dbus_interface_annotation_info_lookup (annotation->annotations,
- "org.gtk.EggDBus.Struct.Signature");
+ "org.gtk.EggDBus.Struct.Type");
if (user_supplied != NULL)
{
- struct_data->signature = g_strdup (user_supplied);
-
- /* validate the signature */
- dbus_error_init (&derror);
- if (struct_data->signature[0] != DBUS_STRUCT_BEGIN_CHAR ||
- struct_data->signature[strlen (struct_data->signature) - 1] != DBUS_STRUCT_END_CHAR ||
- !dbus_signature_validate (struct_data->signature, &derror))
- {
- g_set_error (error,
- EGG_DBUS_ERROR,
- EGG_DBUS_ERROR_FAILED,
- "Signature %s in user supplied struct %s is not valid: %s",
- struct_data->signature,
- struct_data->name,
- derror.message);
- dbus_error_free (&derror);
- goto fail;
- }
-
+ struct_data->type_string = g_strdup (user_supplied);
struct_data->user_supplied = TRUE;
goto out;
}
elems = g_ptr_array_new ();
- signature = g_string_new ("(");
for (n = 0; annotation->annotations != NULL && annotation->annotations[n].key != NULL; n++)
{
@@ -158,44 +259,24 @@ struct_data_new_from_annotation (const EggDBusInterfaceAnnotationInfo *annotati
g_set_error (error,
EGG_DBUS_ERROR,
EGG_DBUS_ERROR_FAILED,
- "No signature:name separator found for value '%s'",
+ "No typename:name separator found for value '%s'",
embedded_annotation->value);
struct_elem_data_free (elem_data);
goto fail;
}
- elem_data->signature = g_strndup (embedded_annotation->value, s - embedded_annotation->value);
+ elem_data->type_string = g_strndup (embedded_annotation->value, s - embedded_annotation->value);
elem_data->name = g_strdup (s + 1);
elem_data->annotations = embedded_annotation->annotations;
/* TODO: validate name */
- dbus_error_init (&derror);
- if (!dbus_signature_validate (elem_data->signature, &derror))
- {
- g_set_error (error,
- EGG_DBUS_ERROR,
- EGG_DBUS_ERROR_FAILED,
- "Signature %s for element %s in struct %s is not valid: %s",
- elem_data->signature,
- elem_data->name,
- struct_data->name,
- derror.message);
- dbus_error_free (&derror);
- struct_elem_data_free (elem_data);
- goto fail;
- }
-
g_ptr_array_add (elems, elem_data);
-
- g_string_append (signature, elem_data->signature);
}
- g_string_append_c (signature, ')');
struct_data->num_elements = elems->len;
struct_data->elements = (StructElemData **) g_ptr_array_free (elems, FALSE);
- struct_data->signature = g_string_free (signature, FALSE);
out:
return struct_data;
@@ -207,8 +288,6 @@ struct_data_new_from_annotation (const EggDBusInterfaceAnnotationInfo *annotati
g_ptr_array_foreach (elems, (GFunc) struct_elem_data_free, NULL);
g_ptr_array_free (elems, TRUE);
}
- if (signature != NULL)
- g_string_free (signature, TRUE);
return NULL;
}
diff --git a/src/eggdbus/struct.h b/src/eggdbus/struct.h
index 660f2e0..99931a2 100644
--- a/src/eggdbus/struct.h
+++ b/src/eggdbus/struct.h
@@ -24,6 +24,7 @@
#include <glib-object.h>
#include "eggdbusinterface.h"
+#include "completetype.h"
G_BEGIN_DECLS
@@ -37,7 +38,6 @@ struct _StructData
gchar *name;
gchar *name_uscore;
gchar *name_uscore_upper;
- gchar *signature;
gboolean user_supplied;
/* these members are only set if user_supplied == FALSE */
@@ -48,17 +48,29 @@ struct _StructData
/* the interface the struct was declared in or NULL if not declared in an interface */
const EggDBusInterfaceInfo *interface;
+
+ gchar *signature;
+ CompleteType *type;
+ gchar *type_string;
};
struct _StructElemData
{
gchar *name;
- gchar *signature;
+ gchar *type_string;
+
const EggDBusInterfaceAnnotationInfo *annotations;
+
+ gchar *signature;
+ CompleteType *type;
};
StructData *struct_data_new_from_annotation (const EggDBusInterfaceAnnotationInfo *annotation, GError **error);
+gboolean struct_data_compute_types_and_signatures (StructData *struct_data,
+ GError **error);
+
+
void struct_data_free (StructData *struct_data);
gboolean struct_generate_h_file (StructData *struct_data,
diff --git a/src/tests/com.example.Frob.xml b/src/tests/com.example.Frob.xml
index 9027d7f..c3aa63f 100644
--- a/src/tests/com.example.Frob.xml
+++ b/src/tests/com.example.Frob.xml
@@ -6,10 +6,10 @@
<annotation name="org.gtk.EggDBus.DocString" value="The #Point type is used for 2D integer points."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="2D point"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:x">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:x">
<annotation name="org.gtk.EggDBus.DocString" value="The X coordinate"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:y">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:y">
<annotation name="org.gtk.EggDBus.DocString" value="The Y coordinate"/>
</annotation>
</annotation>
@@ -18,10 +18,10 @@
<annotation name="org.gtk.EggDBus.DocString" value="The #Pair type is used to group two integers together."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Pair of integers"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:first">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:first">
<annotation name="org.gtk.EggDBus.DocString" value="The first element"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:second">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:second">
<annotation name="org.gtk.EggDBus.DocString" value="The second element"/>
</annotation>
</annotation>
@@ -30,12 +30,12 @@
<annotation name="org.gtk.EggDBus.DocString" value="Test type for wrapping (s(ii))."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Described point"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="s:desc">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="String:desc">
<annotation name="org.gtk.EggDBus.DocString" value="A description of the described point"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="(ii):point">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Point:point">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="The point being described"/>
- <annotation name="org.gtk.EggDBus.StructType" value="Point"/>
</annotation>
</annotation>
@@ -43,12 +43,12 @@
<annotation name="org.gtk.EggDBus.DocString" value="Test type for wrapping (s(ii))."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Described pair"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="s:desc">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="String:desc">
<annotation name="org.gtk.EggDBus.DocString" value="A description of the described pair"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="(ii):pair">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Pair:pair">
+ <annotation name="org.gtk.EggDBus.Type" value="Pair"/>
<annotation name="org.gtk.EggDBus.DocString" value="The pair being described"/>
- <annotation name="org.gtk.EggDBus.StructType" value="Pair"/>
</annotation>
</annotation>
@@ -56,14 +56,14 @@
<annotation name="org.gtk.EggDBus.DocString" value="Test type for wrapping (s(ii)s)."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Extended described point"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="s:desc">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="String:desc">
<annotation name="org.gtk.EggDBus.DocString" value="A description of the described point"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="(ii):point">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Point:point">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="The point being described"/>
- <annotation name="org.gtk.EggDBus.StructType" value="Point"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="s:ext_desc">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="String:ext_desc">
<annotation name="org.gtk.EggDBus.DocString" value="An extended description of the point"/>
</annotation>
</annotation>
@@ -72,19 +72,19 @@
<annotation name="org.gtk.EggDBus.DocString" value="Test type for a complex structure (siivi)."/>
<annotation name="org.gtk.EggDBus.DocString.Summary" value="Complex structure"/>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="s:name">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="String:name">
<annotation name="org.gtk.EggDBus.DocString" value="A name"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:anger_level">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:anger_level">
<annotation name="org.gtk.EggDBus.DocString" value="The level of anger"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:threat_level">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:threat_level">
<annotation name="org.gtk.EggDBus.DocString" value="The level of threat"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="v:a_variant">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Variant:a_variant">
<annotation name="org.gtk.EggDBus.DocString" value="Some variant"/>
</annotation>
- <annotation name="org.gtk.EggDBus.Struct.Member" value="i:override_c_type">
+ <annotation name="org.gtk.EggDBus.Struct.Member" value="Int32:override_c_type">
<annotation name="org.gtk.EggDBus.DocString" value="Some primitive type"/>
<annotation name="org.gtk.EggDBus.CType" value="TestSomeExampleCType"/>
</annotation>
@@ -158,10 +158,18 @@
</method>
<method name="TestStructureTypes">
- <arg direction="in" type="(ii)" name="s1" />
- <arg direction="in" type="(s(ii))" name="s2" />
- <arg direction="out" type="(ii)" />
- <arg direction="out" type="(s(ii))" />
+ <arg direction="in" type="(ii)" name="s1">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
+ </arg>
+ <arg direction="in" type="(s(ii))" name="s2">
+ <annotation name="org.gtk.EggDBus.Type" value="DescribedPoint"/>
+ </arg>
+ <arg direction="out" type="(ii)">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
+ </arg>
+ <arg direction="out" type="(s(ii))">
+ <annotation name="org.gtk.EggDBus.Type" value="DescribedPoint"/>
+ </arg>
</method>
<method name="TestArrayOfStructureTypes">
@@ -219,29 +227,47 @@
<arg direction="out" type="a{sat}" />
<arg direction="in" type="a{sad}" name="hsad" />
<arg direction="out" type="a{sad}" />
- <arg direction="in" type="a{sa(ii)}" name="hash_of_point_arrays" />
- <arg direction="out" type="a{sa(ii)}" name="new_hash_of_point_arrays" />
+ <arg direction="in" type="a{sa(ii)}" name="hash_of_point_arrays">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Array<Point>>"/>
+ </arg>
+ <arg direction="out" type="a{sa(ii)}" name="new_hash_of_point_arrays">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Array<Point>>"/>
+ </arg>
</method>
<method name="TestHashTableOfStructures">
- <arg direction="in" type="a{s(ii)}" name="hash_of_points" />
- <arg direction="out" type="a{s(s(ii))}" name="hash_of_described_points" />
+ <arg direction="in" type="a{s(ii)}" name="hash_of_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Point>"/>
+ </arg>
+ <arg direction="out" type="a{s(s(ii))}" name="hash_of_described_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,DescribedPoint>"/>
+ </arg>
</method>
<method name="TestHashTableOfHashTablesOfStructures">
- <arg direction="in" type="a{sa{s(ii)}}" name="hash_of_hash_of_points" />
- <arg direction="out" type="a{sa{s(ii)}}" name="new_hash_of_hash_of_points" />
+ <arg direction="in" type="a{sa{s(ii)}}" name="hash_of_hash_of_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Dict<String,Point>>"/>
+ </arg>
+ <arg direction="out" type="a{sa{s(ii)}}" name="new_hash_of_hash_of_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Dict<String,Point>>"/>
+ </arg>
</method>
<method name="TestArrayOfHashTablesOfStructures">
- <arg direction="in" type="aa{s(ii)}" name="array_of_hash_of_points" />
- <arg direction="out" type="aa{s(ii)}" name="new_array_of_hash_of_points" />
+ <arg direction="in" type="aa{s(ii)}" name="array_of_hash_of_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Array<Dict<String,Point>>"/>
+ </arg>
+ <arg direction="out" type="aa{s(ii)}" name="new_array_of_hash_of_points">
+ <annotation name="org.gtk.EggDBus.Type" value="Array<Dict<String,Point>>"/>
+ </arg>
</method>
<method name="TestArrayOfArrays">
<!-- TODO: add tests for signature type -->
<arg direction="in" type="aas" name="aas" />
- <arg direction="in" type="aa(ii)" name="aastruct" />
+ <arg direction="in" type="aa(ii)" name="aastruct">
+ <annotation name="org.gtk.EggDBus.Type" value="Array<Array<Point>>"/>
+ </arg>
<arg direction="in" type="aao" name="aao" />
<arg direction="in" type="aai" name="aai" />
<arg direction="in" type="aay" name="aay" />
@@ -254,7 +280,9 @@
<arg direction="in" type="aad" name="aad" />
<arg direction="in" type="aaas" name="aaas" />
<arg direction="out" type="aas" name="ret_aas"/>
- <arg direction="out" type="aa(ii)" name="ret_aastruct"/>
+ <arg direction="out" type="aa(ii)" name="ret_aastruct">
+ <annotation name="org.gtk.EggDBus.Type" value="Array<Array<Point>>"/>
+ </arg>
<arg direction="out" type="aao" name="ret_aao"/>
<arg direction="out" type="aai" name="ret_aai"/>
<arg direction="out" type="aay" name="ret_aay"/>
@@ -324,10 +352,16 @@
</signal>
<signal name="SignalWithStructureAndHash">
- <arg type="(ii)" name="point" />
- <arg type="(s(ii))" name="described-point" />
- <arg type="a{ss}" name="hash_of_string_to_stirng" />
- <arg type="a{s(ii)}" name="hash_of_string_to_point" />
+ <arg type="(ii)" name="point">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
+ </arg>
+ <arg type="(s(ii))" name="described-point">
+ <annotation name="org.gtk.EggDBus.Type" value="DescribedPoint"/>
+ </arg>
+ <arg type="a{ss}" name="hash_of_string_to_string" />
+ <arg type="a{s(ii)}" name="hash_of_string_to_point">
+ <annotation name="org.gtk.EggDBus.Type" value="Dict<String,Point>"/>
+ </arg>
</signal>
<method name="EmitTestSignals">
diff --git a/src/tests/com.example.Tweak.xml b/src/tests/com.example.Tweak.xml
index 82a2e6c..7b869e1 100644
--- a/src/tests/com.example.Tweak.xml
+++ b/src/tests/com.example.Tweak.xml
@@ -13,11 +13,12 @@
<annotation name="org.gtk.EggDBus.DocString" value="The Bar factor"/>
</property>
<property name="baz" type="(ii)" access="read">
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="The Baz indicator"/>
</property>
<property name="baz-forced-to-use-pair" type="(ii)" access="read">
- <annotation name="org.gtk.EggDBus.StructType" value="Pair"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Pair"/>
<annotation name="org.gtk.EggDBus.DocString" value=" A slightly different Baz indicator "/>
</property>
@@ -30,6 +31,16 @@
<annotation name="org.gtk.EggDBus.DocString" value="I'm a special C type"/>
</property>
+ <property name="EscapeVehicle" type="u" access="readwrite">
+ <annotation name="org.gtk.EggDBus.Type" value="Vehicle"/>
+ <annotation name="org.gtk.EggDBus.DocString" value="The vehicle used for escaping."/>
+ </property>
+
+ <property name="DefaultCreateFlags" type="u" access="readwrite">
+ <annotation name="org.gtk.EggDBus.Type" value="CreateFlags"/>
+ <annotation name="org.gtk.EggDBus.DocString" value="The default create flags to use."/>
+ </property>
+
<method name="BlockUntilRWPropertyChanges">
<annotation name="org.gtk.EggDBus.DocString" value="Blocks until #Tweak:SomeReadWriteProperty changes"/>
<arg direction="out" type="s" name="NewPropValue">
@@ -95,19 +106,19 @@
<method name="MethodStructDisambiguation">
<annotation name="org.gtk.EggDBus.DocString" value="A method to check we can properly disambiguate what structure wrapper types to use"/>
<arg direction="in" type="(ii)" name="pair">
- <annotation name="org.gtk.EggDBus.StructType" value="Pair"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Pair"/>
<annotation name="org.gtk.EggDBus.DocString" value="A pair"/>
</arg>
<arg direction="in" type="(ii)" name="point">
- <annotation name="org.gtk.EggDBus.StructType" value="Point"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="A point"/>
</arg>
<arg direction="out" type="(ii)" name="enhanced_point">
- <annotation name="org.gtk.EggDBus.StructType" value="Point"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="An enhanced point"/>
</arg>
<arg direction="out" type="(ii)" name="enhanced_pair">
- <annotation name="org.gtk.EggDBus.StructType" value="Pair"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Pair"/>
<annotation name="org.gtk.EggDBus.DocString" value="An enhanced pair"/>
</arg>
</method>
@@ -115,11 +126,11 @@
<signal name="SignalStructDisambiguation">
<annotation name="org.gtk.EggDBus.DocString" value="A signal to check we can properly disambiguate what structure wrapper types to use"/>
<arg type="(ii)" name="pair">
- <annotation name="org.gtk.EggDBus.StructType" value="Pair"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Pair"/>
<annotation name="org.gtk.EggDBus.DocString" value="A pair"/>
</arg>
<arg type="(ii)" name="point">
- <annotation name="org.gtk.EggDBus.StructType" value="Point"/>
+ <annotation name="org.gtk.EggDBus.Type" value="Point"/>
<annotation name="org.gtk.EggDBus.DocString" value="A point"/>
</arg>
</signal>
@@ -144,6 +155,14 @@
</arg>
</method>
+ <signal name="EscapeVehicleChanged">
+ <annotation name="org.gtk.EggDBus.DocString" value="A signal to check we properly support emitting signals with enums"/>
+ <arg type="u" name="new_escape_vehicle">
+ <annotation name="org.gtk.EggDBus.Type" value="Vehicle"/>
+ <annotation name="org.gtk.EggDBus.DocString" value="The new escape vehicle"/>
+ </arg>
+ </signal>
+
</interface>
</node>
diff --git a/src/tests/com.example.Twiddle.xml b/src/tests/com.example.Twiddle.xml
index 743b682..c6dacda 100644
--- a/src/tests/com.example.Twiddle.xml
+++ b/src/tests/com.example.Twiddle.xml
@@ -120,9 +120,9 @@
</annotation>
</annotation>
- <!-- Example of a user supplied struct; user must manually supply the <namespace>Subject GInterface -->
+ <!-- Example of a user supplied struct; user must manually supply the <namespace>Subject class -->
<annotation name="org.gtk.EggDBus.DeclareStruct" value="Subject">
- <annotation name="org.gtk.EggDBus.Struct.Signature" value="(sa{sv})"/>
+ <annotation name="org.gtk.EggDBus.Struct.Type" value="Struct<String,Dict<String,Variant>>"/>
</annotation>
<!-- -->
@@ -150,7 +150,6 @@
<method name="GetMostPowerfulSubject">
<annotation name="org.gtk.EggDBus.DocString" value="Gets the most powerful subject"/>
<arg name="most_powerful_subject" direction="out" type="(sa{sv})">
- <annotation name="org.gtk.EggDBus.StructType" value="Subject"/>
<annotation name="org.gtk.EggDBus.DocString" value="The most powerful subject"/>
</arg>
</method>
diff --git a/src/tests/testclient.c b/src/tests/testclient.c
index 95f602b..dab45f5 100644
--- a/src/tests/testclient.c
+++ b/src/tests/testclient.c
@@ -1965,6 +1965,16 @@ foo_notify_cb (EggDBusObjectProxy *object_proxy,
}
static void
+escape_vehicle_changed_cb (TestTweak *tweak,
+ TestVehicle new_escape_vehicle,
+ gpointer user_data)
+{
+ TestVehicle *dest = user_data;
+
+ *dest = new_escape_vehicle;
+}
+
+static void
test_properties (void)
{
GError *error;
@@ -1976,6 +1986,7 @@ test_properties (void)
gboolean got_foo_notify_event;
EggDBusVariant *variant;
EggDBusHashMap *property_bag;
+ TestVehicle escape_vehicle_signal_value;
error = NULL;
@@ -2080,6 +2091,33 @@ test_properties (void)
g_assert_cmpstr (s, ==, "A new property value");
g_free (s);
+ /* Check that enum and flag properties work; these are using special paramspecs */
+ g_signal_connect (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ "escape-vehicle-changed",
+ (GCallback) escape_vehicle_changed_cb,
+ &escape_vehicle_signal_value);
+ escape_vehicle_signal_value = TEST_VEHICLE_SPORT_UTILITY_VEHICLE;
+ test_tweak_set_escape_vehicle (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ TEST_VEHICLE_TRUCK);
+ g_assert_cmpint (escape_vehicle_signal_value, ==, TEST_VEHICLE_TRUCK);
+ g_assert_cmpint (test_tweak_get_escape_vehicle (TEST_QUERY_INTERFACE_TWEAK (object_proxy)), ==, TEST_VEHICLE_TRUCK);
+ test_tweak_set_escape_vehicle (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ TEST_VEHICLE_PATRIOT);
+ g_assert_cmpint (escape_vehicle_signal_value, ==, TEST_VEHICLE_PATRIOT);
+ g_assert_cmpint (test_tweak_get_escape_vehicle (TEST_QUERY_INTERFACE_TWEAK (object_proxy)), ==, TEST_VEHICLE_PATRIOT);
+ g_signal_handlers_disconnect_by_func (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ escape_vehicle_changed_cb,
+ &escape_vehicle_signal_value);
+
+ test_tweak_set_default_create_flags (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ TEST_CREATE_FLAGS_NONE);
+ g_assert_cmpint (test_tweak_get_default_create_flags (TEST_QUERY_INTERFACE_TWEAK (object_proxy)), ==,
+ TEST_CREATE_FLAGS_NONE);
+ test_tweak_set_default_create_flags (TEST_QUERY_INTERFACE_TWEAK (object_proxy),
+ TEST_CREATE_FLAGS_USE_FROBNICATOR|TEST_CREATE_FLAGS_LOG_ATTEMPT);
+ g_assert_cmpint (test_tweak_get_default_create_flags (TEST_QUERY_INTERFACE_TWEAK (object_proxy)), ==,
+ TEST_CREATE_FLAGS_USE_FROBNICATOR|TEST_CREATE_FLAGS_LOG_ATTEMPT);
+
/* Check that property Change() signals are generated and received.. again, recurse
* in the mainloop so we get the signal before the method returns.
**/
diff --git a/src/tests/testtweakimpl.c b/src/tests/testtweakimpl.c
index 2b22e63..34c2b4f 100644
--- a/src/tests/testtweakimpl.c
+++ b/src/tests/testtweakimpl.c
@@ -31,6 +31,10 @@ typedef struct
gchar *new_foo;
TestSomeExampleCType property_with_ctype;
+
+ TestVehicle escape_vehicle;
+ TestCreateFlags default_create_flags;
+
} TestTweakImplPrivate;
#define TEST_TWEAK_IMPL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TEST_TYPE_TWEAK_IMPL, TestTweakImplPrivate))
@@ -46,6 +50,8 @@ enum
PROP_BAZ_FORCED_TO_USE_PAIR,
PROP_SOME_READ_WRITE_PROPERTY,
PROP_PROPERTY_WITH_CTYPE,
+ PROP_ESCAPE_VEHICLE,
+ PROP_DEFAULT_CREATE_FLAGS,
};
static void test_tweak_impl_tweak_iface_init (TestTweakIface *iface);
@@ -100,6 +106,17 @@ test_tweak_impl_set_property (GObject *object,
priv->property_with_ctype = (TestSomeExampleCType) g_value_get_int (value);
break;
+ case PROP_ESCAPE_VEHICLE:
+ priv->escape_vehicle = g_value_get_enum (value);
+ test_tweak_emit_signal_escape_vehicle_changed (TEST_TWEAK (object),
+ NULL,
+ priv->escape_vehicle);
+ break;
+
+ case PROP_DEFAULT_CREATE_FLAGS:
+ priv->default_create_flags = g_value_get_flags (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -159,6 +176,14 @@ test_tweak_impl_get_property (GObject *object,
g_value_set_int (value, (gint) priv->property_with_ctype);
break;
+ case PROP_ESCAPE_VEHICLE:
+ g_value_set_enum (value, priv->escape_vehicle);
+ break;
+
+ case PROP_DEFAULT_CREATE_FLAGS:
+ g_value_set_flags (value, priv->default_create_flags);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -174,7 +199,7 @@ test_tweak_impl_class_init (TestTweakImplClass *klass)
gobject_class->set_property = test_tweak_impl_set_property;
gobject_class->get_property = test_tweak_impl_get_property;
- g_assert (test_tweak_override_properties (gobject_class, PROP_FOO) == PROP_PROPERTY_WITH_CTYPE);
+ g_assert (test_tweak_override_properties (gobject_class, PROP_FOO) == PROP_DEFAULT_CREATE_FLAGS);
g_type_class_add_private (klass, sizeof (TestTweakImplPrivate));
}