(root)/
glib-2.79.0/
girepository/
gibaseinfo.c
       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 (&register_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 (&register_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  }