1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Base struct implementation
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008,2009 Red Hat, Inc.
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.
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.
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.
27 #include <glib-object.h>
29 #include "gitypelib-internal.h"
30 #include "girepository-private.h"
32 #define INVALID_REFCOUNT 0x7FFFFFFF
34 /* GBoxed registration of BaseInfo. */
36 g_base_info_gtype_get_type (void)
38 static GType our_type = 0;
42 g_boxed_type_register_static ("GIBaseInfo",
43 (GBoxedCopyFunc) g_base_info_ref,
44 (GBoxedFreeFunc) g_base_info_unref);
51 _g_info_new_full (GIInfoType type,
52 GIRepository *repository,
53 GIBaseInfo *container,
59 g_return_val_if_fail (container != NULL || repository != NULL, NULL);
61 info = g_slice_new (GIRealInfo);
63 _g_info_init (info, type, repository, container, typelib, offset);
66 if (container && ((GIRealInfo *) container)->ref_count != INVALID_REFCOUNT)
67 g_base_info_ref (info->container);
69 g_object_ref (info->repository);
71 return (GIBaseInfo*)info;
75 g_info_new (GIInfoType type,
76 GIBaseInfo *container,
80 return _g_info_new_full (type, ((GIRealInfo*)container)->repository, container, typelib, offset);
84 _g_info_init (GIRealInfo *info,
86 GIRepository *repository,
87 GIBaseInfo *container,
91 memset (info, 0, sizeof (GIRealInfo));
93 /* Invalid refcount used to flag stack-allocated infos */
94 info->ref_count = INVALID_REFCOUNT;
97 info->typelib = typelib;
98 info->offset = offset;
101 info->container = container;
103 g_assert (G_IS_IREPOSITORY (repository));
104 info->repository = repository;
108 _g_info_from_entry (GIRepository *repository,
113 DirEntry *entry = g_typelib_get_dir_entry (typelib, index);
116 result = _g_info_new_full (entry->blob_type, repository, NULL, typelib, entry->offset);
119 const gchar *namespace = g_typelib_get_string (typelib, entry->offset);
120 const gchar *name = g_typelib_get_string (typelib, entry->name);
122 result = g_irepository_find_by_name (repository, namespace, name);
125 GIUnresolvedInfo *unresolved;
127 unresolved = g_slice_new0 (GIUnresolvedInfo);
129 unresolved->type = GI_INFO_TYPE_UNRESOLVED;
130 unresolved->ref_count = 1;
131 unresolved->repository = g_object_ref (repository);
132 unresolved->container = NULL;
133 unresolved->name = name;
134 unresolved->namespace = namespace;
136 return (GIBaseInfo *)unresolved;
138 return (GIBaseInfo *)result;
141 return (GIBaseInfo *)result;
145 _g_type_info_new (GIBaseInfo *container,
149 SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
151 return (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib,
152 (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
156 _g_type_info_init (GIBaseInfo *info,
157 GIBaseInfo *container,
161 GIRealInfo *rinfo = (GIRealInfo*)container;
162 SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
164 _g_info_init ((GIRealInfo*)info, GI_INFO_TYPE_TYPE, rinfo->repository, container, typelib,
165 (type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
168 /* GIBaseInfo functions */
172 * @Short_description: Base struct for all GITypelib structs
175 * GIBaseInfo is the common base struct of all other *Info structs
176 * accessible through the #GIRepository API.
177 * All other structs can be casted to a #GIBaseInfo, for instance:
179 * <title>Casting a #GIFunctionInfo to #GIBaseInfo</title>
181 * GIFunctionInfo *function_info = ...;
182 * GIBaseInfo *info = (GIBaseInfo*)function_info;
185 * Most #GIRepository APIs returning a #GIBaseInfo is actually creating a new struct, in other
186 * words, g_base_info_unref() has to be called when done accessing the data.
187 * GIBaseInfos are normally accessed by calling either
188 * g_irepository_find_by_name(), g_irepository_find_by_gtype() or g_irepository_get_info().
191 * <title>Getting the Button of the Gtk typelib</title>
193 * GIBaseInfo *button_info = g_irepository_find_by_name(NULL, "Gtk", "Button");
194 * ... use button_info ...
195 * g_base_info_unref(button_info);
199 * <refsect1 id="gi-gibaseinfo.struct-hierarchy" role="struct_hierarchy">
200 * <title role="struct_hierarchy.title">Struct hierarchy</title>
203 * +----<link linkend="gi-GIArgInfo">GIArgInfo</link>
204 * +----<link linkend="gi-GICallableInfo">GICallableInfo</link>
205 * +----<link linkend="gi-GIConstantInfo">GIConstantInfo</link>
206 * +----<link linkend="gi-GIFieldInfo">GIFieldInfo</link>
207 * +----<link linkend="gi-GIPropertyInfo">GIPropertyInfo</link>
208 * +----<link linkend="gi-GIRegisteredTypeInfo">GIRegisteredTypeInfo</link>
209 * +----<link linkend="gi-GITypeInfo">GITypeInfo</link>
216 * g_base_info_ref: (skip)
217 * @info: a #GIBaseInfo
219 * Increases the reference count of @info.
221 * Returns: the same @info.
224 g_base_info_ref (GIBaseInfo *info)
226 GIRealInfo *rinfo = (GIRealInfo*)info;
228 g_assert (rinfo->ref_count != INVALID_REFCOUNT);
229 ((GIRealInfo*)info)->ref_count++;
235 * g_base_info_unref: (skip)
236 * @info: a #GIBaseInfo
238 * Decreases the reference count of @info. When its reference count
239 * drops to 0, the info is freed.
242 g_base_info_unref (GIBaseInfo *info)
244 GIRealInfo *rinfo = (GIRealInfo*)info;
246 g_assert (rinfo->ref_count > 0 && rinfo->ref_count != INVALID_REFCOUNT);
249 if (!rinfo->ref_count)
251 if (rinfo->container && ((GIRealInfo *) rinfo->container)->ref_count != INVALID_REFCOUNT)
252 g_base_info_unref (rinfo->container);
254 if (rinfo->repository)
255 g_object_unref (rinfo->repository);
257 if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
258 g_slice_free (GIUnresolvedInfo, (GIUnresolvedInfo *) rinfo);
260 g_slice_free (GIRealInfo, rinfo);
265 * g_base_info_get_type:
266 * @info: a #GIBaseInfo
268 * Obtain the info type of the GIBaseInfo.
270 * Returns: the info type of @info
273 g_base_info_get_type (GIBaseInfo *info)
276 return ((GIRealInfo*)info)->type;
280 * g_base_info_get_name:
281 * @info: a #GIBaseInfo
283 * Obtain the name of the @info. What the name represents depends on
284 * the #GIInfoType of the @info. For instance for #GIFunctionInfo it is
285 * the name of the function.
287 * Returns: the name of @info or %NULL if it lacks a name.
290 g_base_info_get_name (GIBaseInfo *info)
292 GIRealInfo *rinfo = (GIRealInfo*)info;
293 g_assert (rinfo->ref_count > 0);
296 case GI_INFO_TYPE_FUNCTION:
297 case GI_INFO_TYPE_CALLBACK:
298 case GI_INFO_TYPE_STRUCT:
299 case GI_INFO_TYPE_BOXED:
300 case GI_INFO_TYPE_ENUM:
301 case GI_INFO_TYPE_FLAGS:
302 case GI_INFO_TYPE_OBJECT:
303 case GI_INFO_TYPE_INTERFACE:
304 case GI_INFO_TYPE_CONSTANT:
305 case GI_INFO_TYPE_INVALID_0:
306 case GI_INFO_TYPE_UNION:
308 CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
310 return g_typelib_get_string (rinfo->typelib, blob->name);
314 case GI_INFO_TYPE_VALUE:
316 ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
318 return g_typelib_get_string (rinfo->typelib, blob->name);
322 case GI_INFO_TYPE_SIGNAL:
324 SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
326 return g_typelib_get_string (rinfo->typelib, blob->name);
330 case GI_INFO_TYPE_PROPERTY:
332 PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
334 return g_typelib_get_string (rinfo->typelib, blob->name);
338 case GI_INFO_TYPE_VFUNC:
340 VFuncBlob *blob = (VFuncBlob *)&rinfo->typelib->data[rinfo->offset];
342 return g_typelib_get_string (rinfo->typelib, blob->name);
346 case GI_INFO_TYPE_FIELD:
348 FieldBlob *blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
350 return g_typelib_get_string (rinfo->typelib, blob->name);
354 case GI_INFO_TYPE_ARG:
356 ArgBlob *blob = (ArgBlob *)&rinfo->typelib->data[rinfo->offset];
358 return g_typelib_get_string (rinfo->typelib, blob->name);
361 case GI_INFO_TYPE_UNRESOLVED:
363 GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
365 return unresolved->name;
368 case GI_INFO_TYPE_TYPE:
370 g_assert_not_reached ();
378 * g_base_info_get_namespace:
379 * @info: a #GIBaseInfo
381 * Obtain the namespace of @info.
383 * Returns: the namespace
386 g_base_info_get_namespace (GIBaseInfo *info)
388 GIRealInfo *rinfo = (GIRealInfo*) info;
389 Header *header = (Header *)rinfo->typelib->data;
391 g_assert (rinfo->ref_count > 0);
393 if (rinfo->type == GI_INFO_TYPE_UNRESOLVED)
395 GIUnresolvedInfo *unresolved = (GIUnresolvedInfo *)info;
397 return unresolved->namespace;
400 return g_typelib_get_string (rinfo->typelib, header->namespace);
404 * g_base_info_is_deprecated:
405 * @info: a #GIBaseInfo
407 * Obtain whether the @info is represents a metadata which is
410 * Returns: %TRUE if deprecated
413 g_base_info_is_deprecated (GIBaseInfo *info)
415 GIRealInfo *rinfo = (GIRealInfo*) info;
418 case GI_INFO_TYPE_FUNCTION:
419 case GI_INFO_TYPE_CALLBACK:
420 case GI_INFO_TYPE_STRUCT:
421 case GI_INFO_TYPE_BOXED:
422 case GI_INFO_TYPE_ENUM:
423 case GI_INFO_TYPE_FLAGS:
424 case GI_INFO_TYPE_OBJECT:
425 case GI_INFO_TYPE_INTERFACE:
426 case GI_INFO_TYPE_CONSTANT:
427 case GI_INFO_TYPE_INVALID_0:
429 CommonBlob *blob = (CommonBlob *)&rinfo->typelib->data[rinfo->offset];
431 return blob->deprecated;
435 case GI_INFO_TYPE_VALUE:
437 ValueBlob *blob = (ValueBlob *)&rinfo->typelib->data[rinfo->offset];
439 return blob->deprecated;
443 case GI_INFO_TYPE_SIGNAL:
445 SignalBlob *blob = (SignalBlob *)&rinfo->typelib->data[rinfo->offset];
447 return blob->deprecated;
451 case GI_INFO_TYPE_PROPERTY:
453 PropertyBlob *blob = (PropertyBlob *)&rinfo->typelib->data[rinfo->offset];
455 return blob->deprecated;
459 case GI_INFO_TYPE_VFUNC:
460 case GI_INFO_TYPE_FIELD:
461 case GI_INFO_TYPE_ARG:
462 case GI_INFO_TYPE_TYPE:
464 /* no deprecation flag for these */
471 * g_base_info_get_attribute:
472 * @info: a #GIBaseInfo
473 * @name: a freeform string naming an attribute
475 * Retrieve an arbitrary attribute associated with this node.
477 * Returns: The value of the attribute, or %NULL if no such attribute exists
480 g_base_info_get_attribute (GIBaseInfo *info,
483 GIAttributeIter iter = { 0, };
484 gchar *curname, *curvalue;
485 while (g_base_info_iterate_attributes (info, &iter, &curname, &curvalue))
487 if (strcmp (name, curname) == 0)
488 return (const gchar*) curvalue;
495 cmp_attribute (const void *av,
498 const AttributeBlob *a = av;
499 const AttributeBlob *b = bv;
501 if (a->offset < b->offset)
503 else if (a->offset == b->offset)
510 * _attribute_blob_find_first:
511 * @GIBaseInfo: A #GIBaseInfo.
512 * @blob_offset: The offset for the blob to find the first attribute for.
514 * Searches for the first #AttributeBlob for @blob_offset and returns
517 * Returns: A pointer to #AttributeBlob or %NULL if not found.
520 _attribute_blob_find_first (GIBaseInfo *info,
523 GIRealInfo *rinfo = (GIRealInfo *) info;
524 Header *header = (Header *)rinfo->typelib->data;
525 AttributeBlob blob, *first, *res, *previous;
527 blob.offset = blob_offset;
529 first = (AttributeBlob *) &rinfo->typelib->data[header->attributes];
531 res = bsearch (&blob, first, header->n_attributes,
532 header->attribute_blob_size, cmp_attribute);
538 while (previous >= first && previous->offset == blob_offset)
548 * g_base_info_iterate_attributes:
549 * @info: a #GIBaseInfo
550 * @iterator: a #GIAttributeIter structure, must be initialized; see below
551 * @name: (out) (transfer none): Returned name, must not be freed
552 * @value: (out) (transfer none): Returned name, must not be freed
554 * Iterate over all attributes associated with this node. The iterator
555 * structure is typically stack allocated, and must have its first
556 * member initialized to %NULL.
558 * Both the @name and @value should be treated as constants
559 * and must not be freed.
562 * <title>Iterating over attributes</title>
565 * print_attributes (GIBaseInfo *info)
567 * GIAttributeIter iter = { 0, };
570 * while (g_base_info_iterate_attributes (info, &iter, &name, &value))
572 * g_print ("attribute name: %s value: %s", name, value);
578 * Returns: %TRUE if there are more attributes
581 g_base_info_iterate_attributes (GIBaseInfo *info,
582 GIAttributeIter *iterator,
586 GIRealInfo *rinfo = (GIRealInfo *)info;
587 Header *header = (Header *)rinfo->typelib->data;
588 AttributeBlob *next, *after;
590 after = (AttributeBlob *) &rinfo->typelib->data[header->attributes +
591 header->n_attributes * header->attribute_blob_size];
593 if (iterator->data != NULL)
594 next = (AttributeBlob *) iterator->data;
596 next = _attribute_blob_find_first (info, rinfo->offset);
598 if (next == NULL || next->offset != rinfo->offset || next >= after)
601 *name = (gchar*) g_typelib_get_string (rinfo->typelib, next->name);
602 *value = (gchar*) g_typelib_get_string (rinfo->typelib, next->value);
603 iterator->data = next + 1;
609 * g_base_info_get_container:
610 * @info: a #GIBaseInfo
612 * Obtain the container of the @info. The container is the parent
613 * GIBaseInfo. For instance, the parent of a #GIFunctionInfo is an
614 * #GIObjectInfo or #GIInterfaceInfo.
616 * Returns: (transfer none): the container
619 g_base_info_get_container (GIBaseInfo *info)
621 return ((GIRealInfo*)info)->container;
625 * g_base_info_get_typelib:
626 * @info: a #GIBaseInfo
628 * Obtain the typelib this @info belongs to
630 * Returns: (transfer none): the typelib.
633 g_base_info_get_typelib (GIBaseInfo *info)
635 return ((GIRealInfo*)info)->typelib;
640 * @info1: a #GIBaseInfo
641 * @info2: a #GIBaseInfo
643 * Compare two #GIBaseInfo.
645 * Using pointer comparison is not practical since many functions return
646 * different instances of #GIBaseInfo that refers to the same part of the
647 * TypeLib; use this function instead to do #GIBaseInfo comparisons.
649 * Returns: %TRUE if and only if @info1 equals @info2.
652 g_base_info_equal (GIBaseInfo *info1, GIBaseInfo *info2)
654 /* Compare the TypeLib pointers, which are mmapped. */
655 GIRealInfo *rinfo1 = (GIRealInfo*)info1;
656 GIRealInfo *rinfo2 = (GIRealInfo*)info2;
657 return rinfo1->typelib->data + rinfo1->offset == rinfo2->typelib->data + rinfo2->offset;