diff options
Diffstat (limited to 'girepository')
-rw-r--r-- | girepository/ginfo.c | 116 | ||||
-rw-r--r-- | girepository/girepository.h | 5 | ||||
-rw-r--r-- | girepository/girnode.c | 37 | ||||
-rw-r--r-- | girepository/girnode.h | 2 | ||||
-rw-r--r-- | girepository/girparser.c | 6 | ||||
-rw-r--r-- | girepository/gtypelib.h | 8 |
6 files changed, 170 insertions, 4 deletions
diff --git a/girepository/ginfo.c b/girepository/ginfo.c index fcc5f09..d522a56 100644 --- a/girepository/ginfo.c +++ b/girepository/ginfo.c @@ -1527,6 +1527,63 @@ g_object_info_get_vfunc (GIObjectInfo *info, base->typelib, offset); } +static GIVFuncInfo * +find_vfunc (GIBaseInfo *base, + guint32 offset, + gint n_vfuncs, + const gchar *name) +{ + /* FIXME hash */ + Header *header = (Header *)base->typelib->data; + gint i; + + for (i = 0; i < n_vfuncs; i++) + { + VFuncBlob *fblob = (VFuncBlob *)&base->typelib->data[offset]; + const gchar *fname = (const gchar *)&base->typelib->data[fblob->name]; + + if (strcmp (name, fname) == 0) + return (GIVFuncInfo *) g_info_new (GI_INFO_TYPE_VFUNC, base, + base->typelib, offset); + + offset += header->vfunc_blob_size; + } + + return NULL; +} + +/** + * g_object_info_find_vfunc: + * @info: An #GIObjectInfo + * @name: The name of a virtual function to find. + * + * Locate a virtual function slot with name @name. Note that the namespace + * for virtuals is distinct from that of methods; there may or may not be + * a concrete method associated for a virtual. If there is one, it may + * be retrieved using #g_vfunc_info_get_invoker. See the documentation for + * that function for more information on invoking virtuals. + * + * Return value: (transfer full): A #GIVFuncInfo, or %NULL if none with name @name. + */ +GIVFuncInfo * +g_object_info_find_vfunc (GIObjectInfo *info, + const gchar *name) +{ + gint offset; + GIBaseInfo *base = (GIBaseInfo *)info; + Header *header = (Header *)base->typelib->data; + ObjectBlob *blob = (ObjectBlob *)&base->typelib->data[base->offset]; + + offset = base->offset + header->object_blob_size + + (blob->n_interfaces + blob->n_interfaces % 2) * 2 + + blob->n_fields * header->field_blob_size + + blob->n_properties * header->property_blob_size + + blob->n_methods * header->function_blob_size + + blob->n_signals * header->signal_blob_size; + + return find_vfunc (base, offset, blob->n_vfuncs, name); +} + gint g_object_info_get_n_constants (GIObjectInfo *info) { @@ -1728,6 +1785,34 @@ g_interface_info_get_vfunc (GIInterfaceInfo *info, base->typelib, offset); } +/** + * g_interface_info_find_vfunc: + * @info: An #GIObjectInfo + * @name: The name of a virtual function to find. + * + * Locate a virtual function slot with name @name. See the documentation + * for #g_object_info_find_vfunc for more information on virtuals. + * + * Return value: (transfer full): A #GIVFuncInfo, or %NULL if none with name @name. + */ +GIVFuncInfo * +g_interface_info_find_vfunc (GIInterfaceInfo *info, + const gchar *name) +{ + gint offset; + GIBaseInfo *base = (GIBaseInfo *)info; + Header *header = (Header *)base->typelib->data; + InterfaceBlob *blob = (InterfaceBlob *)&base->typelib->data[base->offset]; + + offset = base->offset + header->interface_blob_size + + (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 + + blob->n_properties * header->property_blob_size + + blob->n_methods * header->function_blob_size + + blob->n_signals * header->signal_blob_size; + + return find_vfunc (base, offset, blob->n_vfuncs, name); +} + gint g_interface_info_get_n_constants (GIInterfaceInfo *info) { @@ -1913,6 +1998,37 @@ g_vfunc_info_get_signal (GIVFuncInfo *info) return NULL; } +/** + * g_vfunc_info_get_invoker: + * @info: A #GIVFuncInfo + * + * If this virtual function has an associated invoker method, this + * method will return it. An invoker method is a C entry point. + * + * Not all virtuals will have invokers. + * + * Return value: (transfer full): An invoker function, or %NULL if none known + */ +GIFunctionInfo * +g_vfunc_info_get_invoker (GIVFuncInfo *info) +{ + GIBaseInfo *base = (GIBaseInfo *)info; + VFuncBlob *blob = (VFuncBlob *)&base->typelib->data[base->offset]; + GIBaseInfo *container = base->container; + GIInfoType parent_type; + + /* 1023 = 0x3ff is the maximum of the 10 bits for invoker index */ + if (blob->invoker == 1023) + return NULL; + + parent_type = g_base_info_get_type (container); + if (parent_type == GI_INFO_TYPE_OBJECT) + return g_object_info_get_method ((GIObjectInfo*)container, blob->invoker); + else if (parent_type == GI_INFO_TYPE_INTERFACE) + return g_interface_info_get_method ((GIInterfaceInfo*)container, blob->invoker); + else + g_assert_not_reached (); +} /* GIConstantInfo functions */ GITypeInfo * diff --git a/girepository/girepository.h b/girepository/girepository.h index 4059adc..1058570 100644 --- a/girepository/girepository.h +++ b/girepository/girepository.h @@ -470,6 +470,8 @@ GISignalInfo * g_object_info_get_signal (GIObjectInfo *in gint g_object_info_get_n_vfuncs (GIObjectInfo *info); GIVFuncInfo * g_object_info_get_vfunc (GIObjectInfo *info, gint n); +GIVFuncInfo * g_object_info_find_vfunc (GIObjectInfo *info, + const gchar *name); gint g_object_info_get_n_constants (GIObjectInfo *info); GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info, gint n); @@ -495,6 +497,8 @@ GISignalInfo * g_interface_info_get_signal (GIInterfaceInfo *in gint g_interface_info_get_n_vfuncs (GIInterfaceInfo *info); GIVFuncInfo * g_interface_info_get_vfunc (GIInterfaceInfo *info, gint n); +GIVFuncInfo * g_interface_info_find_vfunc (GIInterfaceInfo *info, + const gchar *name); gint g_interface_info_get_n_constants (GIInterfaceInfo *info); GIConstantInfo * g_interface_info_get_constant (GIInterfaceInfo *info, gint n); @@ -527,6 +531,7 @@ typedef enum GIVFuncInfoFlags g_vfunc_info_get_flags (GIVFuncInfo *info); gint g_vfunc_info_get_offset (GIVFuncInfo *info); GISignalInfo * g_vfunc_info_get_signal (GIVFuncInfo *info); +GIFunctionInfo * g_vfunc_info_get_invoker (GIVFuncInfo *info); /* GIConstantInfo */ diff --git a/girepository/girnode.c b/girepository/girnode.c index 22c0aee..01e83ac 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -265,6 +265,7 @@ g_ir_node_free (GIrNode *node) GIrNodeVFunc *vfunc = (GIrNodeVFunc *)node; g_free (node->name); + g_free (vfunc->invoker); for (l = vfunc->parameters; l; l = l->next) g_ir_node_free ((GIrNode *)l->data); g_list_free (vfunc->parameters); @@ -1186,6 +1187,30 @@ g_ir_find_node (GIrModule *module, return node != NULL; } +static int +get_index_of_member_type (GIrNodeInterface *node, + GIrNodeTypeId type, + const char *name) +{ + guint index = -1; + GList *l; + + for (l = node->members; l; l = l->next) + { + GIrNode *node = l->data; + + if (node->type != type) + continue; + + index++; + + if (strcmp (node->name, name) == 0) + break; + } + + return index; +} + static void serialize_type (GIrModule *module, GList *modules, @@ -1759,6 +1784,18 @@ g_ir_node_build_typelib (GIrNode *node, blob->class_closure = 0; /* FIXME */ blob->reserved = 0; + if (vfunc->invoker) + { + int index = get_index_of_member_type ((GIrNodeInterface*)parent, G_IR_NODE_FUNCTION, vfunc->invoker); + if (index == -1) + { + g_error ("Unknown member function %s for vfunc %s", vfunc->invoker, node->name); + } + blob->invoker = (guint) index; + } + else + blob->invoker = 0x3ff; /* max of 10 bits */ + blob->struct_offset = vfunc->offset; blob->reserved2 = 0; blob->signature = signature; diff --git a/girepository/girnode.h b/girepository/girnode.h index 2a1f6b2..238593a 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -214,6 +214,8 @@ struct _GIrNodeVFunc gboolean must_not_be_implemented; gboolean is_class_closure; + char *invoker; + GList *parameters; GIrNodeParam *result; diff --git a/girepository/girparser.c b/girepository/girparser.c index 006ed3b..9afd858 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -2080,7 +2080,7 @@ start_vfunc (GMarkupParseContext *context, ParseContext *ctx, GError **error) { - if (strcmp (element_name, "vfunc") == 0 && + if (strcmp (element_name, "virtual-method") == 0 && (ctx->state == STATE_CLASS || ctx->state == STATE_INTERFACE)) { @@ -2089,12 +2089,14 @@ start_vfunc (GMarkupParseContext *context, const gchar *override; const gchar *is_class_closure; const gchar *offset; + const gchar *invoker; name = find_attribute ("name", attribute_names, attribute_values); must_chain_up = find_attribute ("must-chain-up", attribute_names, attribute_values); override = find_attribute ("override", attribute_names, attribute_values); is_class_closure = find_attribute ("is-class-closure", attribute_names, attribute_values); offset = find_attribute ("offset", attribute_names, attribute_values); + invoker = find_attribute ("invoker", attribute_names, attribute_values); if (name == NULL) MISSING_ATTRIBUTE (context, error, element_name, "name"); @@ -2138,6 +2140,8 @@ start_vfunc (GMarkupParseContext *context, else vfunc->offset = 0; + vfunc->invoker = g_strdup (invoker); + iface = (GIrNodeInterface *)CURRENT_NODE (ctx); iface->members = g_list_append (iface->members, vfunc); diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h index db5fe11..f6ad8c9 100644 --- a/girepository/gtypelib.h +++ b/girepository/gtypelib.h @@ -843,9 +843,10 @@ typedef struct { * @class_closure: Set if this virtual function is the class closure of a signal. * @signal: The index of the signal in the list of signals of the object or * interface to which this virtual function belongs. - * @struct_offset: - * The offset of the function pointer in the class struct. The value + * @struct_offset: The offset of the function pointer in the class struct. The value * 0xFFFF indicates that the struct offset is unknown. + * @invoker: If a method invoker for this virtual exists, this is the offset in the + * class structure of the method. If no method is known, this value will be 0x3ff. * @signature: * Offset of the SignatureBlob describing the parameter types and the * return value type. @@ -861,7 +862,8 @@ typedef struct { guint16 signal; guint16 struct_offset; - guint16 reserved2; + guint16 invoker : 10; /* Number of bits matches @index in FunctionBlob */ + guint16 reserved2 : 6; guint32 reserved3; guint32 signature; |