summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>2008-11-16 21:14:19 +0000
committerOwen Taylor <otaylor@src.gnome.org>2008-11-16 21:14:19 +0000
commita5d45df66370320ec2ae493383ba1388157182da (patch)
tree543b57c853365a04eeb48d9705f09ee41311d435
parent5404679aba387c5295ae7b50fa1af2259d4b9cf7 (diff)
downloadgobject-introspection-a5d45df66370320ec2ae493383ba1388157182da.tar.gz
Bug 552371 – implement struct field get/set
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
-rw-r--r--ChangeLog11
-rw-r--r--girepository/Makefile.am1
-rw-r--r--girepository/gfield.c308
-rw-r--r--girepository/girepository.h6
4 files changed, 325 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 721a9a51..ff663e8f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,19 @@
+2008-11-16 Owen Taylor <otaylor@redhat.com>
+
+ 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 <a.rottmann@gmx.at>
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 <a.rottmann@gmx.at>
Bug 559601 - Pointers in structs/unions unduly treated as arrays
diff --git a/girepository/Makefile.am b/girepository/Makefile.am
index b58288e8..f98dda29 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 00000000..79a5a0d5
--- /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 46082e03..fc5768c5 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);