glib/girepository/giregisteredtypeinfo.c
Philip Withnall 0fd99a9f16 gibaseinfo: Stop building GIBoxedInfo instances
Instead, add a method on `GIRegisteredTypeInfo` which indicates whether
the registered type is a boxed type. This will return true for
`GIStructInfo` and `GIUnionInfo` instances which are boxed (not all
structs and unions are).

This makes `GIBoxedInfo` redundant, and it’ll be dropped in a following
commit.

---

There are several different things which typelibs need to be able to
represent:
 1. Plain old datatype (POD) structs
 2. POD unions
 3. Structs with a copy func and/or free func
 4. Unions with a copy func and/or free func
 5. Structs which are the ‘GType struct’ for an object or interface (i.e.
    the class or instance or interface struct)
 6. Structs with a copy func and free func *and* boxed GType
 7. Unions with a copy func and free func *and* boxed GType
 8. Boxed GTypes which represent something other than a struct or union

So there’s a lot going on here. In commit
e28078c70cbf4a57c7dbd39626f43f9bd2674145, a lot of this was reworked,
and support was added for boxed unions and boxed ‘others’ (the last item
on the list above).

Since then, support for boxed types other than structs seems to have
atrophied a bit, and the whole lot has got a bit confusing.

It was perhaps less confusing when all the `GIBaseInfo` subclasses were
actually aliases of each other, but now they have subtype relationships,
the position of `GIBoxedInfo` in that type hierarchy has become unclear.
How is it related to `GIStructInfo`, `GIUnionInfo` and
`GIRegisteredTypeInfo`?

Since a boxed type is necessarily a `GIRegisteredTypeInfo`, and the
methods of `GIRegisteredTypeInfo` are all written to allow a `GType` to
be optional, so that `GIStructInfo` and `GIUnionInfo` can safely derive
from it and still be used to represent plain old datatypes without
`GType`s, it makes sense to add a method to `GIRegisteredTypeInfo` to
indicate that the registered type is derived from `G_TYPE_BOXED`.

Accordingly, the things above are now represented in libgirepository’s
type system as:
 1. `GIStructInfo` instance, `GIRegisteredTypeInfo` methods return no
    `GType` info
 2. `GIUnionInfo` instance similarly
 3. `GIStructInfo` instance, `GIRegisteredTypeInfo` methods return no
    `GType` info, `gi_struct_info_get_{copy,free}_function_name()` return
    non-`NULL` values
 4. `GIUnionInfo` instance similarly
 5. `GIStructInfo` instance, `GIRegisteredTypeInfo` methods return no
    `GType` info, `gi_struct_info_is_gtype_struct()` returns true
 6. `GIStructInfo` instance, `GIRegisteredTypeInfo` methods return valid
    `GType` information, `gi_registered_type_info_is_boxed()` returns
    true, `gi_struct_info_get_{copy,free}_function_name()` return
    `NULL` values (because the copy/free functions are hidden inside the
    boxed type registration at runtime)
 7. `GIUnionInfo` instance similarly
 8. Not representable, but could be represented in future by re-adding a
    `GIBoxedInfo` type which derives from `GIRegisteredTypeInfo` and is
    used solely for boxed ‘other’ types, *not* boxed structs or unions

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Fixes: #3245
2024-02-12 13:16:07 +00:00

