Initial packaging for Tizen
[profile/ivi/gobject-introspection.git] / girepository / givfuncinfo.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * GObject introspection: Virtual Function implementation
3  *
4  * Copyright (C) 2005 Matthias Clasen
5  * Copyright (C) 2008,2009 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <string.h>
24
25 #include <glib.h>
26
27 #include <girepository.h>
28 #include "girepository-private.h"
29 #include "gitypelib-internal.h"
30
31 /**
32  * SECTION:givfuncinfo
33  * @Short_description: Struct representing a virtual function
34  * @Title: GIVFuncInfo
35  *
36  * GIVfuncInfo represents a virtual function. A property belongs to
37  * either a #GIObjectInfo or a #GIInterfaceInfo.
38  *
39  * <refsect1 id="gi-givfuncinfo.struct-hierarchy" role="struct_hierarchy">
40  * <title role="struct_hierarchy.title">Struct hierarchy</title>
41  * <synopsis>
42  *   <link linkend="gi-GIBaseInfo">GIBaseInfo</link>
43  *    +----<link linkend="gi-GICallableInfo">GICallableInfo</link>
44  *          +----<link linkend="gi-GIFunctionInfo">GIFunctionInfo</link>
45  *          +----<link linkend="gi-GISignalInfo">GISignalInfo</link>
46  *          +----GIVFuncInfo
47  * </synopsis>
48  * </refsect1>
49  */
50
51 GIVFuncInfo *
52 _g_base_info_find_vfunc (GIRealInfo   *rinfo,
53                          guint32       offset,
54                          gint          n_vfuncs,
55                          const gchar  *name)
56 {
57   /* FIXME hash */
58   Header *header = (Header *)rinfo->typelib->data;
59   gint i;
60
61   for (i = 0; i < n_vfuncs; i++)
62     {
63       VFuncBlob *fblob = (VFuncBlob *)&rinfo->typelib->data[offset];
64       const gchar *fname = (const gchar *)&rinfo->typelib->data[fblob->name];
65
66       if (strcmp (name, fname) == 0)
67         return (GIVFuncInfo *) g_info_new (GI_INFO_TYPE_VFUNC, (GIBaseInfo*) rinfo,
68                                            rinfo->typelib, offset);
69
70       offset += header->vfunc_blob_size;
71     }
72
73   return NULL;
74 }
75
76 /**
77  * g_vfunc_info_get_flags:
78  * @info: a #GIVFuncInfo
79  *
80  * Obtain the flags for this virtual function info. See #GIVFuncInfoFlags for
81  * more information about possible flag values.
82  *
83  * Returns: the flags
84  */
85 GIVFuncInfoFlags
86 g_vfunc_info_get_flags (GIVFuncInfo *info)
87 {
88   GIVFuncInfoFlags flags;
89   GIRealInfo *rinfo = (GIRealInfo *)info;
90   VFuncBlob *blob;
91
92   g_return_val_if_fail (info != NULL, 0);
93   g_return_val_if_fail (GI_IS_VFUNC_INFO (info), 0);
94
95   blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
96
97   flags = 0;
98
99   if (blob->must_chain_up)
100     flags = flags | GI_VFUNC_MUST_CHAIN_UP;
101
102   if (blob->must_be_implemented)
103     flags = flags | GI_VFUNC_MUST_OVERRIDE;
104
105   if (blob->must_not_be_implemented)
106     flags = flags | GI_VFUNC_MUST_NOT_OVERRIDE;
107
108   if (blob->throws)
109     flags = flags | GI_VFUNC_THROWS;
110
111   return flags;
112 }
113
114 /**
115  * g_vfunc_info_get_offset:
116  * @info: a #GIVFuncInfo
117  *
118  * Obtain the offset of the function pointer in the class struct. The value
119  * 0xFFFF indicates that the struct offset is unknown.
120  *
121  * Returns: the struct offset or 0xFFFF if it's unknown
122  */
123 gint
124 g_vfunc_info_get_offset (GIVFuncInfo *info)
125 {
126   GIRealInfo *rinfo = (GIRealInfo *)info;
127   VFuncBlob *blob;
128
129   g_return_val_if_fail (info != NULL, 0);
130   g_return_val_if_fail (GI_IS_VFUNC_INFO (info), 0);
131
132   blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
133
134   return blob->struct_offset;
135 }
136
137 /**
138  * g_vfunc_info_get_signal:
139  * @info: a #GIVFuncInfo
140  *
141  * Obtain the signal for the virtual function if one is set.
142  * The signal comes from the object or interface to which
143  * this virtual function belongs.
144  *
145  * Returns: (transfer full): the signal or %NULL if none set
146  */
147 GISignalInfo *
148 g_vfunc_info_get_signal (GIVFuncInfo *info)
149 {
150   GIRealInfo *rinfo = (GIRealInfo *)info;
151   VFuncBlob *blob;
152
153   g_return_val_if_fail (info != NULL, 0);
154   g_return_val_if_fail (GI_IS_VFUNC_INFO (info), 0);
155
156   blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
157
158   if (blob->class_closure)
159     return g_interface_info_get_signal ((GIInterfaceInfo *)rinfo->container, blob->signal);
160
161   return NULL;
162 }
163
164 /**
165  * g_vfunc_info_get_invoker:
166  * @info: a #GIVFuncInfo
167  *
168  * If this virtual function has an associated invoker method, this
169  * method will return it.  An invoker method is a C entry point.
170  *
171  * Not all virtuals will have invokers.
172  *
173  * Returns: (transfer full): the #GIVFuncInfo or %NULL. Free it with
174  * g_base_info_unref() when done.
175  */
176 GIFunctionInfo *
177 g_vfunc_info_get_invoker (GIVFuncInfo *info)
178 {
179   GIRealInfo *rinfo = (GIRealInfo *)info;
180   VFuncBlob *blob;
181   GIBaseInfo *container;
182   GIInfoType parent_type;
183
184   g_return_val_if_fail (info != NULL, 0);
185   g_return_val_if_fail (GI_IS_VFUNC_INFO (info), 0);
186
187   blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
188
189   /* 1023 = 0x3ff is the maximum of the 10 bits for invoker index */
190   if (blob->invoker == 1023)
191     return NULL;
192
193   container = rinfo->container;
194   parent_type = g_base_info_get_type (container);
195   if (parent_type == GI_INFO_TYPE_OBJECT)
196     return g_object_info_get_method ((GIObjectInfo*)container, blob->invoker);
197   else if (parent_type == GI_INFO_TYPE_INTERFACE)
198     return g_interface_info_get_method ((GIInterfaceInfo*)container, blob->invoker);
199   else
200     g_assert_not_reached ();
201 }
202
203 /**
204  * g_vfunc_info_get_address:
205  * @info: a #GIVFuncInfo
206  * @implementor_gtype: #GType implementing this virtual function
207  * @error: return location for a #GError
208  *
209  * This method will look up where inside the type struct of @implementor_gtype
210  * is the implementation for @info.
211  *
212  * Returns: address to a function or %NULL if an error happened
213  */
214 gpointer
215 g_vfunc_info_get_address (GIVFuncInfo      *vfunc_info,
216                           GType             implementor_gtype,
217                           GError          **error)
218 {
219   GIObjectInfo *object_info;
220   GIStructInfo *struct_info;
221   GIFieldInfo *field_info = NULL;
222   int length, i, offset;
223   gpointer implementor_vtable, func;
224
225   object_info = (GIObjectInfo *) g_base_info_get_container (vfunc_info);
226   struct_info = g_object_info_get_class_struct (object_info);
227
228   length = g_struct_info_get_n_fields (struct_info);
229   for (i = 0; i < length; i++)
230     {
231       field_info = g_struct_info_get_field (struct_info, i);
232
233       if (strcmp (g_base_info_get_name ( (GIBaseInfo*) field_info),
234                   g_base_info_get_name ( (GIBaseInfo*) vfunc_info)) != 0) {
235           g_base_info_unref (field_info);
236           field_info = NULL;
237           continue;
238       }
239
240       break;
241     }
242
243   if (field_info == NULL)
244     {
245       g_set_error (error,
246                    G_INVOKE_ERROR,
247                    G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
248                    "Couldn't find struct field for this vfunc");
249       return NULL;
250     }
251
252   implementor_vtable = g_type_class_ref (implementor_gtype);
253   offset = g_field_info_get_offset (field_info);
254   func = *(gpointer*) G_STRUCT_MEMBER_P (implementor_vtable, offset);
255   g_type_class_unref (implementor_vtable);
256
257   if (func == NULL)
258     {
259       g_set_error (error,
260                    G_INVOKE_ERROR,
261                    G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
262                    "Class %s doesn't implement %s",
263                    g_type_name (implementor_gtype),
264                    g_base_info_get_name ( (GIBaseInfo*) vfunc_info));
265       return NULL;
266     }
267
268   return func;
269 }
270
271 /**
272  * g_vfunc_info_invoke: (skip)
273  * @info: a #GIVFuncInfo describing the virtual function to invoke
274  * @implementor: #GType of the type that implements this virtual function
275  * @in_args: an array of #GIArgument<!-- -->s, one for each in
276  *    parameter of @info. If there are no in parameter, @in_args
277  *    can be %NULL
278  * @n_in_args: the length of the @in_args array
279  * @out_args: an array of #GIArgument<!-- -->s, one for each out
280  *    parameter of @info. If there are no out parameters, @out_args
281  *    may be %NULL
282  * @n_out_args: the length of the @out_args array
283  * @return_value: return location for the return value of the
284  *    function. If the function returns void, @return_value may be
285  *    %NULL
286  * @error: return location for detailed error information, or %NULL
287  *
288  * Invokes the function described in @info with the given
289  * arguments. Note that inout parameters must appear in both
290  * argument lists.
291  *
292  * Returns: %TRUE if the function has been invoked, %FALSE if an
293  *   error occurred.
294  */
295 gboolean
296 g_vfunc_info_invoke (GIVFuncInfo      *info,
297                      GType             implementor,
298                      const GIArgument *in_args,
299                      int               n_in_args,
300                      const GIArgument *out_args,
301                      int               n_out_args,
302                      GIArgument       *return_value,
303                      GError          **error)
304 {
305   gpointer func;
306
307   func = g_vfunc_info_get_address (info, implementor, error);
308   if (*error != NULL)
309     return FALSE;
310
311   return g_callable_info_invoke ((GICallableInfo*) info,
312                                  func,
313                                  in_args,
314                                  n_in_args,
315                                  out_args,
316                                  n_out_args,
317                                  return_value,
318                                  TRUE,
319                                  FALSE,
320                                  error);
321 }