summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>2008-11-18 12:29:10 +0000
committerOwen Taylor <otaylor@src.gnome.org>2008-11-18 12:29:10 +0000
commita26517953e7fefedc8a450f8c727f787296d8823 (patch)
tree4e5b83362f094e7288ed7c45934275e17db8343b
parent6cea68fc58343509c7012ef7b5fec86a115e6fb4 (diff)
downloadgobject-introspection-a26517953e7fefedc8a450f8c727f787296d8823.tar.gz
Add "storage type" to the typelib data for enums
In order to set and get enum and flag fields in structures, we need to know the integral type that the enumeration is stored as. We are already computing that at compile time in order to compute struct offsets, so the easiest thing to do is to save that in the typelib. * docs/typelib-format.txt girepository/girnode.[ch] girepository/giroffsets.c girepository/gtypelib.h: Add 'storage_type' to the typelib format for EnumBlob and compute and save it at compile time. * girepository/girepository.h girepository/ginfo.c: Add g_enum_info_get_storage_type(). * girepository/gfield.c: Implement reading and writing enum and flags fields based on the storage type. http://bugzilla.gnome.org/show_bug.cgi?id=561296 svn path=/trunk/; revision=944
-rw-r--r--ChangeLog19
-rw-r--r--docs/typelib-format.txt7
-rw-r--r--girepository/gfield.c95
-rw-r--r--girepository/ginfo.c22
-rw-r--r--girepository/girepository.h1
-rw-r--r--girepository/girnode.c1
-rw-r--r--girepository/girnode.h1
-rw-r--r--girepository/giroffsets.c63
-rw-r--r--girepository/gtypelib.h3
9 files changed, 197 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 6bc9e238..8faab78a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2008-11-18 Owen Taylor <otaylor@redhat.com>
+ Bug 561296 - Add "storage type" to the typelib data for enums
+
+ In order to set and get enum and flag fields in structures, we need
+ to know the integral type that the enumeration is stored as. We are already
+ computing that at compile time in order to compute struct offsets, so the
+ easiest thing to do is to save that in the typelib.
+
+ * docs/typelib-format.txt girepository/girnode.[ch] girepository/giroffsets.c
+ girepository/gtypelib.h: Add 'storage_type' to the typelib format for EnumBlob
+ and compute and save it at compile time.
+
+ * girepository/girepository.h girepository/ginfo.c:
+ Add g_enum_info_get_storage_type().
+
+ * girepository/gfield.c: Implement reading and writing enum and flags fields
+ based on the storage type.
+
+2008-11-18 Owen Taylor <otaylor@redhat.com>
+
Add enums to the Everything test module
* tests/everything/everything.[ch]: Add TestEnum and TestFlags to the Everything
diff --git a/docs/typelib-format.txt b/docs/typelib-format.txt
index fa76393e..d7cfedae 100644
--- a/docs/typelib-format.txt
+++ b/docs/typelib-format.txt
@@ -856,7 +856,8 @@ struct EnumBlob
guint16 blob_type; /* 5: enum, 6: flags */
guint deprecated : 1;
guint unregistered : 1;
- guint reserved :14;
+ guint storage_type : 5;
+ guint reserved : 9;
guint32 name;
GTypeBlob gtype;
@@ -870,6 +871,10 @@ struct EnumBlob
unregistered:
If this is set, the type is not registered with GType.
+storage_type:
+ The tag of the type used for the enum in the C ABI
+ (will be a signed or unsigned integral type)
+
gtype: For types which are registered with GType, contains the
information about the GType. Otherwise unused.
diff --git a/girepository/gfield.c b/girepository/gfield.c
index 79a5a0d5..673e3db7 100644
--- a/girepository/gfield.c
+++ b/girepository/gfield.c
@@ -1,4 +1,7 @@
+#include <string.h>
+
#include "girepository.h"
+#include "girffi.h"
/**
* g_field_info_get_field:
@@ -117,11 +120,55 @@ g_field_info_get_field (GIFieldInfo *field_info,
break;
case GI_INFO_TYPE_ENUM:
case GI_INFO_TYPE_FLAGS:
- /* Not yet implemented */
- break;
+ {
+ /* FIXME: there's a mismatch here between the value->v_int we use
+ * here and the glong result returned from g_value_info_get_value().
+ * But to switch this to glong, we'd have to make g_function_info_invoke()
+ * translate value->v_long to the proper ABI for an enum function
+ * call parameter, which will usually be int, and then fix up language
+ * bindings.
+ */
+ GITypeTag storage_type = g_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:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ 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;
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_ULONG:
+ value->v_int = (gint)G_STRUCT_MEMBER(gulong, mem, offset);
+ result = TRUE;
+ break;
+ default:
+ g_warning("Field %s: Unexpected enum storage type %s",
+ g_base_info_get_name ((GIBaseInfo *)field_info),
+ g_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",
+ 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;
@@ -269,7 +316,47 @@ g_field_info_set_field (GIFieldInfo *field_info,
break;
case GI_INFO_TYPE_ENUM:
case GI_INFO_TYPE_FLAGS:
- /* Not yet implemented */
+ {
+ /* See FIXME above
+ */
+ GITypeTag storage_type = g_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:
+ case GI_TYPE_TAG_INT:
+ case GI_TYPE_TAG_UINT:
+ 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;
+ case GI_TYPE_TAG_LONG:
+ case GI_TYPE_TAG_ULONG:
+ G_STRUCT_MEMBER(gulong, mem, offset) = (gulong)value->v_int;
+ result = TRUE;
+ break;
+ default:
+ g_warning("Field %s: Unexpected enum storage type %s",
+ g_base_info_get_name ((GIBaseInfo *)field_info),
+ g_type_tag_to_string (storage_type));
+ break;
+ }
+ break;
+ }
break;
case GI_INFO_TYPE_VFUNC:
case GI_INFO_TYPE_CALLBACK:
diff --git a/girepository/ginfo.c b/girepository/ginfo.c
index a3813d64..204583cd 100644
--- a/girepository/ginfo.c
+++ b/girepository/ginfo.c
@@ -1152,6 +1152,28 @@ g_enum_info_get_value (GIEnumInfo *info,
return (GIValueInfo *) g_info_new (GI_INFO_TYPE_VALUE, base, base->typelib, offset);
}
+/**
+ * g_enum_info_get_storage_type:
+ * @info: GIEnumInfo
+ *
+ * Gets the tag of the type used for the enum in the C ABI. This will
+ * will be a signed or unsigned integral type.
+
+ * Note that in the current implementation the width of the type is
+ * computed correctly, but the signed or unsigned nature of the type
+ * may not match the sign of the type used by the C compiler.
+ *
+ * Return Value: the storage type for the enumeration
+ */
+GITypeTag
+g_enum_info_get_storage_type (GIEnumInfo *info)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ EnumBlob *blob = (EnumBlob *)&base->typelib->data[base->offset];
+
+ return blob->storage_type;
+}
+
/* GIObjectInfo functions */
GIObjectInfo *
g_object_info_get_parent (GIObjectInfo *info)
diff --git a/girepository/girepository.h b/girepository/girepository.h
index a671cb5c..abeb8570 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -404,6 +404,7 @@ GType g_registered_type_info_get_g_type (GIRegisteredTypeInf
gint g_enum_info_get_n_values (GIEnumInfo *info);
GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
gint n);
+GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info);
/* GIObjectInfo */
diff --git a/girepository/girnode.c b/girepository/girnode.c
index 9c5cf5b6..8e9d5d1a 100644
--- a/girepository/girnode.c
+++ b/girepository/girnode.c
@@ -1952,6 +1952,7 @@ g_ir_node_build_typelib (GIrNode *node,
blob->deprecated = enum_->deprecated;
blob->reserved = 0;
+ blob->storage_type = enum_->storage_type;
blob->name = write_string (node->name, strings, data, offset2);
if (enum_->gtype_name)
{
diff --git a/girepository/girnode.h b/girepository/girnode.h
index 9829a933..674594d8 100644
--- a/girepository/girnode.h
+++ b/girepository/girnode.h
@@ -259,6 +259,7 @@ struct _GIrNodeEnum
GIrNode node;
gboolean deprecated;
+ gint storage_type;
gchar *gtype_name;
gchar *gtype_init;
diff --git a/girepository/giroffsets.c b/girepository/giroffsets.c
index 1844dd1b..46cdbd90 100644
--- a/girepository/giroffsets.c
+++ b/girepository/giroffsets.c
@@ -63,15 +63,15 @@ typedef enum {
/* etc... */
#endif
-static gboolean
-get_enum_size_alignment (GIrNodeEnum *enum_node,
- gint *size,
- gint *alignment)
+static void
+compute_enum_storage_type (GIrNodeEnum *enum_node)
{
GList *l;
guint32 max_value = 0;
int width;
- ffi_type *type_ffi;
+
+ if (enum_node->storage_type != GI_TYPE_TAG_VOID) /* already done */
+ return;
for (l = enum_node->values; l; l = l->next)
{
@@ -94,15 +94,48 @@ get_enum_size_alignment (GIrNodeEnum *enum_node,
width = sizeof (Enum6);
if (width == 1)
- type_ffi = &ffi_type_sint8;
+ enum_node->storage_type = GI_TYPE_TAG_UINT8;
else if (width == 2)
- type_ffi = &ffi_type_sint16;
+ enum_node->storage_type = GI_TYPE_TAG_UINT16;
else if (width == 4)
- type_ffi = &ffi_type_sint32;
+ enum_node->storage_type = GI_TYPE_TAG_UINT32;
else if (width == 8)
- type_ffi = &ffi_type_sint64;
+ enum_node->storage_type = GI_TYPE_TAG_UINT64;
else
g_error ("Unexpected enum width %d", width);
+}
+
+static gboolean
+get_enum_size_alignment (GIrNodeEnum *enum_node,
+ gint *size,
+ gint *alignment)
+{
+ ffi_type *type_ffi;
+
+ compute_enum_storage_type (enum_node);
+
+ switch (enum_node->storage_type)
+ {
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ type_ffi = &ffi_type_uint8;
+ break;
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ type_ffi = &ffi_type_uint16;
+ break;
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ type_ffi = &ffi_type_uint32;
+ break;
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ type_ffi = &ffi_type_uint64;
+ break;
+ default:
+ g_error ("Unexpected enum storage type %s",
+ g_type_tag_to_string (enum_node->storage_type));
+ }
*size = type_ffi->size;
*alignment = type_ffi->alignment;
@@ -459,6 +492,18 @@ g_ir_node_compute_offsets (GIrNode *node,
&union_->size, &union_->alignment);
break;
}
+ case G_IR_NODE_ENUM:
+ case G_IR_NODE_FLAGS:
+ {
+ GIrNodeEnum *enum_ = (GIrNodeEnum *)node;
+
+ if (enum_->storage_type != GI_TYPE_TAG_VOID) /* already done */
+ return;
+
+ compute_enum_storage_type (enum_);
+
+ break;
+ }
default:
/* Nothing to do */
return;
diff --git a/girepository/gtypelib.h b/girepository/gtypelib.h
index 1b2b8934..7db15db3 100644
--- a/girepository/gtypelib.h
+++ b/girepository/gtypelib.h
@@ -349,7 +349,8 @@ typedef struct
guint16 deprecated : 1;
guint16 unregistered : 1;
- guint16 reserved :14;
+ guint16 storage_type : 5;
+ guint16 reserved : 9;
guint32 name;