230 lines
7.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
* GObject introspection: Registered Type implementation
*
* Copyright (C) 2005 Matthias Clasen
* Copyright (C) 2008,2009 Red Hat, Inc.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib.h>
#include <girepository/girepository.h>
#include "gibaseinfo-private.h"
#include "girepository-private.h"
#include "gitypelib-internal.h"
#include "giregisteredtypeinfo.h"
/**
* GIRegisteredTypeInfo:
*
* `GIRegisteredTypeInfo` represents an entity with a [type@GObject.Type]
* associated.
*
* Could be either a [class@GIRepository.EnumInfo],
* [class@GIRepository.InterfaceInfo], [class@GIRepository.ObjectInfo],
* [class@GIRepository.StructInfo] or a [class@GIRepository.UnionInfo].
*
* A registered type info struct has a name and a type function.
*
* To get the name call [method@GIRepository.RegisteredTypeInfo.get_type_name].
* Most users want to call [method@GIRepository.RegisteredTypeInfo.get_g_type]
* and dont worry about the rest of the details.
*
* If the registered type is a subtype of `G_TYPE_BOXED`,
* [method@GIRepository.RegisteredTypeInfo.is_boxed] will return true, and
* [method@GIRepository.RegisteredTypeInfo.get_type_name] is guaranteed to
* return a non-`NULL` value. This is relevant for the
* [class@GIRepository.StructInfo] and [class@GIRepository.UnionInfo]
* subclasses.
*
* Since: 2.80
*/
/**
* gi_registered_type_info_get_type_name:
* @info: a #GIRegisteredTypeInfo
*
* Obtain the type name of the struct within the GObject type system.
*
* This type can be passed to [func@GObject.type_name] to get a
* [type@GObject.Type].
*
* Returns: (nullable): the type name, or `NULL` if unknown
* Since: 2.80
*/
const char *
gi_registered_type_info_get_type_name (GIRegisteredTypeInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
RegisteredTypeBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_REGISTERED_TYPE_INFO (info), NULL);
blob = (RegisteredTypeBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->gtype_name)
return gi_typelib_get_string (rinfo->typelib, blob->gtype_name);
return NULL;
}
/**
* gi_registered_type_info_get_type_init_function_name:
* @info: a #GIRegisteredTypeInfo
*
* Obtain the type init function for @info.
*
* The type init function is the function which will register the
* [type@GObject.Type] within the GObject type system. Usually this is not
* called by language bindings or applications — use
* [method@GIRepository.RegisteredTypeInfo.get_g_type] directly instead.
*
* Returns: (nullable): the symbol name of the type init function, suitable for
* passing into [method@GModule.Module.symbol], or `NULL` if unknown
* Since: 2.80
*/
const char *
gi_registered_type_info_get_type_init_function_name (GIRegisteredTypeInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
RegisteredTypeBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_REGISTERED_TYPE_INFO (info), NULL);
blob = (RegisteredTypeBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->gtype_init)
return gi_typelib_get_string (rinfo->typelib, blob->gtype_init);
return NULL;
}
/**
* gi_registered_type_info_get_g_type:
* @info: a #GIRegisteredTypeInfo
*
* Obtain the [type@GObject.Type] for this registered type.
*
* If there is no type information associated with @info, or the shared library
* which provides the `type_init` function for @info cannot be called, then
* `G_TYPE_NONE` is returned.
*
* Returns: the [type@GObject.Type], or `G_TYPE_NONE` if unknown
* Since: 2.80
*/
GType
gi_registered_type_info_get_g_type (GIRegisteredTypeInfo *info)
{
const char *type_init;
GType (* get_type_func) (void);
GIRealInfo *rinfo = (GIRealInfo*)info;
g_return_val_if_fail (info != NULL, G_TYPE_INVALID);
g_return_val_if_fail (GI_IS_REGISTERED_TYPE_INFO (info), G_TYPE_INVALID);
type_init = gi_registered_type_info_get_type_init_function_name (info);
if (type_init == NULL)
return G_TYPE_NONE;
else if (!strcmp (type_init, "intern"))
/* The special string "intern" is used for some types exposed by libgobject
(that therefore should be always available) */
return g_type_from_name (gi_registered_type_info_get_type_name (info));
get_type_func = NULL;
if (!gi_typelib_symbol (rinfo->typelib,
type_init,
(void**) &get_type_func))
return G_TYPE_NONE;
return (* get_type_func) ();
}
/**
* gi_registered_type_info_is_boxed:
* @info: a #GIRegisteredTypeInfo
*
* Get whether the registered type is a boxed type.
*
* A boxed type is a subtype of the fundamental `G_TYPE_BOXED` type.
* Its a type which has registered a [type@GObject.Type], and which has
* associated copy and free functions.
*
* Most boxed types are `struct`s; some are `union`s; and its possible for a
* boxed type to be neither, but that is currently unsupported by
* libgirepository. Its also possible for a `struct` or `union` to have
* associated copy and/or free functions *without* being a boxed type, by virtue
* of not having registered a [type@GObject.Type].
*
* This function will return false for [type@GObject.Type]s which are not boxed,
* such as classes or interfaces. It will also return false for the `struct`s
* associated with a class or interface, which return true from
* [method@GIRepository.StructInfo.is_gtype_struct].
*
* Returns: true if @info is a boxed type
* Since: 2.80
*/
gboolean
gi_registered_type_info_is_boxed (GIRegisteredTypeInfo *info)
{
GIBaseInfo *base_info = GI_BASE_INFO (info);
const RegisteredTypeBlob *blob;
g_return_val_if_fail (GI_IS_REGISTERED_TYPE_INFO (info), G_TYPE_INVALID);
blob = (const RegisteredTypeBlob *) &base_info->typelib->data[base_info->offset];
if (blob->blob_type == BLOB_TYPE_BOXED)
{
return TRUE;
}
else if (blob->blob_type == BLOB_TYPE_STRUCT)
{
const StructBlob *struct_blob = (const StructBlob *) &base_info->typelib->data[base_info->offset];
return !struct_blob->unregistered;
}
else if (blob->blob_type == BLOB_TYPE_UNION)
{
const UnionBlob *union_blob = (const UnionBlob *) &base_info->typelib->data[base_info->offset];
return !union_blob->unregistered;
}
/* We dont currently support boxed other types (boxed types which arent
* a struct or union. */
return FALSE;
}
void
gi_registered_type_info_class_init (gpointer g_class,
gpointer class_data)
{
GIBaseInfoClass *info_class = g_class;
info_class->info_type = GI_INFO_TYPE_REGISTERED_TYPE;
}