summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Feltman <sfeltman@src.gnome.org>2014-02-27 02:05:54 -0800
committerSimon Feltman <sfeltman@src.gnome.org>2014-02-27 13:51:18 -0800
commit7027bb256d0d1ab5dd58b6d7fb02ff2f547ae4c2 (patch)
treee145d73c84392eb5f3b8c72c46a377f027d29a8c
parent93a63a77cfda14f7bd69aef88d6a2502903d62f0 (diff)
downloadgobject-introspection-7027bb256d0d1ab5dd58b6d7fb02ff2f547ae4c2.tar.gz
g-ir-compiler: Add support for callback fields on GObjects
Use ParseState enum instead of a boolean for the ParseContexts embedded_type flag. This allows specific tracking of the embedded type currently being parsed which can now either be STATE_STRUCT_FIELD or STATE_CLASS_FIELD (or allow for future expansion). Add ParseState::STATE_NONE as the default for this field. Fix GObject FieldBlob validation to take into account the sizeof CallbackBlobs (copied from the struct validator). Add static g_object_info_get_field_offset which parallels g_struct_info_get_field_offset which is needed since callback fields may vary in size. https://bugzilla.gnome.org/show_bug.cgi?id=725198
-rw-r--r--girepository/giobjectinfo.c71
-rw-r--r--girepository/girparser.c41
-rw-r--r--girepository/gitypelib.c9
-rw-r--r--tests/scanner/Regress-1.0-C-expected/Regress.TestObj-function_ptr.page14
-rw-r--r--tests/scanner/Regress-1.0-C-expected/Regress.TestObj.function_ptr.page24
-rw-r--r--tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.function_ptr.page19
-rw-r--r--tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.function_ptr.page21
-rw-r--r--tests/scanner/Regress-1.0-expected.gir7
-rw-r--r--tests/scanner/regress.h3
9 files changed, 159 insertions, 50 deletions
diff --git a/girepository/giobjectinfo.c b/girepository/giobjectinfo.c
index 3e3b312c..d92a8615 100644
--- a/girepository/giobjectinfo.c
+++ b/girepository/giobjectinfo.c
@@ -48,6 +48,40 @@
*/
/**
+ * g_object_info_get_field_offset:
+ * @info: a #GIObjectInfo
+ * @n: index of queried field
+ *
+ * Obtain the offset of the specified field.
+ *
+ * Returns: field offset in bytes
+ */
+static gint32
+g_object_info_get_field_offset (GIObjectInfo *info,
+ gint n)
+{
+ GIRealInfo *rinfo = (GIRealInfo *)info;
+ Header *header = (Header *)rinfo->typelib->data;
+ ObjectBlob *blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
+ guint32 offset;
+ gint i;
+ FieldBlob *field_blob;
+
+ offset = rinfo->offset + header->object_blob_size
+ + (blob->n_interfaces + blob->n_interfaces % 2) * 2;
+
+ for (i = 0; i < n; i++)
+ {
+ field_blob = (FieldBlob *)&rinfo->typelib->data[offset];
+ offset += header->field_blob_size;
+ if (field_blob->has_embedded_type)
+ offset += header->callback_blob_size;
+ }
+
+ return offset;
+}
+
+/**
* g_object_info_get_parent:
* @info: a #GIObjectInfo
*
@@ -251,18 +285,11 @@ g_object_info_get_field (GIObjectInfo *info,
{
gint offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
- Header *header;
- ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
- header = (Header *)rinfo->typelib->data;
- blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
-
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + n * header->field_blob_size;
+ offset = g_object_info_get_field_offset(info, n);
return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib, offset);
}
@@ -313,9 +340,7 @@ g_object_info_get_property (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ n * header->property_blob_size;
return (GIPropertyInfo *) g_info_new (GI_INFO_TYPE_PROPERTY, (GIBaseInfo*)info,
@@ -370,9 +395,7 @@ g_object_info_get_method (GIObjectInfo *info,
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ n * header->function_blob_size;
@@ -406,9 +429,7 @@ g_object_info_find_method (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size +
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size;
return _g_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name);
@@ -518,9 +539,7 @@ g_object_info_get_signal (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ n * header->signal_blob_size;
@@ -609,9 +628,7 @@ g_object_info_get_vfunc (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size
@@ -652,9 +669,7 @@ g_object_info_find_vfunc (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size;
@@ -769,9 +784,7 @@ g_object_info_get_constant (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
- offset = rinfo->offset + header->object_blob_size
- + (blob->n_interfaces + blob->n_interfaces % 2) * 2
- + blob->n_fields * header->field_blob_size
+ offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 82005fc0..c7feb6ad 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -62,37 +62,38 @@ struct _GIrParser
typedef enum
{
+ STATE_NONE = 0,
STATE_START,
STATE_END,
STATE_REPOSITORY,
STATE_INCLUDE,
- STATE_C_INCLUDE,
- STATE_PACKAGE, /* 5 */
+ STATE_C_INCLUDE, /* 5 */
+ STATE_PACKAGE,
STATE_NAMESPACE,
STATE_ENUM,
STATE_BITFIELD,
- STATE_FUNCTION,
- STATE_FUNCTION_RETURN, /* 10 */
+ STATE_FUNCTION, /* 10 */
+ STATE_FUNCTION_RETURN,
STATE_FUNCTION_PARAMETERS,
STATE_FUNCTION_PARAMETER,
STATE_CLASS,
- STATE_CLASS_FIELD,
- STATE_CLASS_PROPERTY, /* 15 */
+ STATE_CLASS_FIELD, /* 15 */
+ STATE_CLASS_PROPERTY,
STATE_INTERFACE,
STATE_INTERFACE_PROPERTY,
STATE_INTERFACE_FIELD,
- STATE_IMPLEMENTS,
- STATE_PREREQUISITE, /* 20 */
+ STATE_IMPLEMENTS, /* 20 */
+ STATE_PREREQUISITE,
STATE_BOXED,
STATE_BOXED_FIELD,
STATE_STRUCT,
- STATE_STRUCT_FIELD,
- STATE_UNION, /* 25 */
+ STATE_STRUCT_FIELD, /* 25 */
+ STATE_UNION,
STATE_UNION_FIELD,
STATE_NAMESPACE_CONSTANT,
STATE_CLASS_CONSTANT,
- STATE_INTERFACE_CONSTANT,
- STATE_ALIAS, /* 30 */
+ STATE_INTERFACE_CONSTANT, /* 30 */
+ STATE_ALIAS,
STATE_TYPE,
STATE_ATTRIBUTE,
STATE_PASSTHROUGH
@@ -123,7 +124,7 @@ struct _ParseContext
GList *type_stack;
GList *type_parameters;
int type_depth;
- gboolean in_embedded_type;
+ ParseState in_embedded_state;
};
#define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
@@ -807,7 +808,7 @@ start_function (GMarkupParseContext *context,
const gchar *throws;
GIrNodeFunction *function;
gboolean found = FALSE;
- gboolean in_embedded_type;
+ ParseState in_embedded_state = STATE_NONE;
switch (ctx->state)
{
@@ -830,8 +831,10 @@ start_function (GMarkupParseContext *context,
case STATE_ENUM:
found = strcmp (element_name, "function") == 0;
break;
+ case STATE_CLASS_FIELD:
case STATE_STRUCT_FIELD:
found = (found || strcmp (element_name, "callback") == 0);
+ in_embedded_state = ctx->state;
break;
default:
break;
@@ -840,12 +843,10 @@ start_function (GMarkupParseContext *context,
if (!found)
return FALSE;
- in_embedded_type = ctx->state == STATE_STRUCT_FIELD;
-
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
return TRUE;
- ctx->in_embedded_type = in_embedded_type;
+ ctx->in_embedded_state = in_embedded_state;
name = find_attribute ("name", attribute_names, attribute_values);
shadows = find_attribute ("shadows", attribute_names, attribute_values);
@@ -3210,10 +3211,10 @@ end_element_handler (GMarkupParseContext *context,
else
{
g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
- if (ctx->in_embedded_type)
+ if (ctx->in_embedded_state != STATE_NONE)
{
- ctx->in_embedded_type = FALSE;
- state_switch (ctx, STATE_STRUCT_FIELD);
+ state_switch (ctx, ctx->in_embedded_state);
+ ctx->in_embedded_state = STATE_NONE;
}
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
state_switch (ctx, STATE_INTERFACE);
diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c
index 8883496e..41b54fd8 100644
--- a/girepository/gitypelib.c
+++ b/girepository/gitypelib.c
@@ -1773,10 +1773,17 @@ validate_object_blob (ValidateContext *ctx,
push_context (ctx, get_string_nofail (typelib, blob->name));
- for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
+ for (i = 0; i < blob->n_fields; i++)
{
+ FieldBlob *blob = (FieldBlob*) &typelib->data[offset2];
+
if (!validate_field_blob (ctx, offset2, error))
return FALSE;
+
+ offset2 += sizeof (FieldBlob);
+ /* Special case fields which are callbacks. */
+ if (blob->has_embedded_type)
+ offset2 += sizeof (CallbackBlob);
}
for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-function_ptr.page b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-function_ptr.page
new file mode 100644
index 00000000..dca9a51f
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj-function_ptr.page
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj-function_ptr"
+ type="topic"
+ style="field"
+ xmlns="http://projectmallard.org/1.0/"
+ xmlns:api="http://projectmallard.org/experimental/api/"
+ xmlns:ui="http://projectmallard.org/1.0/ui/">
+ <info>
+ <link xref="Regress.TestObj" group="field" type="guide"/>
+ </info>
+ <title>Regress.TestObj->function_ptr</title>
+
+
+</page>
diff --git a/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.function_ptr.page b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.function_ptr.page
new file mode 100644
index 00000000..34565407
--- /dev/null
+++ b/tests/scanner/Regress-1.0-C-expected/Regress.TestObj.function_ptr.page
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj.function_ptr"
+ type="topic"
+ style="callback"
+ xmlns="http://projectmallard.org/1.0/"
+ xmlns:api="http://projectmallard.org/experimental/api/"
+ xmlns:ui="http://projectmallard.org/1.0/ui/">
+ <info>
+ <link xref="index" group="callback" type="guide"/>
+ </info>
+ <title>Regress.TestObj.function_ptr</title>
+ <synopsis><code mime="text/x-csrc">
+void function_ptr (void);
+ </code></synopsis>
+
+
+<terms>
+<item>
+<title><code>Returns</code></title>
+
+</item>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.function_ptr.page b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.function_ptr.page
new file mode 100644
index 00000000..d9f3754c
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Gjs-expected/Regress.TestObj.function_ptr.page
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj.function_ptr"
+ type="topic"
+ style="callback"
+ xmlns="http://projectmallard.org/1.0/"
+ xmlns:api="http://projectmallard.org/experimental/api/"
+ xmlns:ui="http://projectmallard.org/1.0/ui/">
+ <info>
+ <link xref="index" group="callback" type="guide"/>
+ </info>
+ <title>Regress.TestObj.function_ptr</title>
+ <synopsis><code mime="text/x-gjs">
+function onfunction_ptr(): void {
+}
+ </code></synopsis>
+
+
+
+</page>
diff --git a/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.function_ptr.page b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.function_ptr.page
new file mode 100644
index 00000000..caa0c191
--- /dev/null
+++ b/tests/scanner/Regress-1.0-Python-expected/Regress.TestObj.function_ptr.page
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<page id="Regress.TestObj.function_ptr"
+ type="topic"
+ style="callback"
+ xmlns="http://projectmallard.org/1.0/"
+ xmlns:api="http://projectmallard.org/experimental/api/"
+ xmlns:ui="http://projectmallard.org/1.0/ui/">
+ <info>
+ <link xref="index" group="callback" type="guide"/>
+ </info>
+ <title>Regress.TestObj.function_ptr</title>
+ <synopsis><code mime="text/x-python">
+@returns(none)
+def on_function_ptr():
+ </code></synopsis>
+
+
+<terms>
+</terms>
+
+</page>
diff --git a/tests/scanner/Regress-1.0-expected.gir b/tests/scanner/Regress-1.0-expected.gir
index d25e41c8..82c11d32 100644
--- a/tests/scanner/Regress-1.0-expected.gir
+++ b/tests/scanner/Regress-1.0-expected.gir
@@ -3450,6 +3450,13 @@ raise an error.</doc>
<field name="gtype">
<type name="GType" c:type="GType"/>
</field>
+ <field name="function_ptr">
+ <callback name="function_ptr">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ </callback>
+ </field>
<glib:signal name="all"
when="first"
no-recurse="1"
diff --git a/tests/scanner/regress.h b/tests/scanner/regress.h
index ad2cb1fb..004ae36e 100644
--- a/tests/scanner/regress.h
+++ b/tests/scanner/regress.h
@@ -488,6 +488,9 @@ struct _RegressTestObj
double some_double;
char* string;
GType gtype;
+
+ /* < private > */
+ void (*function_ptr)();
};
typedef void (*RegressTestExternallyDefinedCallback) (RegressTestObj *obj, int someint);