Branch data Line data Source code
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 : 0 : value_base_info_init (GValue *value)
46 : : {
47 : 0 : value->data[0].v_pointer = NULL;
48 : 0 : }
49 : :
50 : : static void
51 : 0 : value_base_info_free_value (GValue *value)
52 : : {
53 [ # # ]: 0 : if (value->data[0].v_pointer != NULL)
54 : 0 : gi_base_info_unref (value->data[0].v_pointer);
55 : 0 : }
56 : :
57 : : static void
58 : 0 : value_base_info_copy_value (const GValue *src,
59 : : GValue *dst)
60 : : {
61 [ # # ]: 0 : if (src->data[0].v_pointer != NULL)
62 : 0 : dst->data[0].v_pointer = gi_base_info_ref (src->data[0].v_pointer);
63 : : else
64 : 0 : dst->data[0].v_pointer = NULL;
65 : 0 : }
66 : :
67 : : static void *
68 : 0 : value_base_info_peek_pointer (const GValue *value)
69 : : {
70 : 0 : return value->data[0].v_pointer;
71 : : }
72 : :
73 : : static char *
74 : 0 : value_base_info_collect_value (GValue *value,
75 : : guint n_collect_values,
76 : : GTypeCValue *collect_values,
77 : : guint collect_flags)
78 : : {
79 : 0 : GIBaseInfo *info = collect_values[0].v_pointer;
80 : :
81 [ # # ]: 0 : if (info == NULL)
82 : : {
83 : 0 : value->data[0].v_pointer = NULL;
84 : 0 : return NULL;
85 : : }
86 : :
87 [ # # ]: 0 : if (info->parent_instance.g_class == NULL)
88 : 0 : return g_strconcat ("invalid unclassed GIBaseInfo pointer for "
89 : : "value type '",
90 : : G_VALUE_TYPE_NAME (value),
91 : : "'",
92 : : NULL);
93 : :
94 : 0 : value->data[0].v_pointer = gi_base_info_ref (info);
95 : :
96 : 0 : return NULL;
97 : : }
98 : :
99 : : static char *
100 : 0 : value_base_info_lcopy_value (const GValue *value,
101 : : guint n_collect_values,
102 : : GTypeCValue *collect_values,
103 : : guint collect_flags)
104 : : {
105 : 0 : GIBaseInfo **node_p = collect_values[0].v_pointer;
106 : :
107 [ # # ]: 0 : if (node_p == NULL)
108 : 0 : return g_strconcat ("value location for '",
109 : : G_VALUE_TYPE_NAME (value),
110 : : "' passed as NULL",
111 : : NULL);
112 : :
113 [ # # ]: 0 : if (value->data[0].v_pointer == NULL)
114 : 0 : *node_p = NULL;
115 [ # # ]: 0 : else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
116 : 0 : *node_p = value->data[0].v_pointer;
117 : : else
118 : 0 : *node_p = gi_base_info_ref (value->data[0].v_pointer);
119 : :
120 : 0 : return NULL;
121 : : }
122 : :
123 : : static void
124 : 3003 : gi_base_info_finalize (GIBaseInfo *self)
125 : : {
126 [ + + ]: 3003 : if (self->ref_count != INVALID_REFCOUNT &&
127 [ + + + - ]: 2991 : self->container && self->container->ref_count != INVALID_REFCOUNT)
128 : 992 : gi_base_info_unref (self->container);
129 : 3003 : }
130 : :
131 : : static void
132 : 8 : gi_base_info_class_init (GIBaseInfoClass *klass)
133 : : {
134 : 8 : klass->info_type = GI_INFO_TYPE_INVALID;
135 : 8 : klass->finalize = gi_base_info_finalize;
136 : 8 : }
137 : :
138 : : static void
139 : 2991 : gi_base_info_init (GIBaseInfo *self)
140 : : {
141 : : /* Initialise a dynamically allocated #GIBaseInfo’s members.
142 : : *
143 : : * This function *must* be kept in sync with gi_info_init(). */
144 : 2991 : g_atomic_ref_count_init (&self->ref_count);
145 : 2991 : }
146 : :
147 : : GType
148 : 6033 : gi_base_info_get_type (void)
149 : : {
150 : : static GType base_info_type = 0;
151 : :
152 [ + + + - : 6033 : 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 : 9 : 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 : 9 : 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 : 9 : g_once_init_leave_pointer (&base_info_type, _base_info_type);
197 : : }
198 : :
199 : 6033 : 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 : : * @parent_type: [type@GObject.Type] for the parent type; this will typically be
208 : : * `GI_TYPE_BASE_INFO`
209 : : * @type_flags: flags for the type
210 : : *
211 : : * Registers a new [type@GIRepository.BaseInfo] type for the given @type_name
212 : : * using the type information provided.
213 : : *
214 : : * Returns: the newly registered [type@GObject.Type]
215 : : * Since: 2.80
216 : : */
217 : : GType
218 : 171 : gi_base_info_type_register_static (const char *type_name,
219 : : size_t instance_size,
220 : : GClassInitFunc class_init,
221 : : GType parent_type,
222 : : GTypeFlags type_flags)
223 : : {
224 : : GTypeInfo info;
225 : :
226 : 171 : g_assert (instance_size <= G_MAXUINT16);
227 : :
228 : 171 : info.class_size = sizeof (GIBaseInfoClass);
229 : 171 : info.base_init = NULL;
230 : 171 : info.base_finalize = NULL;
231 : 171 : info.class_init = class_init;
232 : 171 : info.class_finalize = NULL;
233 : 171 : info.instance_size = (guint16) instance_size;
234 : 171 : info.n_preallocs = 0;
235 : 171 : info.instance_init = NULL;
236 : 171 : info.value_table = NULL;
237 : :
238 : 171 : return g_type_register_static (parent_type, type_name, &info, type_flags);
239 : : }
240 : :
241 : : static GType gi_base_info_types[GI_INFO_TYPE_N_TYPES];
242 : :
243 : : #define GI_DEFINE_BASE_INFO_TYPE(type_name, TYPE_ENUM_VALUE) \
244 : : GType \
245 : : type_name ## _get_type (void) \
246 : : { \
247 : : gi_base_info_init_types (); \
248 : : g_assert (gi_base_info_types[TYPE_ENUM_VALUE] != G_TYPE_INVALID); \
249 : : return gi_base_info_types[TYPE_ENUM_VALUE]; \
250 : : }
251 : :
252 [ - + ]: 66 : GI_DEFINE_BASE_INFO_TYPE (gi_callable_info, GI_INFO_TYPE_CALLABLE)
253 [ - + ]: 15 : GI_DEFINE_BASE_INFO_TYPE (gi_function_info, GI_INFO_TYPE_FUNCTION)
254 [ - + ]: 4 : GI_DEFINE_BASE_INFO_TYPE (gi_callback_info, GI_INFO_TYPE_CALLBACK)
255 [ - + ]: 36 : GI_DEFINE_BASE_INFO_TYPE (gi_registered_type_info, GI_INFO_TYPE_REGISTERED_TYPE)
256 [ - + ]: 25 : GI_DEFINE_BASE_INFO_TYPE (gi_struct_info, GI_INFO_TYPE_STRUCT)
257 [ - + ]: 7 : GI_DEFINE_BASE_INFO_TYPE (gi_union_info, GI_INFO_TYPE_UNION)
258 [ - + ]: 2935 : GI_DEFINE_BASE_INFO_TYPE (gi_enum_info, GI_INFO_TYPE_ENUM)
259 [ - + ]: 968 : GI_DEFINE_BASE_INFO_TYPE (gi_flags_info, GI_INFO_TYPE_FLAGS)
260 [ - + ]: 56 : GI_DEFINE_BASE_INFO_TYPE (gi_object_info, GI_INFO_TYPE_OBJECT)
261 [ - + ]: 12 : GI_DEFINE_BASE_INFO_TYPE (gi_interface_info, GI_INFO_TYPE_INTERFACE)
262 [ - + ]: 2 : GI_DEFINE_BASE_INFO_TYPE (gi_constant_info, GI_INFO_TYPE_CONSTANT)
263 [ - + ]: 1 : GI_DEFINE_BASE_INFO_TYPE (gi_value_info, GI_INFO_TYPE_VALUE)
264 [ - + ]: 3 : GI_DEFINE_BASE_INFO_TYPE (gi_signal_info, GI_INFO_TYPE_SIGNAL)
265 [ - + ]: 4 : GI_DEFINE_BASE_INFO_TYPE (gi_vfunc_info, GI_INFO_TYPE_VFUNC)
266 [ - + ]: 1 : GI_DEFINE_BASE_INFO_TYPE (gi_property_info, GI_INFO_TYPE_PROPERTY)
267 [ - + ]: 5 : GI_DEFINE_BASE_INFO_TYPE (gi_field_info, GI_INFO_TYPE_FIELD)
268 [ - + ]: 41 : GI_DEFINE_BASE_INFO_TYPE (gi_arg_info, GI_INFO_TYPE_ARG)
269 [ - + ]: 58 : GI_DEFINE_BASE_INFO_TYPE (gi_type_info, GI_INFO_TYPE_TYPE)
270 [ - + ]: 1 : GI_DEFINE_BASE_INFO_TYPE (gi_unresolved_info, GI_INFO_TYPE_UNRESOLVED)
271 : :
272 : : void
273 : 7231 : gi_base_info_init_types (void)
274 : : {
275 : : static size_t register_types_once = 0;
276 : :
277 [ + + + - : 7231 : if (g_once_init_enter (®ister_types_once))
+ + ]
278 : : {
279 : : const struct
280 : : {
281 : : GIInfoType info_type;
282 : : const char *type_name;
283 : : size_t instance_size;
284 : : GClassInitFunc class_init;
285 : : GIInfoType parent_info_type; /* 0 for GIBaseInfo */
286 : : GTypeFlags type_flags;
287 : : }
288 : 9 : types[] =
289 : : {
290 : : { GI_INFO_TYPE_CALLABLE, "GICallableInfo", sizeof (GICallableInfo), gi_callable_info_class_init, 0, G_TYPE_FLAG_ABSTRACT },
291 : : { GI_INFO_TYPE_FUNCTION, "GIFunctionInfo", sizeof (GIFunctionInfo), gi_function_info_class_init, GI_INFO_TYPE_CALLABLE, G_TYPE_FLAG_NONE },
292 : : { GI_INFO_TYPE_CALLBACK, "GICallbackInfo", sizeof (GICallbackInfo), gi_callback_info_class_init, GI_INFO_TYPE_CALLABLE, G_TYPE_FLAG_NONE },
293 : : { GI_INFO_TYPE_REGISTERED_TYPE, "GIRegisteredTypeInfo", sizeof (GIRegisteredTypeInfo), gi_registered_type_info_class_init, 0, G_TYPE_FLAG_ABSTRACT },
294 : : { GI_INFO_TYPE_STRUCT, "GIStructInfo", sizeof (GIStructInfo), gi_struct_info_class_init, GI_INFO_TYPE_REGISTERED_TYPE, G_TYPE_FLAG_NONE },
295 : : { GI_INFO_TYPE_UNION, "GIUnionInfo", sizeof (GIUnionInfo), gi_union_info_class_init, GI_INFO_TYPE_REGISTERED_TYPE, G_TYPE_FLAG_NONE },
296 : : { GI_INFO_TYPE_ENUM, "GIEnumInfo", sizeof (GIEnumInfo), gi_enum_info_class_init, GI_INFO_TYPE_REGISTERED_TYPE, G_TYPE_FLAG_NONE },
297 : : { GI_INFO_TYPE_FLAGS, "GIFlagsInfo", sizeof (GIFlagsInfo), gi_flags_info_class_init, GI_INFO_TYPE_ENUM, G_TYPE_FLAG_NONE },
298 : : { GI_INFO_TYPE_OBJECT, "GIObjectInfo", sizeof (GIObjectInfo), gi_object_info_class_init, GI_INFO_TYPE_REGISTERED_TYPE, G_TYPE_FLAG_NONE },
299 : : { GI_INFO_TYPE_INTERFACE, "GIInterfaceInfo", sizeof (GIInterfaceInfo), gi_interface_info_class_init, GI_INFO_TYPE_REGISTERED_TYPE, G_TYPE_FLAG_NONE },
300 : : { GI_INFO_TYPE_CONSTANT, "GIConstantInfo", sizeof (GIConstantInfo), gi_constant_info_class_init, 0, G_TYPE_FLAG_NONE },
301 : : { GI_INFO_TYPE_VALUE, "GIValueInfo", sizeof (GIValueInfo), gi_value_info_class_init, 0, G_TYPE_FLAG_NONE },
302 : : { GI_INFO_TYPE_SIGNAL, "GISignalInfo", sizeof (GISignalInfo), gi_signal_info_class_init, GI_INFO_TYPE_CALLABLE, G_TYPE_FLAG_NONE },
303 : : { GI_INFO_TYPE_VFUNC, "GIVFuncInfo", sizeof (GIVFuncInfo), gi_vfunc_info_class_init, GI_INFO_TYPE_CALLABLE, G_TYPE_FLAG_NONE },
304 : : { GI_INFO_TYPE_PROPERTY, "GIPropertyInfo", sizeof (GIPropertyInfo), gi_property_info_class_init, 0, G_TYPE_FLAG_NONE },
305 : : { GI_INFO_TYPE_FIELD, "GIFieldInfo", sizeof (GIFieldInfo), gi_field_info_class_init, 0, G_TYPE_FLAG_NONE },
306 : : { GI_INFO_TYPE_ARG, "GIArgInfo", sizeof (GIArgInfo), gi_arg_info_class_init, 0, G_TYPE_FLAG_NONE },
307 : : { GI_INFO_TYPE_TYPE, "GITypeInfo", sizeof (GITypeInfo), gi_type_info_class_init, 0, G_TYPE_FLAG_NONE },
308 : : { GI_INFO_TYPE_UNRESOLVED, "GIUnresolvedInfo", sizeof (GIUnresolvedInfo), gi_unresolved_info_class_init, 0, G_TYPE_FLAG_NONE },
309 : : };
310 : :
311 [ + + ]: 180 : for (size_t i = 0; i < G_N_ELEMENTS (types); i++)
312 : : {
313 : : GType registered_type, parent_type;
314 : :
315 [ + + ]: 171 : parent_type = (types[i].parent_info_type == 0) ? GI_TYPE_BASE_INFO : gi_base_info_types[types[i].parent_info_type];
316 : 171 : g_assert (parent_type != G_TYPE_INVALID);
317 : :
318 : 171 : registered_type = gi_base_info_type_register_static (g_intern_static_string (types[i].type_name),
319 : 171 : types[i].instance_size,
320 : 171 : types[i].class_init,
321 : : parent_type,
322 : 171 : types[i].type_flags);
323 : 171 : gi_base_info_types[types[i].info_type] = registered_type;
324 : : }
325 : :
326 : 9 : g_once_init_leave (®ister_types_once, 1);
327 : : }
328 : 7231 : }
329 : :
330 : : /* info creation */
331 : : GIBaseInfo *
332 : 2991 : gi_info_new_full (GIInfoType type,
333 : : GIRepository *repository,
334 : : GIBaseInfo *container,
335 : : GITypelib *typelib,
336 : : uint32_t offset)
337 : : {
338 : : GIRealInfo *info;
339 : :
340 : 2991 : g_return_val_if_fail (container != NULL || repository != NULL, NULL);
341 : 2991 : g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
342 : : g_return_val_if_fail (offset <= G_MAXUINT32, NULL);
343 : :
344 : 2991 : gi_base_info_init_types ();
345 : 2991 : g_assert (gi_base_info_types[type] != G_TYPE_INVALID);
346 : 2991 : info = (GIRealInfo *) g_type_create_instance (gi_base_info_types[type]);
347 : :
348 : 2991 : info->typelib = typelib;
349 : 2991 : info->offset = offset;
350 : :
351 [ + + ]: 2991 : if (container)
352 : 992 : info->container = container;
353 [ + + + - ]: 2991 : if (container && container->ref_count != INVALID_REFCOUNT)
354 : 992 : gi_base_info_ref (info->container);
355 : :
356 : : /* Don’t keep a strong ref, since the repository keeps a cache of #GIBaseInfos
357 : : * and holds refs on them. If we kept a ref here, there’d be a cycle.
358 : : * Don’t keep a weak ref either, as that would make creating/destroying a
359 : : * #GIBaseInfo noticeably more expensive, and infos are performance critical
360 : : * for bindings.
361 : : * As stated in the documentation, the mitigation here is to require the user
362 : : * to keep the #GIRepository alive longer than any of its #GIBaseInfos. */
363 : 2991 : info->repository = repository;
364 : :
365 : 2991 : return (GIBaseInfo*)info;
366 : : }
367 : :
368 : : /**
369 : : * gi_base_info_new:
370 : : * @type: type of the info to create
371 : : * @container: (nullable): info which contains this one
372 : : * @typelib: typelib containing the info
373 : : * @offset: offset of the info within @typelib, in bytes
374 : : *
375 : : * Create a new #GIBaseInfo representing an object of the given @type from
376 : : * @offset of @typelib.
377 : : *
378 : : * Returns: (transfer full): The new #GIBaseInfo, unref with
379 : : * [method@GIRepository.BaseInfo.unref]
380 : : * Since: 2.80
381 : : */
382 : : GIBaseInfo *
383 : 992 : gi_base_info_new (GIInfoType type,
384 : : GIBaseInfo *container,
385 : : GITypelib *typelib,
386 : : size_t offset)
387 : : {
388 : 992 : return gi_info_new_full (type, ((GIRealInfo*)container)->repository, container, typelib, offset);
389 : : }
390 : :
391 : : /*< private >
392 : : * gi_info_init:
393 : : * @info: (out caller-allocates): caller-allocated #GIRealInfo to populate
394 : : * @type: type of the info to create
395 : : * @repository: repository the info is in
396 : : * @container: (nullable): info which contains this one
397 : : * @typelib: typelib containing the info
398 : : * @offset: offset of the info within @typelib, in bytes
399 : : *
400 : : * Initialise a stack-allocated #GIBaseInfo representing an object of the given
401 : : * @type from @offset of @typelib.
402 : : *
403 : : * Since: 2.80
404 : : */
405 : : void
406 : 12 : gi_info_init (GIRealInfo *info,
407 : : GType type,
408 : : GIRepository *repository,
409 : : GIBaseInfo *container,
410 : : GITypelib *typelib,
411 : : uint32_t offset)
412 : : {
413 : 12 : memset (info, 0, sizeof (GIRealInfo));
414 : :
415 : : /* Evil setup of a stack allocated #GTypeInstance. This is not something it’s
416 : : * really designed to do.
417 : : *
418 : : * This function *must* be kept in sync with gi_base_info_init(), which is
419 : : * the equivalent function for dynamically allocated types. */
420 : 12 : info->parent_instance.g_class = g_type_class_ref (type);
421 : :
422 : : /* g_type_create_instance() calls the #GInstanceInitFunc for each of the
423 : : * parent types, down to (and including) @type. We don’t need to do that, as
424 : : * #GIBaseInfo is fundamental so doesn’t have a parent type, the instance init
425 : : * function for #GIBaseInfo is gi_base_info_init() (which only sets the
426 : : * refcount, which we already do here), and subtypes of #GIBaseInfo don’t have
427 : : * instance init functions (see gi_base_info_type_register_static()). */
428 : :
429 : : /* Invalid refcount used to flag stack-allocated infos */
430 : 12 : info->ref_count = INVALID_REFCOUNT;
431 : 12 : info->typelib = typelib;
432 : 12 : info->offset = offset;
433 : :
434 [ + - ]: 12 : if (container)
435 : 12 : info->container = container;
436 : :
437 : 12 : g_assert (GI_IS_REPOSITORY (repository));
438 : 12 : info->repository = repository;
439 : 12 : }
440 : :
441 : : /**
442 : : * gi_base_info_clear:
443 : : * @info: (type GIRepository.BaseInfo): a #GIBaseInfo
444 : : *
445 : : * Clears memory allocated internally by a stack-allocated
446 : : * [type@GIRepository.BaseInfo].
447 : : *
448 : : * This does not deallocate the [type@GIRepository.BaseInfo] struct itself. It
449 : : * does clear the struct to zero so that calling this function subsequent times
450 : : * on the same struct is a no-op.
451 : : *
452 : : * This must only be called on stack-allocated [type@GIRepository.BaseInfo]s.
453 : : * Use [method@GIRepository.BaseInfo.unref] for heap-allocated ones.
454 : : *
455 : : * Since: 2.80
456 : : */
457 : : void
458 : 17 : gi_base_info_clear (void *info)
459 : : {
460 : 17 : GIBaseInfo *rinfo = (GIBaseInfo *) info;
461 : :
462 : : /* If @info is zero-filled, do nothing. This allows gi_base_info_clear() to be
463 : : * used with g_auto(). */
464 [ + + ]: 17 : if (rinfo->ref_count == 0)
465 : 5 : return;
466 : :
467 : 12 : g_return_if_fail (GI_IS_BASE_INFO (rinfo));
468 : :
469 : 12 : g_assert (rinfo->ref_count == INVALID_REFCOUNT);
470 : :
471 : 12 : GI_BASE_INFO_GET_CLASS (info)->finalize (rinfo);
472 : :
473 : 12 : g_type_class_unref (rinfo->parent_instance.g_class);
474 : :
475 : 12 : memset (rinfo, 0, sizeof (*rinfo));
476 : : }
477 : :
478 : : GIBaseInfo *
479 : 7 : gi_info_from_entry (GIRepository *repository,
480 : : GITypelib *typelib,
481 : : uint16_t index)
482 : : {
483 : : GIBaseInfo *result;
484 : 7 : DirEntry *entry = gi_typelib_get_dir_entry (typelib, index);
485 : :
486 [ + - ]: 7 : if (entry->local)
487 : 7 : result = gi_info_new_full (gi_typelib_blob_type_to_info_type (entry->blob_type),
488 : : repository, NULL, typelib, entry->offset);
489 : : else
490 : : {
491 : 0 : const char *namespace = gi_typelib_get_string (typelib, entry->offset);
492 : 0 : const char *name = gi_typelib_get_string (typelib, entry->name);
493 : :
494 : 0 : result = gi_repository_find_by_name (repository, namespace, name);
495 [ # # ]: 0 : if (result == NULL)
496 : : {
497 : : GIUnresolvedInfo *unresolved;
498 : :
499 : 0 : unresolved = (GIUnresolvedInfo *) gi_info_new_full (GI_INFO_TYPE_UNRESOLVED,
500 : : repository,
501 : : NULL,
502 : : typelib,
503 : : entry->offset);
504 : :
505 : 0 : unresolved->name = name;
506 : 0 : unresolved->namespace = namespace;
507 : :
508 : 0 : return (GIBaseInfo *)unresolved;
509 : : }
510 : 0 : return (GIBaseInfo *)result;
511 : : }
512 : :
513 : 7 : return (GIBaseInfo *)result;
514 : : }
515 : :
516 : : GITypeInfo *
517 : 13 : gi_type_info_new (GIBaseInfo *container,
518 : : GITypelib *typelib,
519 : : uint32_t offset)
520 : : {
521 : 13 : SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
522 : :
523 : 13 : return (GITypeInfo *) gi_base_info_new (GI_INFO_TYPE_TYPE, container, typelib,
524 [ + + - + ]: 13 : (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
525 : : }
526 : :
527 : : /*< private >
528 : : * gi_type_info_init:
529 : : * @info: (out caller-allocates): caller-allocated #GITypeInfo to populate
530 : : * @container: (nullable): info which contains this one
531 : : * @typelib: typelib containing the info
532 : : * @offset: offset of the info within @typelib, in bytes
533 : : *
534 : : * Initialise a stack-allocated #GITypeInfo representing an object of type
535 : : * [type@GIRepository.TypeInfo] from @offset of @typelib.
536 : : *
537 : : * This is a specialised form of [func@GIRepository.info_init] for type
538 : : * information.
539 : : *
540 : : * Since: 2.80
541 : : */
542 : : void
543 : 7 : gi_type_info_init (GITypeInfo *info,
544 : : GIBaseInfo *container,
545 : : GITypelib *typelib,
546 : : uint32_t offset)
547 : : {
548 : 7 : GIRealInfo *rinfo = (GIRealInfo*)container;
549 : 7 : SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
550 : :
551 : 7 : gi_info_init ((GIRealInfo*)info, GI_TYPE_TYPE_INFO, rinfo->repository, container, typelib,
552 [ + + - + ]: 7 : (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
553 : 7 : }
554 : :
555 : : /* GIBaseInfo functions */
556 : :
557 : : /**
558 : : * GIBaseInfo:
559 : : *
560 : : * `GIBaseInfo` is the common base struct of all other Info structs
561 : : * accessible through the [class@GIRepository.Repository] API.
562 : : *
563 : : * All info structures can be cast to a `GIBaseInfo`, for instance:
564 : : *
565 : : * ```c
566 : : * GIFunctionInfo *function_info = …;
567 : : * GIBaseInfo *info = (GIBaseInfo *) function_info;
568 : : * ```
569 : : *
570 : : * Most [class@GIRepository.Repository] APIs returning a `GIBaseInfo` are
571 : : * actually creating a new struct; in other words,
572 : : * [method@GIRepository.BaseInfo.unref] has to be called when done accessing the
573 : : * data.
574 : : *
575 : : * `GIBaseInfo` structuress are normally accessed by calling either
576 : : * [method@GIRepository.Repository.find_by_name],
577 : : * [method@GIRepository.Repository.find_by_gtype] or
578 : : * [method@GIRepository.get_info].
579 : : *
580 : : * ```c
581 : : * GIBaseInfo *button_info =
582 : : * gi_repository_find_by_name (NULL, "Gtk", "Button");
583 : : *
584 : : * // use button_info…
585 : : *
586 : : * gi_base_info_unref (button_info);
587 : : * ```
588 : : *
589 : : * Since: 2.80
590 : : */
591 : :
592 : : /**
593 : : * gi_base_info_ref:
594 : : * @info: (type GIRepository.BaseInfo): a #GIBaseInfo
595 : : *
596 : : * Increases the reference count of @info.
597 : : *
598 : : * Returns: (transfer full): the same @info.
599 : : * Since: 2.80
600 : : */
601 : : GIBaseInfo *
602 : 998 : gi_base_info_ref (void *info)
603 : : {
604 : 998 : GIRealInfo *rinfo = (GIRealInfo*)info;
605 : :
606 : 998 : g_return_val_if_fail (GI_IS_BASE_INFO (info), NULL);
607 : :
608 : 998 : g_assert (rinfo->ref_count != INVALID_REFCOUNT);
609 : 998 : g_atomic_ref_count_inc (&rinfo->ref_count);
610 : :
611 : 998 : return info;
612 : : }
613 : :
614 : : /**
615 : : * gi_base_info_unref:
616 : : * @info: (type GIRepository.BaseInfo) (transfer full): a #GIBaseInfo
617 : : *
618 : : * Decreases the reference count of @info. When its reference count
619 : : * drops to 0, the info is freed.
620 : : *
621 : : * This must not be called on stack-allocated [type@GIRepository.BaseInfo]s —
622 : : * use [method@GIRepository.BaseInfo.clear] for that.
623 : : *
624 : : * Since: 2.80
625 : : */
626 : : void
627 : 3989 : gi_base_info_unref (void *info)
628 : : {
629 : 3989 : GIRealInfo *rinfo = (GIRealInfo*)info;
630 : :
631 : 3989 : g_return_if_fail (GI_IS_BASE_INFO (info));
632 : :
633 : 3989 : g_assert (rinfo->ref_count > 0 && rinfo->ref_count != INVALID_REFCOUNT);
634 : :
635 [ + + ]: 3989 : if (g_atomic_ref_count_dec (&rinfo->ref_count))
636 : : {
637 : 2991 : GI_BASE_INFO_GET_CLASS (info)->finalize (info);
638 : 2991 : g_type_free_instance ((GTypeInstance *) info);
639 : : }
640 : : }
641 : :
642 : : /**
643 : : * gi_base_info_get_info_type:
644 : : * @info: a #GIBaseInfo
645 : : *
646 : : * Obtain the info type of the `GIBaseInfo`.
647 : : *
648 : : * Returns: the info type of @info
649 : : * Since: 2.80
650 : : */
651 : : GIInfoType
652 : 113 : gi_base_info_get_info_type (GIBaseInfo *info)
653 : : {
654 : 113 : return GI_BASE_INFO_GET_CLASS (info)->info_type;
655 : : }
656 : :
657 : : /**
658 : : * gi_base_info_get_name:
659 : : * @info: a #GIBaseInfo
660 : : *
661 : : * Obtain the name of the @info.
662 : : *
663 : : * What the name represents depends on the type of the
664 : : * @info. For instance for [class@GIRepository.FunctionInfo] it is the name of
665 : : * the function.
666 : : *
667 : : * Returns: (nullable): the name of @info or `NULL` if it lacks a name.
668 : : * Since: 2.80
669 : : */
670 : : const char *
671 : 48 : gi_base_info_get_name (GIBaseInfo *info)
672 : : {
673 : 48 : GIRealInfo *rinfo = (GIRealInfo*)info;
674 : 48 : g_assert (rinfo->ref_count > 0);
675 [ + - + - : 48 : switch (gi_base_info_get_info_type ((GIBaseInfo *) info))
- + + - +
- ]
676 : : {
677 : 11 : case GI_INFO_TYPE_FUNCTION:
678 : : case GI_INFO_TYPE_CALLBACK:
679 : : case GI_INFO_TYPE_STRUCT:
680 : : case GI_INFO_TYPE_ENUM:
681 : : case GI_INFO_TYPE_FLAGS:
682 : : case GI_INFO_TYPE_OBJECT:
683 : : case GI_INFO_TYPE_INTERFACE:
684 : : case GI_INFO_TYPE_CONSTANT:
685 : : case GI_INFO_TYPE_UNION:
686 : : {
687 : 11 : CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
688 : :
689 : 11 : return gi_typelib_get_string (rinfo->typelib, blob->name);
690 : : }
691 : : break;
692 : :
693 : 0 : case GI_INFO_TYPE_VALUE:
694 : : {
695 : 0 : ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
696 : :
697 : 0 : return gi_typelib_get_string (rinfo->typelib, blob->name);
698 : : }
699 : : break;
700 : :
701 : 3 : case GI_INFO_TYPE_SIGNAL:
702 : : {
703 : 3 : SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
704 : :
705 : 3 : return gi_typelib_get_string (rinfo->typelib, blob->name);
706 : : }
707 : : break;
708 : :
709 : 0 : case GI_INFO_TYPE_PROPERTY:
710 : : {
711 : 0 : PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
712 : :
713 : 0 : return gi_typelib_get_string (rinfo->typelib, blob->name);
714 : : }
715 : : break;
716 : :
717 : 0 : case GI_INFO_TYPE_VFUNC:
718 : : {
719 : 0 : VFuncBlob *blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
720 : :
721 : 0 : return gi_typelib_get_string (rinfo->typelib, blob->name);
722 : : }
723 : : break;
724 : :
725 : 31 : case GI_INFO_TYPE_FIELD:
726 : : {
727 : 31 : FieldBlob *blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
728 : :
729 : 31 : return gi_typelib_get_string (rinfo->typelib, blob->name);
730 : : }
731 : : break;
732 : :
733 : 2 : case GI_INFO_TYPE_ARG:
734 : : {
735 : 2 : ArgBlob *blob = (ArgBlob *)&rinfo->typelib->data[rinfo->offset];
736 : :
737 : 2 : return gi_typelib_get_string (rinfo->typelib, blob->name);
738 : : }
739 : : break;
740 : 0 : case GI_INFO_TYPE_UNRESOLVED:
741 : : {
742 : 0 : GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
743 : :
744 : 0 : return unresolved->name;
745 : : }
746 : : break;
747 : 1 : case GI_INFO_TYPE_TYPE:
748 : 1 : return NULL;
749 : 0 : default: ;
750 : : g_assert_not_reached ();
751 : : /* unnamed */
752 : : }
753 : :
754 : : return NULL;
755 : : }
756 : :
757 : : /**
758 : : * gi_base_info_get_namespace:
759 : : * @info: a #GIBaseInfo
760 : : *
761 : : * Obtain the namespace of @info.
762 : : *
763 : : * Returns: the namespace
764 : : * Since: 2.80
765 : : */
766 : : const char *
767 : 3 : gi_base_info_get_namespace (GIBaseInfo *info)
768 : : {
769 : 3 : GIRealInfo *rinfo = (GIRealInfo*) info;
770 : 3 : Header *header = (Header *)rinfo->typelib->data;
771 : :
772 : 3 : g_assert (rinfo->ref_count > 0);
773 : :
774 [ - + ]: 3 : if (gi_base_info_get_info_type (info) == GI_INFO_TYPE_UNRESOLVED)
775 : : {
776 : 0 : GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
777 : :
778 : 0 : return unresolved->namespace;
779 : : }
780 : :
781 : 3 : return gi_typelib_get_string (rinfo->typelib, header->namespace);
782 : : }
783 : :
784 : : /**
785 : : * gi_base_info_is_deprecated:
786 : : * @info: a #GIBaseInfo
787 : : *
788 : : * Obtain whether the @info is represents a metadata which is
789 : : * deprecated.
790 : : *
791 : : * Returns: `TRUE` if deprecated
792 : : * Since: 2.80
793 : : */
794 : : gboolean
795 : 0 : gi_base_info_is_deprecated (GIBaseInfo *info)
796 : : {
797 : 0 : GIRealInfo *rinfo = (GIRealInfo*) info;
798 [ # # # # : 0 : switch (gi_base_info_get_info_type ((GIBaseInfo *) info))
# ]
799 : : {
800 : 0 : case GI_INFO_TYPE_FUNCTION:
801 : : case GI_INFO_TYPE_CALLBACK:
802 : : case GI_INFO_TYPE_STRUCT:
803 : : case GI_INFO_TYPE_ENUM:
804 : : case GI_INFO_TYPE_FLAGS:
805 : : case GI_INFO_TYPE_OBJECT:
806 : : case GI_INFO_TYPE_INTERFACE:
807 : : case GI_INFO_TYPE_CONSTANT:
808 : : {
809 : 0 : CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
810 : :
811 : 0 : return blob->deprecated;
812 : : }
813 : : break;
814 : :
815 : 0 : case GI_INFO_TYPE_VALUE:
816 : : {
817 : 0 : ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
818 : :
819 : 0 : return blob->deprecated;
820 : : }
821 : : break;
822 : :
823 : 0 : case GI_INFO_TYPE_SIGNAL:
824 : : {
825 : 0 : SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
826 : :
827 : 0 : return blob->deprecated;
828 : : }
829 : : break;
830 : :
831 : 0 : case GI_INFO_TYPE_PROPERTY:
832 : : {
833 : 0 : PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
834 : :
835 : 0 : return blob->deprecated;
836 : : }
837 : : break;
838 : :
839 : 0 : case GI_INFO_TYPE_VFUNC:
840 : : case GI_INFO_TYPE_FIELD:
841 : : case GI_INFO_TYPE_ARG:
842 : : case GI_INFO_TYPE_TYPE:
843 : : default: ;
844 : : /* no deprecation flag for these */
845 : : }
846 : :
847 : 0 : return FALSE;
848 : : }
849 : :
850 : : /**
851 : : * gi_base_info_get_attribute:
852 : : * @info: a #GIBaseInfo
853 : : * @name: a freeform string naming an attribute
854 : : *
855 : : * Retrieve an arbitrary attribute associated with this node.
856 : : *
857 : : * Returns: (nullable): The value of the attribute, or `NULL` if no such
858 : : * attribute exists
859 : : * Since: 2.80
860 : : */
861 : : const char *
862 : 897 : gi_base_info_get_attribute (GIBaseInfo *info,
863 : : const char *name)
864 : : {
865 : 897 : GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT;
866 : : const char *curname, *curvalue;
867 [ + - ]: 897 : while (gi_base_info_iterate_attributes (info, &iter, &curname, &curvalue))
868 : : {
869 [ + - ]: 897 : if (strcmp (name, curname) == 0)
870 : 897 : return (const char *) curvalue;
871 : : }
872 : :
873 : 0 : return NULL;
874 : : }
875 : :
876 : : static int
877 : 7756 : cmp_attribute (const void *av,
878 : : const void *bv)
879 : : {
880 : 7756 : const AttributeBlob *a = av;
881 : 7756 : const AttributeBlob *b = bv;
882 : :
883 [ + + ]: 7756 : if (a->offset < b->offset)
884 : 3687 : return -1;
885 [ + + ]: 4069 : else if (a->offset == b->offset)
886 : 897 : return 0;
887 : : else
888 : 3172 : return 1;
889 : : }
890 : :
891 : : /*< private >
892 : : * _attribute_blob_find_first:
893 : : * @GIBaseInfo: A #GIBaseInfo.
894 : : * @blob_offset: The offset for the blob to find the first attribute for.
895 : : *
896 : : * Searches for the first #AttributeBlob for @blob_offset and returns
897 : : * it if found.
898 : : *
899 : : * Returns: (transfer none): A pointer to #AttributeBlob or `NULL` if not found.
900 : : * Since: 2.80
901 : : */
902 : : AttributeBlob *
903 : 899 : _attribute_blob_find_first (GIBaseInfo *info,
904 : : uint32_t blob_offset)
905 : : {
906 : 899 : GIRealInfo *rinfo = (GIRealInfo *) info;
907 : 899 : Header *header = (Header *)rinfo->typelib->data;
908 : : AttributeBlob blob, *first, *res, *previous;
909 : :
910 : 899 : blob.offset = blob_offset;
911 : :
912 : 899 : first = (AttributeBlob *) &rinfo->typelib->data[header->attributes];
913 : :
914 : 899 : res = bsearch (&blob, first, header->n_attributes,
915 : 899 : header->attribute_blob_size, cmp_attribute);
916 : :
917 [ + + ]: 899 : if (res == NULL)
918 : 2 : return NULL;
919 : :
920 : 897 : previous = res - 1;
921 [ + + - + ]: 897 : while (previous >= first && previous->offset == blob_offset)
922 : : {
923 : 0 : res = previous;
924 : 0 : previous = res - 1;
925 : : }
926 : :
927 : 897 : return res;
928 : : }
929 : :
930 : : /**
931 : : * gi_base_info_iterate_attributes:
932 : : * @info: a #GIBaseInfo
933 : : * @iterator: (inout): a [type@GIRepository.AttributeIter] structure, must be
934 : : * initialized; see below
935 : : * @name: (out) (transfer none): Returned name, must not be freed
936 : : * @value: (out) (transfer none): Returned name, must not be freed
937 : : *
938 : : * Iterate over all attributes associated with this node.
939 : : *
940 : : * The iterator structure is typically stack allocated, and must have its first
941 : : * member initialized to `NULL`. Attributes are arbitrary namespaced key–value
942 : : * pairs which can be attached to almost any item. They are intended for use
943 : : * by software higher in the toolchain than bindings, and are distinct from
944 : : * normal GIR annotations.
945 : : *
946 : : * Both the @name and @value should be treated as constants
947 : : * and must not be freed.
948 : : *
949 : : * ```c
950 : : * void
951 : : * print_attributes (GIBaseInfo *info)
952 : : * {
953 : : * GIAttributeIter iter = GI_ATTRIBUTE_ITER_INIT;
954 : : * const char *name;
955 : : * const char *value;
956 : : * while (gi_base_info_iterate_attributes (info, &iter, &name, &value))
957 : : * {
958 : : * g_print ("attribute name: %s value: %s", name, value);
959 : : * }
960 : : * }
961 : : * ```
962 : : *
963 : : * Returns: `TRUE` if there are more attributes
964 : : * Since: 2.80
965 : : */
966 : : gboolean
967 : 897 : gi_base_info_iterate_attributes (GIBaseInfo *info,
968 : : GIAttributeIter *iterator,
969 : : const char **name,
970 : : const char **value)
971 : : {
972 : 897 : GIRealInfo *rinfo = (GIRealInfo *)info;
973 : 897 : Header *header = (Header *)rinfo->typelib->data;
974 : : AttributeBlob *next, *after;
975 : :
976 : 897 : after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
977 : 897 : header->n_attributes * header->attribute_blob_size];
978 : :
979 [ - + ]: 897 : if (iterator->data != NULL)
980 : 0 : next = (AttributeBlob *) iterator->data;
981 : : else
982 : 897 : next = _attribute_blob_find_first (info, rinfo->offset);
983 : :
984 [ + - + - : 897 : if (next == NULL || next->offset != rinfo->offset || next >= after)
- + ]
985 : 0 : return FALSE;
986 : :
987 : 897 : *name = gi_typelib_get_string (rinfo->typelib, next->name);
988 : 897 : *value = gi_typelib_get_string (rinfo->typelib, next->value);
989 : 897 : iterator->data = next + 1;
990 : :
991 : 897 : return TRUE;
992 : : }
993 : :
994 : : /**
995 : : * gi_base_info_get_container:
996 : : * @info: a #GIBaseInfo
997 : : *
998 : : * Obtain the container of the @info.
999 : : *
1000 : : * The container is the parent `GIBaseInfo`. For instance, the parent of a
1001 : : * [class@GIRepository.FunctionInfo] is an [class@GIRepository.ObjectInfo] or
1002 : : * [class@GIRepository.InterfaceInfo].
1003 : : *
1004 : : * Returns: (transfer none): the container
1005 : : * Since: 2.80
1006 : : */
1007 : : GIBaseInfo *
1008 : 0 : gi_base_info_get_container (GIBaseInfo *info)
1009 : : {
1010 : 0 : return ((GIRealInfo*)info)->container;
1011 : : }
1012 : :
1013 : : /**
1014 : : * gi_base_info_get_typelib:
1015 : : * @info: a #GIBaseInfo
1016 : : *
1017 : : * Obtain the typelib this @info belongs to
1018 : : *
1019 : : * Returns: (transfer none): the typelib
1020 : : * Since: 2.80
1021 : : */
1022 : : GITypelib *
1023 : 3 : gi_base_info_get_typelib (GIBaseInfo *info)
1024 : : {
1025 : 3 : return ((GIRealInfo*)info)->typelib;
1026 : : }
1027 : :
1028 : : /**
1029 : : * gi_base_info_equal:
1030 : : * @info1: a #GIBaseInfo
1031 : : * @info2: a #GIBaseInfo
1032 : : *
1033 : : * Compare two `GIBaseInfo`s.
1034 : : *
1035 : : * Using pointer comparison is not practical since many functions return
1036 : : * different instances of `GIBaseInfo` that refers to the same part of the
1037 : : * TypeLib; use this function instead to do `GIBaseInfo` comparisons.
1038 : : *
1039 : : * Returns: `TRUE` if and only if @info1 equals @info2.
1040 : : * Since: 2.80
1041 : : */
1042 : : gboolean
1043 : 0 : gi_base_info_equal (GIBaseInfo *info1, GIBaseInfo *info2)
1044 : : {
1045 : : /* Compare the TypeLib pointers, which are mmapped. */
1046 : 0 : GIRealInfo *rinfo1 = (GIRealInfo*)info1;
1047 : 0 : GIRealInfo *rinfo2 = (GIRealInfo*)info2;
1048 : 0 : return rinfo1->typelib->data + rinfo1->offset == rinfo2->typelib->data + rinfo2->offset;
1049 : : }
|