glib/girepository/giobjectinfo.c
Marco Trevisan (Treviño) 19476db825 girepository: Ensure indexed access on members is not overflowing
Even though we expose member access as size_t, a GI info blob can
typically just access to an a number of values that is never bigger
than uint16_t, as that's how the typelib is defined (cfr. typelib
internal header blob sizes and n_* elements).

So let's avoid this to happen by adding a check.
2024-01-16 18:40:42 +01:00

1189 lines
34 KiB
C
Raw 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: Object 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 <glib.h>
#include <girepository/girepository.h>
#include "gibaseinfo-private.h"
#include "girepository-private.h"
#include "gitypelib-internal.h"
#include "giobjectinfo.h"
/**
* GIObjectInfo:
*
* `GIObjectInfo` represents a classed type.
*
* Classed types in [type@GObject.Type] inherit from
* [type@GObject.TypeInstance]; the most common type is [class@GObject.Object].
*
* A `GIObjectInfo` doesnt represent a specific instance of a classed type,
* instead this represent the object type (i.e. the class).
*
* A `GIObjectInfo` has methods, fields, properties, signals, interfaces,
* constants and virtual functions.
*
* Since: 2.80
*/
/**
* gi_object_info_get_field_offset:
* @info: a #GIObjectInfo
* @n: index of queried field
*
* Obtain the offset of the specified field.
*
* Returns: field offset, in bytes
* Since: 2.80
*/
static size_t
gi_object_info_get_field_offset (GIObjectInfo *info,
size_t n)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header = (Header *)rinfo->typelib->data;
ObjectBlob *blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
uint32_t offset;
FieldBlob *field_blob;
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2;
for (unsigned int i = 0; i < n; i++)
{
field_blob = (FieldBlob *)&rinfo->typelib->data[offset];
offset += header->field_blob_size;
if (field_blob->has_embedded_type)
offset += header->callback_blob_size;
}
return offset;
}
/**
* gi_object_info_get_parent:
* @info: a #GIObjectInfo
*
* Obtain the parent of the object type.
*
* Returns: (transfer full) (nullable): The `GIObjectInfo`. Free the struct by
* calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIObjectInfo *
gi_object_info_get_parent (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->parent)
return (GIObjectInfo *) gi_info_from_entry (rinfo->repository,
rinfo->typelib, blob->parent);
else
return NULL;
}
/**
* gi_object_info_get_abstract:
* @info: a #GIObjectInfo
*
* Obtain if the object type is an abstract type, i.e. if it cannot be
* instantiated.
*
* Returns: `TRUE` if the object type is abstract
* Since: 2.80
*/
gboolean
gi_object_info_get_abstract (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), FALSE);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->abstract != 0;
}
/**
* gi_object_info_get_final:
* @info: a #GIObjectInfo
*
* Checks whether the object type is a final type, i.e. if it cannot
* be derived.
*
* Returns: `TRUE` if the object type is final
* Since: 2.80
*/
gboolean
gi_object_info_get_final (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *) info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), FALSE);
blob = (ObjectBlob *) &rinfo->typelib->data[rinfo->offset];
return blob->final_ != 0;
}
/**
* gi_object_info_get_fundamental:
* @info: a #GIObjectInfo
*
* Obtain if the object type is of a fundamental type which is not
* `G_TYPE_OBJECT`.
*
* This is mostly for supporting `GstMiniObject`.
*
* Returns: `TRUE` if the object type is a fundamental type
* Since: 2.80
*/
gboolean
gi_object_info_get_fundamental (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), FALSE);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->fundamental != 0;
}
/**
* gi_object_info_get_type_name:
* @info: a #GIObjectInfo
*
* Obtain the name of the objects class/type.
*
* Returns: name of the objects type
* Since: 2.80
*/
const char *
gi_object_info_get_type_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return gi_typelib_get_string (rinfo->typelib, blob->gtype_name);
}
/**
* gi_object_info_get_type_init_function_name:
* @info: a #GIObjectInfo
*
* Obtain the name of the function which, when called, will return the
* [type@GObject.Type] for this object type.
*
* Returns: the type init function name
* Since: 2.80
*/
const char *
gi_object_info_get_type_init_function_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return gi_typelib_get_string (rinfo->typelib, blob->gtype_init);
}
/**
* gi_object_info_get_n_interfaces:
* @info: a #GIObjectInfo
*
* Obtain the number of interfaces that this object type has.
*
* Returns: number of interfaces
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_interfaces (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_interfaces;
}
/**
* gi_object_info_get_interface:
* @info: a #GIObjectInfo
* @n: index of interface to get
*
* Obtain an object type interface at index @n.
*
* Returns: (transfer full): The [class@GIRepository.InterfaceInfo]. Free the
* struct by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIInterfaceInfo *
gi_object_info_get_interface (GIObjectInfo *info,
unsigned int n)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return (GIInterfaceInfo *) gi_info_from_entry (rinfo->repository,
rinfo->typelib, blob->interfaces[n]);
}
/**
* gi_object_info_get_n_fields:
* @info: a #GIObjectInfo
*
* Obtain the number of fields that this object type has.
*
* Returns: number of fields
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_fields (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_fields;
}
/**
* gi_object_info_get_field:
* @info: a #GIObjectInfo
* @n: index of field to get
*
* Obtain an object type field at index @n.
*
* Returns: (transfer full): The [class@GIRepository.FieldInfo]. Free the struct
* by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIFieldInfo *
gi_object_info_get_field (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
offset = gi_object_info_get_field_offset(info, n);
return (GIFieldInfo *) gi_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib, offset);
}
/**
* gi_object_info_get_n_properties:
* @info: a #GIObjectInfo
*
* Obtain the number of properties that this object type has.
*
* Returns: number of properties
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_properties (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_properties;
}
/**
* gi_object_info_get_property:
* @info: a #GIObjectInfo
* @n: index of property to get
*
* Obtain an object type property at index @n.
*
* Returns: (transfer full): The [class@GIRepository.PropertyInfo]. Free the
* struct by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIPropertyInfo *
gi_object_info_get_property (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ n * header->property_blob_size;
return (GIPropertyInfo *) gi_info_new (GI_INFO_TYPE_PROPERTY, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* gi_object_info_get_n_methods:
* @info: a #GIObjectInfo
*
* Obtain the number of methods that this object type has.
*
* Returns: number of methods
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_methods (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_methods;
}
/**
* gi_object_info_get_method:
* @info: a #GIObjectInfo
* @n: index of method to get
*
* Obtain an object type method at index @n.
*
* Returns: (transfer full): The [class@GIRepository.FunctionInfo]. Free the
* struct by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIFunctionInfo *
gi_object_info_get_method (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size
+ n * header->function_blob_size;
return (GIFunctionInfo *) gi_info_new (GI_INFO_TYPE_FUNCTION, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* gi_object_info_find_method:
* @info: a #GIObjectInfo
* @name: name of method to obtain
*
* Obtain a method of the object type given a @name.
*
* `NULL` will be returned if theres no method available with that name.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.FunctionInfo],
* or `NULL` if no method could be found. Free the struct by calling
* [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIFunctionInfo *
gi_object_info_find_method (GIObjectInfo *info,
const char *name)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size +
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size;
return gi_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name);
}
/**
* gi_object_info_find_method_using_interfaces:
* @info: a #GIObjectInfo
* @name: name of method to obtain
* @implementor: (out) (transfer full) (optional) (nullable): The implementor of
* the interface, or `NULL` to ignore. If no method is found, this will return
* `NULL`.
*
* Obtain a method of the object given a @name, searching both the
* object @info and any interfaces it implements.
*
* `NULL` will be returned if theres no method available with that name.
*
* Note that this function does *not* search parent classes; you will have
* to chain up if thats desired.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.FunctionInfo],
* or `NULL` if none was found. Free the struct by calling
* [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIFunctionInfo *
gi_object_info_find_method_using_interfaces (GIObjectInfo *info,
const char *name,
GIObjectInfo **implementor)
{
GIFunctionInfo *result = NULL;
GIObjectInfo *implementor_result = NULL;
result = gi_object_info_find_method (info, name);
if (result)
implementor_result = (GIObjectInfo *) gi_base_info_ref ((GIBaseInfo*) info);
if (result == NULL)
{
int n_interfaces;
int i;
n_interfaces = gi_object_info_get_n_interfaces (info);
for (i = 0; i < n_interfaces; ++i)
{
GIInterfaceInfo *iface_info;
iface_info = gi_object_info_get_interface (info, i);
result = gi_interface_info_find_method (iface_info, name);
if (result != NULL)
{
implementor_result = (GIObjectInfo *) iface_info;
break;
}
gi_base_info_unref ((GIBaseInfo*) iface_info);
}
}
if (implementor)
*implementor = implementor_result;
else if (implementor_result != NULL)
gi_base_info_unref ((GIBaseInfo*) implementor_result);
return result;
}
/**
* gi_object_info_get_n_signals:
* @info: a #GIObjectInfo
*
* Obtain the number of signals that this object type has.
*
* Returns: number of signals
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_signals (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_signals;
}
/**
* gi_object_info_get_signal:
* @info: a #GIObjectInfo
* @n: index of signal to get
*
* Obtain an object type signal at index @n.
*
* Returns: (transfer full): The [class@GIRepository.SignalInfo]. Free the
* struct by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GISignalInfo *
gi_object_info_get_signal (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ n * header->signal_blob_size;
return (GISignalInfo *) gi_info_new (GI_INFO_TYPE_SIGNAL, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* gi_object_info_find_signal:
* @info: a #GIObjectInfo
* @name: name of signal
*
* Obtain a signal of the object type given a @name.
*
* `NULL` will be returned if theres no signal available with that name.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.SignalInfo],
* or `NULL` if no signal could be found. Free the struct by calling
* [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GISignalInfo *
gi_object_info_find_signal (GIObjectInfo *info,
const char *name)
{
size_t n_signals;
n_signals = gi_object_info_get_n_signals (info);
for (size_t i = 0; i < n_signals; i++)
{
GISignalInfo *siginfo = gi_object_info_get_signal (info, i);
if (g_strcmp0 (gi_base_info_get_name ((GIBaseInfo *) siginfo), name) != 0)
{
gi_base_info_unref ((GIBaseInfo*)siginfo);
continue;
}
return siginfo;
}
return NULL;
}
/**
* gi_object_info_get_n_vfuncs:
* @info: a #GIObjectInfo
*
* Obtain the number of virtual functions that this object type has.
*
* Returns: number of virtual functions
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_vfuncs (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_vfuncs;
}
/**
* gi_object_info_get_vfunc:
* @info: a #GIObjectInfo
* @n: index of virtual function to get
*
* Obtain an object type virtual function at index @n.
*
* Returns: (transfer full): The [class@GIRepository.VFuncInfo]. Free the struct
* by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIVFuncInfo *
gi_object_info_get_vfunc (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size
+ n * header->vfunc_blob_size;
return (GIVFuncInfo *) gi_info_new (GI_INFO_TYPE_VFUNC, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* gi_object_info_find_vfunc:
* @info: a #GIObjectInfo
* @name: the name of a virtual function to find.
*
* Locate a virtual function slot with name @name.
*
* Note that the namespace for virtuals is distinct from that of methods; there
* may or may not be a concrete method associated for a virtual. If there is
* one, it may be retrieved using [method@GIRepository.VFuncInfo.get_invoker],
* otherwise that method will return `NULL`.
*
* See the documentation for [method@GIRepository.VFuncInfo.get_invoker] for
* more information on invoking virtuals.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.VFuncInfo], or
* `NULL` if none is found. Free it with [method@GIRepository.BaseInfo.unref]
* when done.
* Since: 2.80
*/
GIVFuncInfo *
gi_object_info_find_vfunc (GIObjectInfo *info,
const char *name)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size;
return gi_base_info_find_vfunc (rinfo, offset, blob->n_vfuncs, name);
}
/**
* gi_object_info_find_vfunc_using_interfaces:
* @info: a #GIObjectInfo
* @name: name of vfunc to obtain
* @implementor: (out) (transfer full) (optional) (nullable): The implementor of
* the interface, or `NULL` to ignore. If no vfunc is found, this will return
* `NULL`.
*
* Locate a virtual function slot with name @name, searching both the object
* @info and any interfaces it implements.
*
* `NULL` will be returned if theres no vfunc available with that name.
*
* Note that the namespace for virtuals is distinct from that of methods; there
* may or may not be a concrete method associated for a virtual. If there is
* one, it may be retrieved using [method@GIRepository.VFuncInfo.get_invoker],
* otherwise that method will return `NULL`.
*
* Note that this function does *not* search parent classes; you will have
* to chain up if thats desired.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.VFuncInfo],
* or `NULL` if none was found. Free the struct by calling
* [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIVFuncInfo *
gi_object_info_find_vfunc_using_interfaces (GIObjectInfo *info,
const char *name,
GIObjectInfo **implementor)
{
GIVFuncInfo *result = NULL;
GIObjectInfo *implementor_result = NULL;
result = gi_object_info_find_vfunc (info, name);
if (result)
implementor_result = (GIObjectInfo *) gi_base_info_ref ((GIBaseInfo*) info);
if (result == NULL)
{
int n_interfaces;
int i;
n_interfaces = gi_object_info_get_n_interfaces (info);
for (i = 0; i < n_interfaces; ++i)
{
GIInterfaceInfo *iface_info;
iface_info = gi_object_info_get_interface (info, i);
result = gi_interface_info_find_vfunc (iface_info, name);
if (result != NULL)
{
implementor_result = (GIObjectInfo *) iface_info;
break;
}
gi_base_info_unref ((GIBaseInfo*) iface_info);
}
}
if (implementor)
*implementor = implementor_result;
else if (implementor_result != NULL)
gi_base_info_unref ((GIBaseInfo*) implementor_result);
return result;
}
/**
* gi_object_info_get_n_constants:
* @info: a #GIObjectInfo
*
* Obtain the number of constants that this object type has.
*
* Returns: number of constants
* Since: 2.80
*/
unsigned int
gi_object_info_get_n_constants (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), 0);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_constants;
}
/**
* gi_object_info_get_constant:
* @info: a #GIObjectInfo
* @n: index of constant to get
*
* Obtain an object type constant at index @n.
*
* Returns: (transfer full): The [class@GIRepository.ConstantInfo]. Free the
* struct by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GIConstantInfo *
gi_object_info_get_constant (GIObjectInfo *info,
unsigned int n)
{
size_t offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
g_return_val_if_fail (n <= G_MAXUINT16, NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
+ blob->n_field_callbacks * header->callback_blob_size
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size
+ blob->n_vfuncs * header->vfunc_blob_size
+ n * header->constant_blob_size;
return (GIConstantInfo *) gi_info_new (GI_INFO_TYPE_CONSTANT, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* gi_object_info_get_class_struct:
* @info: a #GIObjectInfo
*
* Every [class@GObject.Object] has two structures; an instance structure and a
* class structure. This function returns the metadata for the class structure.
*
* Returns: (transfer full) (nullable): The [class@GIRepository.StructInfo] or
* `NULL` if its unknown. Free with [method@GIRepository.BaseInfo.unref] when
* done.
* Since: 2.80
*/
GIStructInfo *
gi_object_info_get_class_struct (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->gtype_struct)
return (GIStructInfo *) gi_info_from_entry (rinfo->repository,
rinfo->typelib, blob->gtype_struct);
else
return NULL;
}
typedef const char* (*SymbolGetter) (GIObjectInfo *info);
static void *
_get_func(GIObjectInfo *info,
SymbolGetter getter)
{
const char* symbol;
GSList *parents = NULL, *l;
GIObjectInfo *parent_info;
void *func = NULL;
parent_info = (GIObjectInfo *) gi_base_info_ref ((GIBaseInfo *) info);
while (parent_info != NULL)
{
parents = g_slist_prepend (parents, parent_info);
parent_info = gi_object_info_get_parent (parent_info);
}
for (l = parents; l; l = l->next)
{
parent_info = l->data;
symbol = getter (parent_info);
if (symbol == NULL)
continue;
gi_typelib_symbol (((GIRealInfo *)parent_info)->typelib, symbol, (gpointer*) &func);
if (func)
break;
}
g_slist_free_full (parents, (GDestroyNotify) gi_base_info_unref);
return func;
}
/**
* gi_object_info_get_ref_function_name:
* @info: a #GIObjectInfo
*
* Obtain the symbol name of the function that should be called to ref this
* object type.
*
* Its mainly used for fundamental types. The type signature for
* the symbol is [type@GIRepository.ObjectInfoRefFunction]. To fetch the
* function pointer see
* [method@GIRepository.ObjectInfo.get_ref_function_pointer].
*
* Returns: (nullable): the symbol, or `NULL` if the object type has no ref
* function
* Since: 2.80
*/
const char *
gi_object_info_get_ref_function_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->ref_func)
return gi_typelib_get_string (rinfo->typelib, blob->ref_func);
return NULL;
}
/**
* gi_object_info_get_ref_function_pointer: (skip)
* @info: a #GIObjectInfo
*
* Obtain a pointer to a function which can be used to
* increase the reference count an instance of this object type.
*
* This takes derivation into account and will reversely traverse
* the base classes of this type, starting at the top type.
*
* Returns: (nullable): the function pointer, or `NULL` if the object type has
* no ref function
* Since: 2.80
*/
GIObjectInfoRefFunction
gi_object_info_get_ref_function_pointer (GIObjectInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
return (GIObjectInfoRefFunction)_get_func(info, (SymbolGetter)gi_object_info_get_ref_function_name);
}
/**
* gi_object_info_get_unref_function_name:
* @info: a #GIObjectInfo
*
* Obtain the symbol name of the function that should be called to unref this
* object type.
*
* Its mainly used for fundamental types. The type signature for the symbol is
* [type@GIRepository.ObjectInfoUnrefFunction]. To fetch the function pointer
* see [method@GIRepository.ObjectInfo.get_unref_function_pointer].
*
* Returns: (nullable): the symbol, or `NULL` if the object type has no unref
* function
* Since: 2.80
*/
const char *
gi_object_info_get_unref_function_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->unref_func)
return gi_typelib_get_string (rinfo->typelib, blob->unref_func);
return NULL;
}
/**
* gi_object_info_get_unref_function_pointer: (skip)
* @info: a #GIObjectInfo
*
* Obtain a pointer to a function which can be used to
* decrease the reference count an instance of this object type.
*
* This takes derivation into account and will reversely traverse
* the base classes of this type, starting at the top type.
*
* Returns: (nullable): the function pointer, or `NULL` if the object type has
* no unref function
* Since: 2.80
*/
GIObjectInfoUnrefFunction
gi_object_info_get_unref_function_pointer (GIObjectInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
return (GIObjectInfoUnrefFunction)_get_func(info, (SymbolGetter)gi_object_info_get_unref_function_name);
}
/**
* gi_object_info_get_set_value_function_name:
* @info: a #GIObjectInfo
*
* Obtain the symbol name of the function that should be called to set a
* [type@GObject.Value], given an object instance pointer of this object type.
*
* Its mainly used for fundamental types. The type signature for the symbol
* is [type@GIRepository.ObjectInfoSetValueFunction]. To fetch the function
* pointer see [method@GIRepository.ObjectInfo.get_set_value_function_pointer].
*
* Returns: (nullable): the symbol, or `NULL` if the object type has no
* set-value function
* Since: 2.80
*/
const char *
gi_object_info_get_set_value_function_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->set_value_func)
return gi_typelib_get_string (rinfo->typelib, blob->set_value_func);
return NULL;
}
/**
* gi_object_info_get_set_value_function_pointer: (skip)
* @info: a #GIObjectInfo
*
* Obtain a pointer to a function which can be used to set a
* [type@GObject.Value], given an instance of this object type.
*
* This takes derivation into account and will reversely traverse
* the base classes of this type, starting at the top type.
*
* Returns: (nullable): the function pointer, or `NULL` if the object type has
* no set-value function
* Since: 2.80
*/
GIObjectInfoSetValueFunction
gi_object_info_get_set_value_function_pointer (GIObjectInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
return (GIObjectInfoSetValueFunction)_get_func(info, (SymbolGetter)gi_object_info_get_set_value_function_name);
}
/**
* gi_object_info_get_get_value_function_name:
* @info: a #GIObjectInfo
*
* Obtain the symbol name of the function that should be called to convert
* an object instance pointer of this object type to a [type@GObject.Value].
*
* Its mainly used for fundamental types. The type signature for the symbol
* is [type@GIRepository.ObjectInfoGetValueFunction]. To fetch the function
* pointer see [method@GIRepository.ObjectInfo.get_get_value_function_pointer].
*
* Returns: (nullable): the symbol, or `NULL` if the object type has no
* get-value function
* Since: 2.80
*/
const char *
gi_object_info_get_get_value_function_name (GIObjectInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->get_value_func)
return gi_typelib_get_string (rinfo->typelib, blob->get_value_func);
return NULL;
}
/**
* gi_object_info_get_get_value_function_pointer: (skip)
* @info: a #GIObjectInfo
*
* Obtain a pointer to a function which can be used to extract an instance of
* this object type out of a [type@GObject.Value].
*
* This takes derivation into account and will reversely traverse
* the base classes of this type, starting at the top type.
*
* Returns: (nullable): the function pointer, or `NULL` if the object type has
* no get-value function
* Since: 2.80
*/
GIObjectInfoGetValueFunction
gi_object_info_get_get_value_function_pointer (GIObjectInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
return (GIObjectInfoGetValueFunction)_get_func(info, (SymbolGetter)gi_object_info_get_get_value_function_name);
}
void
gi_object_info_class_init (gpointer g_class,
gpointer class_data)
{
GIBaseInfoClass *info_class = g_class;
info_class->info_type = GI_INFO_TYPE_OBJECT;
}