From a5d45df66370320ec2ae493383ba1388157182da Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sun, 16 Nov 2008 21:14:19 +0000 Subject: [PATCH] =?utf8?q?Bug=20552371=20=E2=80=93=20implement=20struct=20?= =?utf8?q?field=20get/set?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add convenience functions g_field_info_set_field() and g_field_info_get_field() to set and get fields based on the offsets in GIFieldInfo. svn path=/trunk/; revision=929 --- ChangeLog | 11 +- girepository/Makefile.am | 1 + girepository/gfield.c | 308 ++++++++++++++++++++++++++++++++++++++++++++ girepository/girepository.h | 6 + 4 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 girepository/gfield.c diff --git a/ChangeLog b/ChangeLog index 721a9a5..ff663e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,19 @@ +2008-11-16 Owen Taylor + + Bug 552371 – implement struct field get/set + + * girepository/gfield.c girepository/girepository.h: Add + convenience functions g_field_info_set_field() and + g_field_info_get_field() to set and get fields based on the + offsets in GIFieldInfo. + 2008-11-16 Andreas Rottmann Bug 560241 - Out-arguments should not be marked as being pointers in all cases * girepository/girparser.c: Improved logic for out arguments. - + 2008-11-16 Andreas Rottmann Bug 559601 - Pointers in structs/unions unduly treated as arrays diff --git a/girepository/Makefile.am b/girepository/Makefile.am index b58288e..f98dda2 100644 --- a/girepository/Makefile.am +++ b/girepository/Makefile.am @@ -12,6 +12,7 @@ libgirepository_la_SOURCES = \ girepository.c \ gtypelib.h \ gtypelib.c \ + gfield.c \ ginfo.c \ girffi.c \ girffi.h \ diff --git a/girepository/gfield.c b/girepository/gfield.c new file mode 100644 index 0000000..79a5a0d --- /dev/null +++ b/girepository/gfield.c @@ -0,0 +1,308 @@ +#include "girepository.h" + +/** + * g_field_info_get_field: + * @field_info: a #GIFieldInfo + * @mem: pointer to a block of memory representing a C structure or union + * @value: a #GArgument into which to store the value retrieved + * + * Reads a field identified by a #GFieldInfo 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, otherwise %FALSE + */ +gboolean +g_field_info_get_field (GIFieldInfo *field_info, + gpointer mem, + GArgument *value) +{ + int offset; + GITypeInfo *type_info; + gboolean result = FALSE; + + if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) + return FALSE; + + offset = g_field_info_get_offset (field_info); + type_info = g_field_info_get_type (field_info); + + if (g_type_info_is_pointer (type_info)) + { + value->v_pointer = G_STRUCT_MEMBER(gpointer, mem, offset); + result = TRUE; + } + else + { + switch (g_type_info_get_tag (type_info)) + { + case GI_TYPE_TAG_VOID: + g_warning("Field %s: should not be have void type", + g_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_INT: + case GI_TYPE_TAG_UINT: + 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_LONG: + case GI_TYPE_TAG_ULONG: + value->v_ulong = G_STRUCT_MEMBER(gulong, mem, offset); + result = TRUE; + break; + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_SIZE: + 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_TIME_T: + value->v_long = G_STRUCT_MEMBER(time_t, mem, offset); + 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", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_type_tag_to_string (g_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 = g_type_info_get_interface (type_info); + switch (g_base_info_get_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: + /* Not yet implemented */ + break; + case GI_INFO_TYPE_VFUNC: + case GI_INFO_TYPE_CALLBACK: + g_warning("Field%s: Interface type %d should have is_pointer set", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_base_info_get_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_ERROR_DOMAIN: + 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", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_base_info_get_type (interface)); + break; + } + + g_base_info_unref ((GIBaseInfo *)interface); + break; + } + break; + } + } + + g_base_info_unref ((GIBaseInfo *)field_info); + + return result; +} + +/** + * g_field_info_set_field: + * @field_info: a #GIFieldInfo + * @mem: pointer to a block of memory representing a C structure or union + * @value: a #GArgument holding the value to store + * + * Writes a field identified by a #GFieldInfo 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 reading the field succeeded, otherwise %FALSE + */ +gboolean +g_field_info_set_field (GIFieldInfo *field_info, + gpointer mem, + const GArgument *value) +{ + int offset; + GITypeInfo *type_info; + gboolean result = FALSE; + + if (!g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) + return FALSE; + + offset = g_field_info_get_offset (field_info); + type_info = g_field_info_get_type (field_info); + + if (!g_type_info_is_pointer (type_info)) + { + switch (g_type_info_get_tag (type_info)) + { + case GI_TYPE_TAG_VOID: + g_warning("Field %s: should not be have void type", + g_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_INT: + case GI_TYPE_TAG_UINT: + 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_LONG: + case GI_TYPE_TAG_ULONG: + G_STRUCT_MEMBER(gulong, mem, offset)= value->v_ulong; + result = TRUE; + break; + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_SIZE: + 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_TIME_T: + G_STRUCT_MEMBER(time_t, mem, offset) = value->v_long; + 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", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_type_tag_to_string (g_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 = g_type_info_get_interface (type_info); + switch (g_base_info_get_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: + /* Not yet implemented */ + break; + case GI_INFO_TYPE_VFUNC: + case GI_INFO_TYPE_CALLBACK: + g_warning("Field%s: Interface type %d should have is_pointer set", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_base_info_get_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_ERROR_DOMAIN: + 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", + g_base_info_get_name ((GIBaseInfo *)field_info), + g_base_info_get_type (interface)); + break; + } + + g_base_info_unref ((GIBaseInfo *)interface); + break; + } + break; + } + } + + g_base_info_unref ((GIBaseInfo *)field_info); + + return result; +} diff --git a/girepository/girepository.h b/girepository/girepository.h index 46082e0..fc5768c 100644 --- a/girepository/girepository.h +++ b/girepository/girepository.h @@ -356,6 +356,12 @@ gint g_field_info_get_size (GIFieldInfo *info); gint g_field_info_get_offset (GIFieldInfo *info); GITypeInfo * g_field_info_get_type (GIFieldInfo *info); +gboolean g_field_info_get_field (GIFieldInfo *field_info, + gpointer mem, + GArgument *value); +gboolean g_field_info_set_field (GIFieldInfo *field_info, + gpointer mem, + const GArgument *value); /* GIUnionInfo */ gint g_union_info_get_n_fields (GIUnionInfo *info); -- 2.7.4