1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Base struct 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 <stdlib.h>
28 #include <string.h>
29
30 #include <glib.h>
31 #include <glib-object.h>
32 #include <gobject/gvaluecollector.h>
33
34 #include "gitypelib-internal.h"
35 #include "girepository-private.h"
36 #include "gibaseinfo.h"
37 #include "gibaseinfo-private.h"
38
39 #define INVALID_REFCOUNT 0x7FFFFFFF
40
41 /* Type registration of BaseInfo. */
42 #define GI_BASE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GI_TYPE_BASE_INFO, GIBaseInfoClass))
43
44 static void
45 value_base_info_init (GValue *value)
46 {
47 value->data[0].v_pointer = NULL;
48 }
49
50 static void
51 value_base_info_free_value (GValue *value)
52 {
53 if (value->data[0].v_pointer != NULL)
54 gi_base_info_unref (value->data[0].v_pointer);
55 }
56
57 static void
58 value_base_info_copy_value (const GValue *src,
59 GValue *dst)
60 {
61 if (src->data[0].v_pointer != NULL)
62 dst->data[0].v_pointer = gi_base_info_ref (src->data[0].v_pointer);
63 else
64 dst->data[0].v_pointer = NULL;
65 }
66
67 static gpointer
68 value_base_info_peek_pointer (const GValue *value)
69 {
70 return value->data[0].v_pointer;
71 }
72
73 static char *
74 value_base_info_collect_value (GValue *value,
75 guint n_collect_values,
76 GTypeCValue *collect_values,
77 guint collect_flags)
78 {
79 GIBaseInfo *info = collect_values[0].v_pointer;
80
81 if (info == NULL)
82 {
83 value->data[0].v_pointer = NULL;
84 return NULL;
85 }
86
87 if (info->parent_instance.g_class == NULL)
88 return g_strconcat ("invalid unclassed GIBaseInfo pointer for "
89 "value type '",
90 G_VALUE_TYPE_NAME (value),
91 "'",
92 NULL);
93
94 value->data[0].v_pointer = gi_base_info_ref (info);
95
96 return NULL;
97 }
98
99 static gchar *
100 value_base_info_lcopy_value (const GValue *value,
101 guint n_collect_values,
102 GTypeCValue *collect_values,
103 guint collect_flags)
104 {
105 GIBaseInfo **node_p = collect_values[0].v_pointer;
106
107 if (node_p == NULL)
108 return g_strconcat ("value location for '",
109 G_VALUE_TYPE_NAME (value),
110 "' passed as NULL",
111 NULL);
112
113 if (value->data[0].v_pointer == NULL)
114 *node_p = NULL;
115 else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
116 *node_p = value->data[0].v_pointer;
117 else
118 *node_p = gi_base_info_ref (value->data[0].v_pointer);
119
120 return NULL;
121 }
122
123 static void
124 gi_base_info_finalize (GIBaseInfo *self)
125 {
126 if (self->container && self->container->ref_count != INVALID_REFCOUNT)
127 gi_base_info_unref (self->container);
128
129 g_clear_object (&self->repository);
130
131 g_type_free_instance ((GTypeInstance *) self);
132 }
133
134 static void
135 gi_base_info_class_init (GIBaseInfoClass *klass)
136 {
137 klass->info_type = GI_INFO_TYPE_INVALID;
138 klass->finalize = gi_base_info_finalize;
139 }
140
141 static void
142 gi_base_info_init (GIBaseInfo *self)
143 {
144 g_atomic_ref_count_init (&self->ref_count);
145 }
146
147 GType
148 gi_base_info_get_type (void)
149 {
150 static GType base_info_type = 0;
151
152 if (g_once_init_enter_pointer (&base_info_type))
153 {
154 static const GTypeFundamentalInfo finfo = {
155 (G_TYPE_FLAG_CLASSED |
156 G_TYPE_FLAG_INSTANTIATABLE |
157 G_TYPE_FLAG_DERIVABLE |
158 G_TYPE_FLAG_DEEP_DERIVABLE),
159 };
160
161 static const GTypeValueTable value_table = {
162 value_base_info_init,
163 value_base_info_free_value,
164 value_base_info_copy_value,
165 value_base_info_peek_pointer,
166 "p",
167 value_base_info_collect_value,
168 "p",
169 value_base_info_lcopy_value,
170 };
171
172 const GTypeInfo type_info = {
173 /* Class */
174 sizeof (GIBaseInfoClass),
175 (GBaseInitFunc) NULL,
176 (GBaseFinalizeFunc) NULL,
177 (GClassInitFunc) gi_base_info_class_init,
178 (GClassFinalizeFunc) NULL,
179 NULL,
180
181 /* Instance */
182 sizeof (GIBaseInfo),
183 0,
184 (GInstanceInitFunc) gi_base_info_init,
185
186 /* GValue */
187 &value_table,
188 };
189
190 GType _base_info_type =
191 g_type_register_fundamental (g_type_fundamental_next (),
192 g_intern_static_string ("GIBaseInfo"),
193 &type_info, &finfo,
194 G_TYPE_FLAG_ABSTRACT);
195
196 g_once_init_leave_pointer (&base_info_type, _base_info_type);
197 }
198
199 return base_info_type;
200 }
201
202 /*< private >
203 * gi_base_info_type_register_static:
204 * @type_name: the name of the type
205 * @instance_size: size (in bytes) of the type’s instance struct
206 * @class_init: class init function for the type
207 *
208 * Registers a new [type@GIRepository.BaseInfo] type for the given @type_name
209 * using the type information provided.
210 *
211 * Returns: the newly registered [type@GObject.Type]
212 * Since: 2.80
213 */
214 GType
215 gi_base_info_type_register_static (const char *type_name,
216 gsize instance_size,
217 GClassInitFunc class_init)
218 {
219 GTypeInfo info;
220
221 info.class_size = sizeof (GIBaseInfoClass);
222 info.base_init = NULL;
223 info.base_finalize = NULL;
224 info.class_init = class_init;
225 info.class_finalize = NULL;
226 info.instance_size = instance_size;
227 info.n_preallocs = 0;
228 info.instance_init = NULL;
229 info.value_table = NULL;
230
231 return g_type_register_static (GI_TYPE_BASE_INFO, type_name, &info, 0);
232 }
233
234 static GType gi_base_info_types[GI_INFO_TYPE_N_TYPES];
235
236 #define GI_DEFINE_BASE_INFO_TYPE(type_name, TYPE_ENUM_VALUE) \
237 GType \
238 type_name ## _get_type (void) \
239 { \
240 gi_base_info_init_types (); \
241 g_assert (gi_base_info_types[TYPE_ENUM_VALUE] != G_TYPE_INVALID); \
242 return gi_base_info_types[TYPE_ENUM_VALUE]; \
243 }
244
245 GI_DEFINE_BASE_INFO_TYPE (gi_callable_info, GI_INFO_TYPE_CALLABLE)
246 GI_DEFINE_BASE_INFO_TYPE (gi_function_info, GI_INFO_TYPE_FUNCTION)
247 GI_DEFINE_BASE_INFO_TYPE (gi_callback_info, GI_INFO_TYPE_CALLBACK)
248 GI_DEFINE_BASE_INFO_TYPE (gi_registered_type_info, GI_INFO_TYPE_REGISTERED_TYPE)
249 GI_DEFINE_BASE_INFO_TYPE (gi_struct_info, GI_INFO_TYPE_STRUCT)
250 GI_DEFINE_BASE_INFO_TYPE (gi_union_info, GI_INFO_TYPE_UNION)
251 GI_DEFINE_BASE_INFO_TYPE (gi_enum_info, GI_INFO_TYPE_ENUM)
252 GI_DEFINE_BASE_INFO_TYPE (gi_object_info, GI_INFO_TYPE_OBJECT)
253 GI_DEFINE_BASE_INFO_TYPE (gi_interface_info, GI_INFO_TYPE_INTERFACE)
254 GI_DEFINE_BASE_INFO_TYPE (gi_constant_info, GI_INFO_TYPE_CONSTANT)
255 GI_DEFINE_BASE_INFO_TYPE (gi_value_info, GI_INFO_TYPE_VALUE)
256 GI_DEFINE_BASE_INFO_TYPE (gi_signal_info, GI_INFO_TYPE_SIGNAL)
257 GI_DEFINE_BASE_INFO_TYPE (gi_vfunc_info, GI_INFO_TYPE_VFUNC)
258 GI_DEFINE_BASE_INFO_TYPE (gi_property_info, GI_INFO_TYPE_PROPERTY)
259 GI_DEFINE_BASE_INFO_TYPE (gi_field_info, GI_INFO_TYPE_FIELD)
260 GI_DEFINE_BASE_INFO_TYPE (gi_arg_info, GI_INFO_TYPE_ARG)
261 GI_DEFINE_BASE_INFO_TYPE (gi_type_info, GI_INFO_TYPE_TYPE)
262 GI_DEFINE_BASE_INFO_TYPE (gi_unresolved_info, GI_INFO_TYPE_UNRESOLVED)
263
264 void
265 gi_base_info_init_types (void)
266 {
267 static gsize register_types_once = 0;
268
269 if (g_once_init_enter (®ister_types_once))
270 {
271 const struct
272 {
273 GIInfoType info_type;
274 const char *type_name;
275 gsize instance_size;
276 GClassInitFunc class_init;
277 }
278 types[] =
279 {
280 { GI_INFO_TYPE_CALLABLE, "GICallableInfo", sizeof (GICallableInfo), gi_callable_info_class_init },
281 { GI_INFO_TYPE_FUNCTION, "GIFunctionInfo", sizeof (GIFunctionInfo), gi_function_info_class_init },
282 { GI_INFO_TYPE_CALLBACK, "GICallbackInfo", sizeof (GICallbackInfo), gi_callback_info_class_init },
283 { GI_INFO_TYPE_REGISTERED_TYPE, "GIRegisteredTypeInfo", sizeof (GIRegisteredTypeInfo), gi_registered_type_info_class_init },
284 { GI_INFO_TYPE_STRUCT, "GIStructInfo", sizeof (GIStructInfo), gi_struct_info_class_init },
285 { GI_INFO_TYPE_UNION, "GIUnionInfo", sizeof (GIUnionInfo), gi_union_info_class_init },
286 { GI_INFO_TYPE_ENUM, "GIEnumInfo", sizeof (GIEnumInfo), gi_enum_info_class_init },
287 { GI_INFO_TYPE_OBJECT, "GIObjectInfo", sizeof (GIObjectInfo), gi_object_info_class_init },
288 { GI_INFO_TYPE_INTERFACE, "GIInterfaceInfo", sizeof (GIInterfaceInfo), gi_interface_info_class_init },
289 { GI_INFO_TYPE_CONSTANT, "GIConstantInfo", sizeof (GIConstantInfo), gi_constant_info_class_init },
290 { GI_INFO_TYPE_VALUE, "GIValueInfo", sizeof (GIValueInfo), gi_value_info_class_init },
291 { GI_INFO_TYPE_SIGNAL, "GISignalInfo", sizeof (GISignalInfo), gi_signal_info_class_init },
292 { GI_INFO_TYPE_VFUNC, "GIVFuncInfo", sizeof (GIVFuncInfo), gi_vfunc_info_class_init },
293 { GI_INFO_TYPE_PROPERTY, "GIPropertyInfo", sizeof (GIPropertyInfo), gi_property_info_class_init },
294 { GI_INFO_TYPE_FIELD, "GIFieldInfo", sizeof (GIFieldInfo), gi_field_info_class_init },
295 { GI_INFO_TYPE_ARG, "GIArgInfo", sizeof (GIArgInfo), gi_arg_info_class_init },
296 { GI_INFO_TYPE_TYPE, "GITypeInfo", sizeof (GITypeInfo), gi_type_info_class_init },
297 { GI_INFO_TYPE_UNRESOLVED, "GIUnresolvedInfo", sizeof (GIUnresolvedInfo), gi_unresolved_info_class_init },
298 };
299
300 for (gsize i = 0; i < G_N_ELEMENTS (types); i++)
301 {
302 GType registered_type = gi_base_info_type_register_static (g_intern_static_string (types[i].type_name),
303 types[i].instance_size,
304 types[i].class_init);
305 gi_base_info_types[types[i].info_type] = registered_type;
306 }
307
308 g_once_init_leave (®ister_types_once, 1);
309 }
310 }
311
312 /* info creation */
313 GIBaseInfo *
314 gi_info_new_full (GIInfoType type,
315 GIRepository *repository,
316 GIBaseInfo *container,
317 GITypelib *typelib,
318 guint32 offset)
319 {
320 GIRealInfo *info;
321
322 g_return_val_if_fail (container != NULL || repository != NULL, NULL);
323 g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
324
325 gi_base_info_init_types ();
326 g_assert (gi_base_info_types[type] != G_TYPE_INVALID);
327 info = (GIRealInfo *) g_type_create_instance (gi_base_info_types[type]);
328
329 info->typelib = typelib;
330 info->offset = offset;
331
332 if (container)
333 info->container = container;
334 if (container && container->ref_count != INVALID_REFCOUNT)
335 gi_base_info_ref (info->container);
336
337 info->repository = g_object_ref (repository);
338
339 return (GIBaseInfo*)info;
340 }
341
342 /**
343 * gi_info_new:
344 * @type: type of the info to create
345 * @container: (nullable): info which contains this one
346 * @typelib: typelib containing the info
347 * @offset: offset of the info within @typelib, in bytes
348 *
349 * Create a new #GIBaseInfo representing an object of the given @type from
350 * @offset of @typelib.
351 *
352 * Returns: (transfer full): The new #GIBaseInfo, unref with
353 * [method@GIRepository.BaseInfo.unref]
354 * Since: 2.80
355 */
356 GIBaseInfo *
357 gi_info_new (GIInfoType type,
358 GIBaseInfo *container,
359 GITypelib *typelib,
360 guint32 offset)
361 {
362 return gi_info_new_full (type, ((GIRealInfo*)container)->repository, container, typelib, offset);
363 }
364
365 /*< private >
366 * gi_info_init:
367 * @info: (out caller-allocates): caller-allocated #GIRealInfo to populate
368 * @type: type of the info to create
369 * @repository: repository the info is in
370 * @container: (nullable): info which contains this one
371 * @typelib: typelib containing the info
372 * @offset: offset of the info within @typelib, in bytes
373 *
374 * Initialise a stack-allocated #GIBaseInfo representing an object of the given
375 * @type from @offset of @typelib.
376 *
377 * Since: 2.80
378 */
379 void
380 gi_info_init (GIRealInfo *info,
381 GIInfoType type,
382 GIRepository *repository,
383 GIBaseInfo *container,
384 GITypelib *typelib,
385 guint32 offset)
386 {
387 memset (info, 0, sizeof (GIRealInfo));
388
389 /* Invalid refcount used to flag stack-allocated infos */
390 info->ref_count = INVALID_REFCOUNT;
391 info->typelib = typelib;
392 info->offset = offset;
393
394 if (container)
395 info->container = container;
396
397 g_assert (GI_IS_REPOSITORY (repository));
398 info->repository = repository;
399 }
400
401 GIBaseInfo *
402 gi_info_from_entry (GIRepository *repository,
403 GITypelib *typelib,
404 guint16 index)
405 {
406 GIBaseInfo *result;
407 DirEntry *entry = gi_typelib_get_dir_entry (typelib, index);
408
409 if (entry->local)
410 result = gi_info_new_full (entry->blob_type, repository, NULL, typelib, entry->offset);
411 else
412 {
413 const gchar *namespace = gi_typelib_get_string (typelib, entry->offset);
414 const gchar *name = gi_typelib_get_string (typelib, entry->name);
415
416 result = gi_repository_find_by_name (repository, namespace, name);
417 if (result == NULL)
418 {
419 GIUnresolvedInfo *unresolved;
420
421 unresolved = (GIUnresolvedInfo *) gi_info_new_full (GI_INFO_TYPE_UNRESOLVED,
422 repository,
423 NULL,
424 typelib,
425 entry->offset);
426
427 unresolved->name = name;
428 unresolved->namespace = namespace;
429
430 return (GIBaseInfo *)unresolved;
431 }
432 return (GIBaseInfo *)result;
433 }
434
435 return (GIBaseInfo *)result;
436 }
437
438 GITypeInfo *
439 gi_type_info_new (GIBaseInfo *container,
440 GITypelib *typelib,
441 guint32 offset)
442 {
443 SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
444
445 return (GITypeInfo *) gi_info_new (GI_INFO_TYPE_TYPE, container, typelib,
446 (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
447 }
448
449 void
450 gi_type_info_init (GIBaseInfo *info,
451 GIBaseInfo *container,
452 GITypelib *typelib,
453 guint32 offset)
454 {
455 GIRealInfo *rinfo = (GIRealInfo*)container;
456 SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
457
458 gi_info_init ((GIRealInfo*)info, GI_INFO_TYPE_TYPE, rinfo->repository, container, typelib,
459 (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
460 }
461
462 /* GIBaseInfo functions */
463
464 /**
465 * GIBaseInfo:
466 *
467 * `GIBaseInfo` is the common base struct of all other Info structs
468 * accessible through the [class@GIRepository.Repository] API.
469 *
470 * All info structures can be cast to a `GIBaseInfo`, for instance:
471 *
472 * ```c
473 * GIFunctionInfo *function_info = …;
474 * GIBaseInfo *info = (GIBaseInfo *) function_info;
475 * ```
476 *
477 * Most [class@GIRepository.Repository] APIs returning a `GIBaseInfo` are
478 * actually creating a new struct; in other words,
479 * [method@GIRepository.BaseInfo.unref] has to be called when done accessing the
480 * data.
481 *
482 * `GIBaseInfo` structuress are normally accessed by calling either
483 * [method@GIRepository.Repository.find_by_name],
484 * [method@GIRepository.Repository.find_by_gtype] or
485 * [method@GIRepository.get_info].
486 *
487 * ```c
488 * GIBaseInfo *button_info =
489 * gi_repository_find_by_name (NULL, "Gtk", "Button");
490 *
491 * // use button_info…
492 *
493 * gi_base_info_unref (button_info);
494 * ```
495 *
496 * Since: 2.80
497 */
498
499 /**
500 * gi_base_info_ref:
501 * @info: a #GIBaseInfo
502 *
503 * Increases the reference count of @info.
504 *
505 * Returns: (transfer full): the same @info.
506 * Since: 2.80
507 */
508 GIBaseInfo *
509 gi_base_info_ref (GIBaseInfo *info)
510 {
511 GIRealInfo *rinfo = (GIRealInfo*)info;
512
513 g_assert (rinfo->ref_count != INVALID_REFCOUNT);
514 g_atomic_ref_count_inc (&rinfo->ref_count);
515
516 return info;
517 }
518
519 /**
520 * gi_base_info_unref:
521 * @info: (transfer full): a #GIBaseInfo
522 *
523 * Decreases the reference count of @info. When its reference count
524 * drops to 0, the info is freed.
525 *
526 * Since: 2.80
527 */
528 void
529 gi_base_info_unref (GIBaseInfo *info)
530 {
531 GIRealInfo *rinfo = (GIRealInfo*)info;
532
533 g_assert (rinfo->ref_count > 0 && rinfo->ref_count != INVALID_REFCOUNT);
534
535 if (g_atomic_ref_count_dec (&rinfo->ref_count))
536 GI_BASE_INFO_GET_CLASS (info)->finalize (info);
537 }
538
539 /**
540 * gi_base_info_get_info_type:
541 * @info: a #GIBaseInfo
542 *
543 * Obtain the info type of the `GIBaseInfo`.
544 *
545 * Returns: the info type of @info
546 * Since: 2.80
547 */
548 GIInfoType
549 gi_base_info_get_info_type (GIBaseInfo *info)
550 {
551 return GI_BASE_INFO_GET_CLASS (info)->info_type;
552 }
553
554 /**
555 * gi_base_info_get_name:
556 * @info: a #GIBaseInfo
557 *
558 * Obtain the name of the @info.
559 *
560 * What the name represents depends on the [type@GIRepository.InfoType] of the
561 * @info. For instance for [class@GIRepository.FunctionInfo] it is the name of
562 * the function.
563 *
564 * Returns: (nullable): the name of @info or `NULL` if it lacks a name.
565 * Since: 2.80
566 */
567 const gchar *
568 gi_base_info_get_name (GIBaseInfo *info)
569 {
570 GIRealInfo *rinfo = (GIRealInfo*)info;
571 g_assert (rinfo->ref_count > 0);
572 switch (gi_base_info_get_info_type ((GIBaseInfo *) info))
573 {
574 case GI_INFO_TYPE_FUNCTION:
575 case GI_INFO_TYPE_CALLBACK:
576 case GI_INFO_TYPE_STRUCT:
577 case GI_INFO_TYPE_BOXED:
578 case GI_INFO_TYPE_ENUM:
579 case GI_INFO_TYPE_FLAGS:
580 case GI_INFO_TYPE_OBJECT:
581 case GI_INFO_TYPE_INTERFACE:
582 case GI_INFO_TYPE_CONSTANT:
583 case GI_INFO_TYPE_INVALID_0:
584 case GI_INFO_TYPE_UNION:
585 {
586 CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
587
588 return gi_typelib_get_string (rinfo->typelib, blob->name);
589 }
590 break;
591
592 case GI_INFO_TYPE_VALUE:
593 {
594 ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
595
596 return gi_typelib_get_string (rinfo->typelib, blob->name);
597 }
598 break;
599
600 case GI_INFO_TYPE_SIGNAL:
601 {
602 SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
603
604 return gi_typelib_get_string (rinfo->typelib, blob->name);
605 }
606 break;
607
608 case GI_INFO_TYPE_PROPERTY:
609 {
610 PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
611
612 return gi_typelib_get_string (rinfo->typelib, blob->name);
613 }
614 break;
615
616 case GI_INFO_TYPE_VFUNC:
617 {
618 VFuncBlob *blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
619
620 return gi_typelib_get_string (rinfo->typelib, blob->name);
621 }
622 break;
623
624 case GI_INFO_TYPE_FIELD:
625 {
626 FieldBlob *blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
627
628 return gi_typelib_get_string (rinfo->typelib, blob->name);
629 }
630 break;
631
632 case GI_INFO_TYPE_ARG:
633 {
634 ArgBlob *blob = (ArgBlob *)&rinfo->typelib->data[rinfo->offset];
635
636 return gi_typelib_get_string (rinfo->typelib, blob->name);
637 }
638 break;
639 case GI_INFO_TYPE_UNRESOLVED:
640 {
641 GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
642
643 return unresolved->name;
644 }
645 break;
646 case GI_INFO_TYPE_TYPE:
647 return NULL;
648 default: ;
649 g_assert_not_reached ();
650 /* unnamed */
651 }
652
653 return NULL;
654 }
655
656 /**
657 * gi_base_info_get_namespace:
658 * @info: a #GIBaseInfo
659 *
660 * Obtain the namespace of @info.
661 *
662 * Returns: the namespace
663 * Since: 2.80
664 */
665 const gchar *
666 gi_base_info_get_namespace (GIBaseInfo *info)
667 {
668 GIRealInfo *rinfo = (GIRealInfo*) info;
669 Header *header = (Header *)rinfo->typelib->data;
670
671 g_assert (rinfo->ref_count > 0);
672
673 if (gi_base_info_get_info_type (info) == GI_INFO_TYPE_UNRESOLVED)
674 {
675 GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
676
677 return unresolved->namespace;
678 }
679
680 return gi_typelib_get_string (rinfo->typelib, header->namespace);
681 }
682
683 /**
684 * gi_base_info_is_deprecated:
685 * @info: a #GIBaseInfo
686 *
687 * Obtain whether the @info is represents a metadata which is
688 * deprecated.
689 *
690 * Returns: `TRUE` if deprecated
691 * Since: 2.80
692 */
693 gboolean
694 gi_base_info_is_deprecated (GIBaseInfo *info)
695 {
696 GIRealInfo *rinfo = (GIRealInfo*) info;
697 switch (gi_base_info_get_info_type ((GIBaseInfo *) info))
698 {
699 case GI_INFO_TYPE_FUNCTION:
700 case GI_INFO_TYPE_CALLBACK:
701 case GI_INFO_TYPE_STRUCT:
702 case GI_INFO_TYPE_BOXED:
703 case GI_INFO_TYPE_ENUM:
704 case GI_INFO_TYPE_FLAGS:
705 case GI_INFO_TYPE_OBJECT:
706 case GI_INFO_TYPE_INTERFACE:
707 case GI_INFO_TYPE_CONSTANT:
708 case GI_INFO_TYPE_INVALID_0:
709 {
710 CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
711
712 return blob->deprecated;
713 }
714 break;
715
716 case GI_INFO_TYPE_VALUE:
717 {
718 ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
719
720 return blob->deprecated;
721 }
722 break;
723
724 case GI_INFO_TYPE_SIGNAL:
725 {
726 SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
727
728 return blob->deprecated;
729 }
730 break;
731
732 case GI_INFO_TYPE_PROPERTY:
733 {
734 PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
735
736 return blob->deprecated;
737 }
738 break;
739
740 case GI_INFO_TYPE_VFUNC:
741 case GI_INFO_TYPE_FIELD:
742 case GI_INFO_TYPE_ARG:
743 case GI_INFO_TYPE_TYPE:
744 default: ;
745 /* no deprecation flag for these */
746 }
747
748 return FALSE;
749 }
750
751 /**
752 * gi_base_info_get_attribute:
753 * @info: a #GIBaseInfo
754 * @name: a freeform string naming an attribute
755 *
756 * Retrieve an arbitrary attribute associated with this node.
757 *
758 * Returns: (nullable): The value of the attribute, or `NULL` if no such
759 * attribute exists
760 * Since: 2.80
761 */
762 const gchar *
763 gi_base_info_get_attribute (GIBaseInfo *info,
764 const gchar *name)
765 {
766 GIAttributeIter iter = { 0, };
767 const char *curname, *curvalue;
768 while (gi_base_info_iterate_attributes (info, &iter, &curname, &curvalue))
769 {
770 if (strcmp (name, curname) == 0)
771 return (const gchar*) curvalue;
772 }
773
774 return NULL;
775 }
776
777 static int
778 cmp_attribute (const void *av,
779 const void *bv)
780 {
781 const AttributeBlob *a = av;
782 const AttributeBlob *b = bv;
783
784 if (a->offset < b->offset)
785 return -1;
786 else if (a->offset == b->offset)
787 return 0;
788 else
789 return 1;
790 }
791
792 /*< private >
793 * _attribute_blob_find_first:
794 * @GIBaseInfo: A #GIBaseInfo.
795 * @blob_offset: The offset for the blob to find the first attribute for.
796 *
797 * Searches for the first #AttributeBlob for @blob_offset and returns
798 * it if found.
799 *
800 * Returns: (transfer none): A pointer to #AttributeBlob or `NULL` if not found.
801 * Since: 2.80
802 */
803 AttributeBlob *
804 _attribute_blob_find_first (GIBaseInfo *info,
805 guint32 blob_offset)
806 {
807 GIRealInfo *rinfo = (GIRealInfo *) info;
808 Header *header = (Header *)rinfo->typelib->data;
809 AttributeBlob blob, *first, *res, *previous;
810
811 blob.offset = blob_offset;
812
813 first = (AttributeBlob *) &rinfo->typelib->data[header->attributes];
814
815 res = bsearch (&blob, first, header->n_attributes,
816 header->attribute_blob_size, cmp_attribute);
817
818 if (res == NULL)
819 return NULL;
820
821 previous = res - 1;
822 while (previous >= first && previous->offset == blob_offset)
823 {
824 res = previous;
825 previous = res - 1;
826 }
827
828 return res;
829 }
830
831 /**
832 * gi_base_info_iterate_attributes:
833 * @info: a #GIBaseInfo
834 * @iterator: (inout): a [type@GIRepository.AttributeIter] structure, must be
835 * initialized; see below
836 * @name: (out) (transfer none): Returned name, must not be freed
837 * @value: (out) (transfer none): Returned name, must not be freed
838 *
839 * Iterate over all attributes associated with this node.
840 *
841 * The iterator structure is typically stack allocated, and must have its first
842 * member initialized to `NULL`. Attributes are arbitrary namespaced key–value
843 * pairs which can be attached to almost any item. They are intended for use
844 * by software higher in the toolchain than bindings, and are distinct from
845 * normal GIR annotations.
846 *
847 * Both the @name and @value should be treated as constants
848 * and must not be freed.
849 *
850 * ```c
851 * void
852 * print_attributes (GIBaseInfo *info)
853 * {
854 * GIAttributeIter iter = { 0, };
855 * const char *name;
856 * const char *value;
857 * while (gi_base_info_iterate_attributes (info, &iter, &name, &value))
858 * {
859 * g_print ("attribute name: %s value: %s", name, value);
860 * }
861 * }
862 * ```
863 *
864 * Returns: `TRUE` if there are more attributes
865 * Since: 2.80
866 */
867 gboolean
868 gi_base_info_iterate_attributes (GIBaseInfo *info,
869 GIAttributeIter *iterator,
870 const gchar **name,
871 const gchar **value)
872 {
873 GIRealInfo *rinfo = (GIRealInfo *)info;
874 Header *header = (Header *)rinfo->typelib->data;
875 AttributeBlob *next, *after;
876
877 after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
878 header->n_attributes * header->attribute_blob_size];
879
880 if (iterator->data != NULL)
881 next = (AttributeBlob *) iterator->data;
882 else
883 next = _attribute_blob_find_first (info, rinfo->offset);
884
885 if (next == NULL || next->offset != rinfo->offset || next >= after)
886 return FALSE;
887
888 *name = gi_typelib_get_string (rinfo->typelib, next->name);
889 *value = gi_typelib_get_string (rinfo->typelib, next->value);
890 iterator->data = next + 1;
891
892 return TRUE;
893 }
894
895 /**
896 * gi_base_info_get_container:
897 * @info: a #GIBaseInfo
898 *
899 * Obtain the container of the @info.
900 *
901 * The container is the parent `GIBaseInfo`. For instance, the parent of a
902 * [class@GIRepository.FunctionInfo] is an [class@GIRepository.ObjectInfo] or
903 * [class@GIRepository.InterfaceInfo].
904 *
905 * Returns: (transfer none): the container
906 * Since: 2.80
907 */
908 GIBaseInfo *
909 gi_base_info_get_container (GIBaseInfo *info)
910 {
911 return ((GIRealInfo*)info)->container;
912 }
913
914 /**
915 * gi_base_info_get_typelib:
916 * @info: a #GIBaseInfo
917 *
918 * Obtain the typelib this @info belongs to
919 *
920 * Returns: (transfer none): the typelib
921 * Since: 2.80
922 */
923 GITypelib *
924 gi_base_info_get_typelib (GIBaseInfo *info)
925 {
926 return ((GIRealInfo*)info)->typelib;
927 }
928
929 /**
930 * gi_base_info_equal:
931 * @info1: a #GIBaseInfo
932 * @info2: a #GIBaseInfo
933 *
934 * Compare two `GIBaseInfo`s.
935 *
936 * Using pointer comparison is not practical since many functions return
937 * different instances of `GIBaseInfo` that refers to the same part of the
938 * TypeLib; use this function instead to do `GIBaseInfo` comparisons.
939 *
940 * Returns: `TRUE` if and only if @info1 equals @info2.
941 * Since: 2.80
942 */
943 gboolean
944 gi_base_info_equal (GIBaseInfo *info1, GIBaseInfo *info2)
945 {
946 /* Compare the TypeLib pointers, which are mmapped. */
947 GIRealInfo *rinfo1 = (GIRealInfo*)info1;
948 GIRealInfo *rinfo2 = (GIRealInfo*)info2;
949 return rinfo1->typelib->data + rinfo1->offset == rinfo2->typelib->data + rinfo2->offset;
950 }