gobject-introspection r944 - in trunk: . docs girepository



Author: otaylor
Date: Tue Nov 18 12:29:10 2008
New Revision: 944
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=944&view=rev

Log:
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

Modified:
   trunk/ChangeLog
   trunk/docs/typelib-format.txt
   trunk/girepository/gfield.c
   trunk/girepository/ginfo.c
   trunk/girepository/girepository.h
   trunk/girepository/girnode.c
   trunk/girepository/girnode.h
   trunk/girepository/giroffsets.c
   trunk/girepository/gtypelib.h

Modified: trunk/docs/typelib-format.txt
==============================================================================
--- trunk/docs/typelib-format.txt	(original)
+++ trunk/docs/typelib-format.txt	Tue Nov 18 12:29:10 2008
@@ -856,7 +856,8 @@
   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 @@
 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.
 

Modified: trunk/girepository/gfield.c
==============================================================================
--- trunk/girepository/gfield.c	(original)
+++ trunk/girepository/gfield.c	Tue Nov 18 12:29:10 2008
@@ -1,4 +1,7 @@
+#include <string.h>
+
 #include "girepository.h"
+#include "girffi.h"
 
 /**
  * g_field_info_get_field:
@@ -117,11 +120,55 @@
 		  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 @@
 		  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:

Modified: trunk/girepository/ginfo.c
==============================================================================
--- trunk/girepository/ginfo.c	(original)
+++ trunk/girepository/ginfo.c	Tue Nov 18 12:29:10 2008
@@ -1152,6 +1152,28 @@
   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)

Modified: trunk/girepository/girepository.h
==============================================================================
--- trunk/girepository/girepository.h	(original)
+++ trunk/girepository/girepository.h	Tue Nov 18 12:29:10 2008
@@ -404,6 +404,7 @@
 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 */
 

Modified: trunk/girepository/girnode.c
==============================================================================
--- trunk/girepository/girnode.c	(original)
+++ trunk/girepository/girnode.c	Tue Nov 18 12:29:10 2008
@@ -1952,6 +1952,7 @@
 	  
 	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)
 	  {

Modified: trunk/girepository/girnode.h
==============================================================================
--- trunk/girepository/girnode.h	(original)
+++ trunk/girepository/girnode.h	Tue Nov 18 12:29:10 2008
@@ -259,6 +259,7 @@
   GIrNode node;
 
   gboolean deprecated;
+  gint storage_type;
 
   gchar *gtype_name;
   gchar *gtype_init;

Modified: trunk/girepository/giroffsets.c
==============================================================================
--- trunk/girepository/giroffsets.c	(original)
+++ trunk/girepository/giroffsets.c	Tue Nov 18 12:29:10 2008
@@ -63,15 +63,15 @@
 /* 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 @@
     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 @@
 				     &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;

Modified: trunk/girepository/gtypelib.h
==============================================================================
--- trunk/girepository/gtypelib.h	(original)
+++ trunk/girepository/gtypelib.h	Tue Nov 18 12:29:10 2008
@@ -349,7 +349,8 @@
 
   guint16   deprecated   : 1; 
   guint16   unregistered : 1;
-  guint16   reserved     :14;
+  guint16   storage_type : 5;
+  guint16   reserved     : 9;
 
   guint32   name; 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]