1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Interface implementation
3 *
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008,2009 Red Hat, Inc.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 */
24
25 #include "config.h"
26
27 #include <glib.h>
28
29 #include <girepository/girepository.h>
30 #include "gibaseinfo-private.h"
31 #include "girepository-private.h"
32 #include "gitypelib-internal.h"
33 #include "giinterfaceinfo.h"
34
35 /**
36 * GIInterfaceInfo:
37 *
38 * `GIInterfaceInfo` represents a `GInterface` type.
39 *
40 * A `GInterface` has methods, fields, properties, signals,
41 * interfaces, constants, virtual functions and prerequisites.
42 *
43 * Since: 2.80
44 */
45
46 /**
47 * gi_interface_info_get_n_prerequisites:
48 * @info: a #GIInterfaceInfo
49 *
50 * Obtain the number of prerequisites for this interface type.
51 *
52 * A prerequisite is another interface that needs to be implemented for
53 * interface, similar to a base class for [class@GObject.Object]s.
54 *
55 * Returns: number of prerequisites
56 * Since: 2.80
57 */
58 guint
59 gi_interface_info_get_n_prerequisites (GIInterfaceInfo *info)
60 {
61 GIRealInfo *rinfo = (GIRealInfo *)info;
62 InterfaceBlob *blob;
63
64 g_return_val_if_fail (info != NULL, 0);
65 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
66
67 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
68
69 return blob->n_prerequisites;
70 }
71
72 /**
73 * gi_interface_info_get_prerequisite:
74 * @info: a #GIInterfaceInfo
75 * @n: index of prerequisite to get
76 *
77 * Obtain an interface type’s prerequisite at index @n.
78 *
79 * Returns: (transfer full): The prerequisite as a [class@GIRepository.BaseInfo].
80 * Free the struct by calling [method@GIRepository.BaseInfo.unref] when done.
81 * Since: 2.80
82 */
83 GIBaseInfo *
84 gi_interface_info_get_prerequisite (GIInterfaceInfo *info,
85 guint n)
86 {
87 GIRealInfo *rinfo = (GIRealInfo *)info;
88 InterfaceBlob *blob;
89
90 g_return_val_if_fail (info != NULL, NULL);
91 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
92
93 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
94
95 return gi_info_from_entry (rinfo->repository,
96 rinfo->typelib, blob->prerequisites[n]);
97 }
98
99
100 /**
101 * gi_interface_info_get_n_properties:
102 * @info: a #GIInterfaceInfo
103 *
104 * Obtain the number of properties that this interface type has.
105 *
106 * Returns: number of properties
107 * Since: 2.80
108 */
109 guint
110 gi_interface_info_get_n_properties (GIInterfaceInfo *info)
111 {
112 GIRealInfo *rinfo = (GIRealInfo *)info;
113 InterfaceBlob *blob;
114
115 g_return_val_if_fail (info != NULL, 0);
116 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
117
118 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
119
120 return blob->n_properties;
121 }
122
123 /**
124 * gi_interface_info_get_property:
125 * @info: a #GIInterfaceInfo
126 * @n: index of property to get
127 *
128 * Obtain an interface type property at index @n.
129 *
130 * Returns: (transfer full): The [class@GIRepository.PropertyInfo]. Free the
131 * struct by calling [method@GIRepository.BaseInfo.unref] when done.
132 * Since: 2.80
133 */
134 GIPropertyInfo *
135 gi_interface_info_get_property (GIInterfaceInfo *info,
136 guint n)
137 {
138 gint offset;
139 GIRealInfo *rinfo = (GIRealInfo *)info;
140 Header *header;
141 InterfaceBlob *blob;
142
143 g_return_val_if_fail (info != NULL, NULL);
144 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
145
146 header = (Header *)rinfo->typelib->data;
147 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
148
149 offset = rinfo->offset + header->interface_blob_size
150 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
151 + n * header->property_blob_size;
152
153 return (GIPropertyInfo *) gi_info_new (GI_INFO_TYPE_PROPERTY, (GIBaseInfo*)info,
154 rinfo->typelib, offset);
155 }
156
157 /**
158 * gi_interface_info_get_n_methods:
159 * @info: a #GIInterfaceInfo
160 *
161 * Obtain the number of methods that this interface type has.
162 *
163 * Returns: number of methods
164 * Since: 2.80
165 */
166 guint
167 gi_interface_info_get_n_methods (GIInterfaceInfo *info)
168 {
169 GIRealInfo *rinfo = (GIRealInfo *)info;
170 InterfaceBlob *blob;
171
172 g_return_val_if_fail (info != NULL, 0);
173 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
174
175 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
176
177 return blob->n_methods;
178 }
179
180 /**
181 * gi_interface_info_get_method:
182 * @info: a #GIInterfaceInfo
183 * @n: index of method to get
184 *
185 * Obtain an interface type method at index @n.
186 *
187 * Returns: (transfer full): The [class@GIRepository.FunctionInfo]. Free the
188 * struct by calling [method@GIRepository.BaseInfo.unref] when done.
189 * Since: 2.80
190 */
191 GIFunctionInfo *
192 gi_interface_info_get_method (GIInterfaceInfo *info,
193 guint n)
194 {
195 gint offset;
196 GIRealInfo *rinfo = (GIRealInfo *)info;
197 Header *header;
198 InterfaceBlob *blob;
199
200 g_return_val_if_fail (info != NULL, NULL);
201 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
202
203 header = (Header *)rinfo->typelib->data;
204 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
205
206 offset = rinfo->offset + header->interface_blob_size
207 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
208 + blob->n_properties * header->property_blob_size
209 + n * header->function_blob_size;
210
211 return (GIFunctionInfo *) gi_info_new (GI_INFO_TYPE_FUNCTION, (GIBaseInfo*)info,
212 rinfo->typelib, offset);
213 }
214
215 /**
216 * gi_interface_info_find_method:
217 * @info: a #GIInterfaceInfo
218 * @name: name of method to obtain
219 *
220 * Obtain a method of the interface type given a @name.
221 *
222 * `NULL` will be returned if there’s no method available with that name.
223 *
224 * Returns: (transfer full) (nullable): The [class@GIRepository.FunctionInfo] or
225 * `NULL` if none found. Free the struct by calling
226 * [method@GIRepository.BaseInfo.unref] when done.
227 * Since: 2.80
228 */
229 GIFunctionInfo *
230 gi_interface_info_find_method (GIInterfaceInfo *info,
231 const gchar *name)
232 {
233 gint offset;
234 GIRealInfo *rinfo = (GIRealInfo *)info;
235 Header *header = (Header *)rinfo->typelib->data;
236 InterfaceBlob *blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
237
238 offset = rinfo->offset + header->interface_blob_size
239 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
240 + blob->n_properties * header->property_blob_size;
241
242 return gi_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name);
243 }
244
245 /**
246 * gi_interface_info_get_n_signals:
247 * @info: a #GIInterfaceInfo
248 *
249 * Obtain the number of signals that this interface type has.
250 *
251 * Returns: number of signals
252 * Since: 2.80
253 */
254 guint
255 gi_interface_info_get_n_signals (GIInterfaceInfo *info)
256 {
257 GIRealInfo *rinfo = (GIRealInfo *)info;
258 InterfaceBlob *blob;
259
260 g_return_val_if_fail (info != NULL, 0);
261 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
262
263 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
264
265 return blob->n_signals;
266 }
267
268 /**
269 * gi_interface_info_get_signal:
270 * @info: a #GIInterfaceInfo
271 * @n: index of signal to get
272 *
273 * Obtain an interface type signal at index @n.
274 *
275 * Returns: (transfer full): The [class@GIRepository.SignalInfo]. Free the
276 * struct by calling [method@GIRepository.BaseInfo.unref] when done.
277 * Since: 2.80
278 */
279 GISignalInfo *
280 gi_interface_info_get_signal (GIInterfaceInfo *info,
281 guint n)
282 {
283 gint offset;
284 GIRealInfo *rinfo = (GIRealInfo *)info;
285 Header *header;
286 InterfaceBlob *blob;
287
288 g_return_val_if_fail (info != NULL, NULL);
289 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
290
291 header = (Header *)rinfo->typelib->data;
292 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
293
294 offset = rinfo->offset + header->interface_blob_size
295 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
296 + blob->n_properties * header->property_blob_size
297 + blob->n_methods * header->function_blob_size
298 + n * header->signal_blob_size;
299
300 return (GISignalInfo *) gi_info_new (GI_INFO_TYPE_SIGNAL, (GIBaseInfo*)info,
301 rinfo->typelib, offset);
302 }
303
304 /**
305 * gi_interface_info_find_signal:
306 * @info: a #GIInterfaceInfo
307 * @name: name of signal to find
308 *
309 * Obtain a signal of the interface type given a @name.
310 *
311 * `NULL` will be returned if there’s no signal available with that name.
312 *
313 * Returns: (transfer full) (nullable): The [class@GIRepository.SignalInfo] or
314 * `NULL` if none found. Free the struct by calling
315 * [method@GIRepository.BaseInfo.unref] when done.
316 * Since: 2.80
317 */
318 GISignalInfo *
319 gi_interface_info_find_signal (GIInterfaceInfo *info,
320 const gchar *name)
321 {
322 guint n_signals;
323
324 n_signals = gi_interface_info_get_n_signals (info);
325 for (guint i = 0; i < n_signals; i++)
326 {
327 GISignalInfo *siginfo = gi_interface_info_get_signal (info, i);
328
329 if (g_strcmp0 (gi_base_info_get_name ((GIBaseInfo *) siginfo), name) != 0)
330 {
331 gi_base_info_unref ((GIBaseInfo*)siginfo);
332 continue;
333 }
334
335 return siginfo;
336 }
337 return NULL;
338 }
339
340 /**
341 * gi_interface_info_get_n_vfuncs:
342 * @info: a #GIInterfaceInfo
343 *
344 * Obtain the number of virtual functions that this interface type has.
345 *
346 * Returns: number of virtual functions
347 * Since: 2.80
348 */
349 guint
350 gi_interface_info_get_n_vfuncs (GIInterfaceInfo *info)
351 {
352 GIRealInfo *rinfo = (GIRealInfo *)info;
353 InterfaceBlob *blob;
354
355 g_return_val_if_fail (info != NULL, 0);
356 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
357
358 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
359
360 return blob->n_vfuncs;
361 }
362
363 /**
364 * gi_interface_info_get_vfunc:
365 * @info: a #GIInterfaceInfo
366 * @n: index of virtual function to get
367 *
368 * Obtain an interface type virtual function at index @n.
369 *
370 * Returns: (transfer full): the [class@GIRepository.VFuncInfo]. Free the struct
371 * by calling [method@GIRepository.BaseInfo.unref] when done.
372 * Since: 2.80
373 */
374 GIVFuncInfo *
375 gi_interface_info_get_vfunc (GIInterfaceInfo *info,
376 guint n)
377 {
378 gint offset;
379 GIRealInfo *rinfo = (GIRealInfo *)info;
380 Header *header;
381 InterfaceBlob *blob;
382
383 g_return_val_if_fail (info != NULL, NULL);
384 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
385
386 header = (Header *)rinfo->typelib->data;
387 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
388
389 offset = rinfo->offset + header->interface_blob_size
390 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
391 + blob->n_properties * header->property_blob_size
392 + blob->n_methods * header->function_blob_size
393 + blob->n_signals * header->signal_blob_size
394 + n * header->vfunc_blob_size;
395
396 return (GIVFuncInfo *) gi_info_new (GI_INFO_TYPE_VFUNC, (GIBaseInfo*)info,
397 rinfo->typelib, offset);
398 }
399
400 /**
401 * gi_interface_info_find_vfunc:
402 * @info: a #GIInterfaceInfo
403 * @name: The name of a virtual function to find.
404 *
405 * Locate a virtual function slot with name @name.
406 *
407 * See the documentation for [method@GIRepository.ObjectInfo.find_vfunc] for
408 * more information on virtuals.
409 *
410 * Returns: (transfer full) (nullable): The [class@GIRepository.VFuncInfo], or
411 * `NULL` if none found. Free it with [method@GIRepository.BaseInfo.unref]
412 * when done.
413 * Since: 2.80
414 */
415 GIVFuncInfo *
416 gi_interface_info_find_vfunc (GIInterfaceInfo *info,
417 const gchar *name)
418 {
419 gint offset;
420 GIRealInfo *rinfo = (GIRealInfo *)info;
421 Header *header;
422 InterfaceBlob *blob;
423
424 g_return_val_if_fail (info != NULL, NULL);
425 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
426
427 header = (Header *)rinfo->typelib->data;
428 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
429
430 offset = rinfo->offset + header->interface_blob_size
431 + (blob->n_prerequisites + blob->n_prerequisites % 2) * 2
432 + blob->n_properties * header->property_blob_size
433 + blob->n_methods * header->function_blob_size
434 + blob->n_signals * header->signal_blob_size;
435
436 return gi_base_info_find_vfunc (rinfo, offset, blob->n_vfuncs, name);
437 }
438
439 /**
440 * gi_interface_info_get_n_constants:
441 * @info: a #GIInterfaceInfo
442 *
443 * Obtain the number of constants that this interface type has.
444 *
445 * Returns: number of constants
446 * Since: 2.80
447 */
448 guint
449 gi_interface_info_get_n_constants (GIInterfaceInfo *info)
450 {
451 GIRealInfo *rinfo = (GIRealInfo *)info;
452 InterfaceBlob *blob;
453
454 g_return_val_if_fail (info != NULL, 0);
455 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), 0);
456
457 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
458
459 return blob->n_constants;
460 }
461
462 /**
463 * gi_interface_info_get_constant:
464 * @info: a #GIInterfaceInfo
465 * @n: index of constant to get
466 *
467 * Obtain an interface type constant at index @n.
468 *
469 * Returns: (transfer full): The [class@GIRepository.ConstantInfo]. Free the
470 * struct by calling [method@GIRepository.BaseInfo.unref] when done.
471 * Since: 2.80
472 */
473 GIConstantInfo *
474 gi_interface_info_get_constant (GIInterfaceInfo *info,
475 guint n)
476 {
477 gint offset;
478 GIRealInfo *rinfo = (GIRealInfo *)info;
479 Header *header;
480 InterfaceBlob *blob;
481
482 g_return_val_if_fail (info != NULL, NULL);
483 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
484
485 header = (Header *)rinfo->typelib->data;
486 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
487
488 offset = rinfo->offset + header->interface_blob_size
489 + (blob->n_prerequisites + (blob->n_prerequisites % 2)) * 2
490 + blob->n_properties * header->property_blob_size
491 + blob->n_methods * header->function_blob_size
492 + blob->n_signals * header->signal_blob_size
493 + blob->n_vfuncs * header->vfunc_blob_size
494 + n * header->constant_blob_size;
495
496 return (GIConstantInfo *) gi_info_new (GI_INFO_TYPE_CONSTANT, (GIBaseInfo*)info,
497 rinfo->typelib, offset);
498 }
499
500 /**
501 * gi_interface_info_get_iface_struct:
502 * @info: a #GIInterfaceInfo
503 *
504 * Returns the layout C structure associated with this `GInterface`.
505 *
506 * Returns: (transfer full) (nullable): The [class@GIRepository.StructInfo] or
507 * `NULL` if unknown. Free it with [method@GIRepository.BaseInfo.unref] when
508 * done.
509 * Since: 2.80
510 */
511 GIStructInfo *
512 gi_interface_info_get_iface_struct (GIInterfaceInfo *info)
513 {
514 GIRealInfo *rinfo = (GIRealInfo *)info;
515 InterfaceBlob *blob;
516
517 g_return_val_if_fail (info != NULL, NULL);
518 g_return_val_if_fail (GI_IS_INTERFACE_INFO (info), NULL);
519
520 blob = (InterfaceBlob *)&rinfo->typelib->data[rinfo->offset];
521
522 if (blob->gtype_struct)
523 return (GIStructInfo *) gi_info_from_entry (rinfo->repository,
524 rinfo->typelib, blob->gtype_struct);
525 else
526 return NULL;
527 }
528
529 void
530 gi_interface_info_class_init (gpointer g_class,
531 gpointer class_data)
532 {
533 GIBaseInfoClass *info_class = g_class;
534
535 info_class->info_type = GI_INFO_TYPE_INTERFACE;
536 }