glib/girepository/gifieldinfo.c
Philip Withnall 0910e2f6ad girepository: Drop outdated/unused GIInfoType member
It was deprecated since before libgirepository was moved into this
repository. Take the opportunity now to remove it entirely, as it’s a
bit confusing to have it in the public API.

This should not affect the binary typelib format, as it still has its
`BLOB_TYPE_INVALID_0` member, and that will remain in place until the
binary format next breaks compatibility (no plans to do that).

This is an API break in libgirepository, but since it’s not been in a
stable release yet, that’s fine.

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

Helps: #3155
2024-01-05 13:51:23 +00:00

578 lines
17 KiB
C

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
* GObject introspection: Field 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 "config.h"
#include "gifieldinfo.h"
/**
* GIFieldInfo:
*
* A `GIFieldInfo` struct represents a field of a struct, union, or object.
*
* The `GIFieldInfo` is fetched by calling
* [method@GIRepository.StructInfo.get_field],
* [method@GIRepository.UnionInfo.get_field] or
* [method@GIRepository.ObjectInfo.get_field].
*
* A field has a size, type and a struct offset associated and a set of flags,
* which are currently `GI_FIELD_IS_READABLE` or `GI_FIELD_IS_WRITABLE`.
*
* See also: [type@GIRepository.StructInfo], [type@GIRepository.UnionInfo],
* [type@GIRepository.ObjectInfo]
*
* Since: 2.80
*/
/**
* gi_field_info_get_flags:
* @info: a #GIFieldInfo
*
* Obtain the flags for this `GIFieldInfo`. See
* [flags@GIRepository.FieldInfoFlags] for possible flag values.
*
* Returns: the flags
* Since: 2.80
*/
GIFieldInfoFlags
gi_field_info_get_flags (GIFieldInfo *info)
{
GIFieldInfoFlags flags;
GIRealInfo *rinfo = (GIRealInfo *)info;
FieldBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
flags = 0;
if (blob->readable)
flags = flags | GI_FIELD_IS_READABLE;
if (blob->writable)
flags = flags | GI_FIELD_IS_WRITABLE;
return flags;
}
/**
* gi_field_info_get_size:
* @info: a #GIFieldInfo
*
* Obtain the size of the field member, in bits. This is how
* much space you need to allocate to store the field.
*
* Returns: the field size, in bits
* Since: 2.80
*/
gsize
gi_field_info_get_size (GIFieldInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
FieldBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->bits;
}
/**
* gi_field_info_get_offset:
* @info: a #GIFieldInfo
*
* Obtain the offset of the field member, in bytes. This is relative
* to the beginning of the struct or union.
*
* Returns: the field offset, in bytes
* Since: 2.80
*/
gsize
gi_field_info_get_offset (GIFieldInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
FieldBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->struct_offset;
}
/**
* gi_field_info_get_type_info:
* @info: a #GIFieldInfo
*
* Obtain the type of a field as a [type@GIRepository.TypeInfo].
*
* Returns: (transfer full): the [type@GIRepository.TypeInfo]. Free the struct
* by calling [method@GIRepository.BaseInfo.unref] when done.
* Since: 2.80
*/
GITypeInfo *
gi_field_info_get_type_info (GIFieldInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header = (Header *)rinfo->typelib->data;
FieldBlob *blob;
GIRealInfo *type_info;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_FIELD_INFO (info), NULL);
blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
if (blob->has_embedded_type)
{
type_info = (GIRealInfo *) gi_info_new (GI_INFO_TYPE_TYPE,
(GIBaseInfo*)info, rinfo->typelib,
rinfo->offset + header->field_blob_size);
type_info->type_is_embedded = TRUE;
}
else
return gi_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + G_STRUCT_OFFSET (FieldBlob, type));
return (GITypeInfo *) type_info;
}
/**
* gi_field_info_get_field: (skip)
* @field_info: a #GIFieldInfo
* @mem: pointer to a block of memory representing a C structure or union
* @value: a [type@GIRepository.Argument] into which to store the value retrieved
*
* Reads a field identified by a `GIFieldInfo` from a C structure or
* union.
*
* This only handles fields of simple C types. It will fail for a field of a
* composite type like a nested structure or union even if that is actually
* readable.
*
* Returns: `TRUE` if reading the field succeeded, `FALSE` otherwise
* Since: 2.80
*/
gboolean
gi_field_info_get_field (GIFieldInfo *field_info,
gpointer mem,
GIArgument *value)
{
int offset;
GITypeInfo *type_info;
gboolean result = FALSE;
g_return_val_if_fail (field_info != NULL, FALSE);
g_return_val_if_fail (GI_IS_FIELD_INFO (field_info), FALSE);
if ((gi_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) == 0)
return FALSE;
offset = gi_field_info_get_offset (field_info);
type_info = gi_field_info_get_type_info (field_info);
if (gi_type_info_is_pointer (type_info))
{
value->v_pointer = G_STRUCT_MEMBER (gpointer, mem, offset);
result = TRUE;
}
else
{
switch (gi_type_info_get_tag (type_info))
{
case GI_TYPE_TAG_VOID:
g_warning("Field %s: should not be have void type",
gi_base_info_get_name ((GIBaseInfo *)field_info));
break;
case GI_TYPE_TAG_BOOLEAN:
value->v_boolean = G_STRUCT_MEMBER (gboolean, mem, offset) != FALSE;
result = TRUE;
break;
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
value->v_uint8 = G_STRUCT_MEMBER (guint8, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
value->v_uint16 = G_STRUCT_MEMBER (guint16, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_UINT32:
case GI_TYPE_TAG_UNICHAR:
value->v_uint32 = G_STRUCT_MEMBER (guint32, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT64:
case GI_TYPE_TAG_UINT64:
value->v_uint64 = G_STRUCT_MEMBER (guint64, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_GTYPE:
value->v_size = G_STRUCT_MEMBER (gsize, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_FLOAT:
value->v_float = G_STRUCT_MEMBER (gfloat, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_DOUBLE:
value->v_double = G_STRUCT_MEMBER (gdouble, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_ARRAY:
/* We don't check the array type and that it is fixed-size,
we trust g-ir-compiler to do the right thing */
value->v_pointer = G_STRUCT_MEMBER_P (mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_GHASH:
g_warning("Field %s: type %s should have is_pointer set",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_type_tag_to_string (gi_type_info_get_tag (type_info)));
break;
case GI_TYPE_TAG_ERROR:
/* Needs to be handled by the language binding directly */
break;
case GI_TYPE_TAG_INTERFACE:
{
GIBaseInfo *interface = gi_type_info_get_interface (type_info);
switch (gi_base_info_get_info_type (interface))
{
case GI_INFO_TYPE_STRUCT:
case GI_INFO_TYPE_UNION:
case GI_INFO_TYPE_BOXED:
/* Needs to be handled by the language binding directly */
break;
case GI_INFO_TYPE_OBJECT:
break;
case GI_INFO_TYPE_ENUM:
case GI_INFO_TYPE_FLAGS:
{
/* FIXME: there's a mismatch here between the value->v_int we use
* here and the gint64 result returned from gi_value_info_get_value().
* But to switch this to gint64, we'd have to make gi_function_info_invoke()
* translate value->v_int64 to the proper ABI for an enum function
* call parameter, which will usually be int, and then fix up language
* bindings.
*/
GITypeTag storage_type = gi_enum_info_get_storage_type ((GIEnumInfo *)interface);
switch (storage_type)
{
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
value->v_int = (gint)G_STRUCT_MEMBER (guint8, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
value->v_int = (gint)G_STRUCT_MEMBER (guint16, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_UINT32:
value->v_int = (gint)G_STRUCT_MEMBER (guint32, mem, offset);
result = TRUE;
break;
case GI_TYPE_TAG_INT64:
case GI_TYPE_TAG_UINT64:
value->v_int = (gint)G_STRUCT_MEMBER (guint64, mem, offset);
result = TRUE;
break;
default:
g_warning("Field %s: Unexpected enum storage type %s",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_type_tag_to_string (storage_type));
break;
}
break;
}
case GI_INFO_TYPE_VFUNC:
case GI_INFO_TYPE_CALLBACK:
g_warning("Field %s: Interface type %d should have is_pointer set",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_base_info_get_info_type (interface));
break;
case GI_INFO_TYPE_INVALID:
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_FUNCTION:
case GI_INFO_TYPE_CONSTANT:
case GI_INFO_TYPE_VALUE:
case GI_INFO_TYPE_SIGNAL:
case GI_INFO_TYPE_PROPERTY:
case GI_INFO_TYPE_FIELD:
case GI_INFO_TYPE_ARG:
case GI_INFO_TYPE_TYPE:
case GI_INFO_TYPE_UNRESOLVED:
g_warning("Field %s: Interface type %d not expected",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_base_info_get_info_type (interface));
break;
default:
break;
}
gi_base_info_unref ((GIBaseInfo *)interface);
break;
}
break;
default:
break;
}
}
gi_base_info_unref ((GIBaseInfo *)type_info);
return result;
}
/**
* gi_field_info_set_field: (skip)
* @field_info: a #GIFieldInfo
* @mem: pointer to a block of memory representing a C structure or union
* @value: a [type@GIRepository.Argument] holding the value to store
*
* Writes a field identified by a `GIFieldInfo` to a C structure or
* union.
*
* This only handles fields of simple C types. It will fail for a field of a
* composite type like a nested structure or union even if that is actually
* writable. Note also that that it will refuse to write fields where memory
* management would by required. A field with a type such as `char *` must be
* set with a setter function.
*
* Returns: `TRUE` if writing the field succeeded, `FALSE` otherwise
* Since: 2.80
*/
gboolean
gi_field_info_set_field (GIFieldInfo *field_info,
gpointer mem,
const GIArgument *value)
{
int offset;
GITypeInfo *type_info;
gboolean result = FALSE;
g_return_val_if_fail (field_info != NULL, FALSE);
g_return_val_if_fail (GI_IS_FIELD_INFO (field_info), FALSE);
if ((gi_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) == 0)
return FALSE;
offset = gi_field_info_get_offset (field_info);
type_info = gi_field_info_get_type_info (field_info);
if (!gi_type_info_is_pointer (type_info))
{
switch (gi_type_info_get_tag (type_info))
{
case GI_TYPE_TAG_VOID:
g_warning("Field %s: should not be have void type",
gi_base_info_get_name ((GIBaseInfo *)field_info));
break;
case GI_TYPE_TAG_BOOLEAN:
G_STRUCT_MEMBER (gboolean, mem, offset) = value->v_boolean != FALSE;
result = TRUE;
break;
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
G_STRUCT_MEMBER (guint8, mem, offset) = value->v_uint8;
result = TRUE;
break;
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
G_STRUCT_MEMBER (guint16, mem, offset) = value->v_uint16;
result = TRUE;
break;
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_UINT32:
case GI_TYPE_TAG_UNICHAR:
G_STRUCT_MEMBER (guint32, mem, offset) = value->v_uint32;
result = TRUE;
break;
case GI_TYPE_TAG_INT64:
case GI_TYPE_TAG_UINT64:
G_STRUCT_MEMBER (guint64, mem, offset) = value->v_uint64;
result = TRUE;
break;
case GI_TYPE_TAG_GTYPE:
G_STRUCT_MEMBER (gsize, mem, offset) = value->v_size;
result = TRUE;
break;
case GI_TYPE_TAG_FLOAT:
G_STRUCT_MEMBER (gfloat, mem, offset) = value->v_float;
result = TRUE;
break;
case GI_TYPE_TAG_DOUBLE:
G_STRUCT_MEMBER (gdouble, mem, offset)= value->v_double;
result = TRUE;
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_GHASH:
g_warning("Field %s: type %s should have is_pointer set",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_type_tag_to_string (gi_type_info_get_tag (type_info)));
break;
case GI_TYPE_TAG_ERROR:
/* Needs to be handled by the language binding directly */
break;
case GI_TYPE_TAG_INTERFACE:
{
GIBaseInfo *interface = gi_type_info_get_interface (type_info);
switch (gi_base_info_get_info_type (interface))
{
case GI_INFO_TYPE_STRUCT:
case GI_INFO_TYPE_UNION:
case GI_INFO_TYPE_BOXED:
/* Needs to be handled by the language binding directly */
break;
case GI_INFO_TYPE_OBJECT:
break;
case GI_INFO_TYPE_ENUM:
case GI_INFO_TYPE_FLAGS:
{
/* See FIXME above
*/
GITypeTag storage_type = gi_enum_info_get_storage_type ((GIEnumInfo *)interface);
switch (storage_type)
{
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
G_STRUCT_MEMBER (guint8, mem, offset) = (guint8)value->v_int;
result = TRUE;
break;
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
G_STRUCT_MEMBER (guint16, mem, offset) = (guint16)value->v_int;
result = TRUE;
break;
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_UINT32:
G_STRUCT_MEMBER (guint32, mem, offset) = (guint32)value->v_int;
result = TRUE;
break;
case GI_TYPE_TAG_INT64:
case GI_TYPE_TAG_UINT64:
G_STRUCT_MEMBER (guint64, mem, offset) = (guint64)value->v_int;
result = TRUE;
break;
default:
g_warning("Field %s: Unexpected enum storage type %s",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_type_tag_to_string (storage_type));
break;
}
break;
}
break;
case GI_INFO_TYPE_VFUNC:
case GI_INFO_TYPE_CALLBACK:
g_warning("Field%s: Interface type %d should have is_pointer set",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_base_info_get_info_type (interface));
break;
case GI_INFO_TYPE_INVALID:
case GI_INFO_TYPE_INTERFACE:
case GI_INFO_TYPE_FUNCTION:
case GI_INFO_TYPE_CONSTANT:
case GI_INFO_TYPE_VALUE:
case GI_INFO_TYPE_SIGNAL:
case GI_INFO_TYPE_PROPERTY:
case GI_INFO_TYPE_FIELD:
case GI_INFO_TYPE_ARG:
case GI_INFO_TYPE_TYPE:
case GI_INFO_TYPE_UNRESOLVED:
g_warning("Field %s: Interface type %d not expected",
gi_base_info_get_name ((GIBaseInfo *)field_info),
gi_base_info_get_info_type (interface));
break;
default:
break;
}
gi_base_info_unref ((GIBaseInfo *)interface);
break;
}
break;
default:
break;
}
} else {
switch (gi_type_info_get_tag (type_info))
{
case GI_TYPE_TAG_INTERFACE:
{
GIBaseInfo *interface = gi_type_info_get_interface (type_info);
switch (gi_base_info_get_info_type (interface))
{
case GI_INFO_TYPE_OBJECT:
case GI_INFO_TYPE_INTERFACE:
G_STRUCT_MEMBER (gpointer, mem, offset) = (gpointer)value->v_pointer;
result = TRUE;
break;
default:
break;
}
gi_base_info_unref ((GIBaseInfo *)interface);
}
break;
default:
break;
}
}
gi_base_info_unref ((GIBaseInfo *)type_info);
return result;
}
void
gi_field_info_class_init (gpointer g_class,
gpointer class_data)
{
GIBaseInfoClass *info_class = g_class;
info_class->info_type = GI_INFO_TYPE_FIELD;
}