+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
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;
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.
+#include <string.h>
+
#include "girepository.h"
+#include "girffi.h"
/**
* g_field_info_get_field:
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;
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:
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)
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 */
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)
{
GIrNode node;
gboolean deprecated;
+ gint storage_type;
gchar *gtype_name;
gchar *gtype_init;
/* 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)
{
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;
&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;
guint16 deprecated : 1;
guint16 unregistered : 1;
- guint16 reserved :14;
+ guint16 storage_type : 5;
+ guint16 reserved : 9;
guint32 name;