[perl-Glib-Object-Introspection] Support more struct types when writing fields



commit d2abe8c2717e6b4cbafaf81cc50e029ca528cb13
Author: Torsten SchÃnfeld <kaffeetisch gmx de>
Date:   Sat Aug 11 20:27:57 2012 +0200

    Support more struct types when writing fields
    
    Specifically, boxed pointers and raw struct pointers.

 NEWS               |    5 +++
 gperl-i11n-field.c |   79 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 62 insertions(+), 22 deletions(-)
---
diff --git a/NEWS b/NEWS
index 9343399..0c57526 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Overview of changes in Glib::Object::Introspection 0.012
+========================================================
+
+* Support more struct types when writing fields.
+
 Overview of changes in Glib::Object::Introspection 0.011
 ========================================================
 
diff --git a/gperl-i11n-field.c b/gperl-i11n-field.c
index e5880e4..f991dbb 100644
--- a/gperl-i11n-field.c
+++ b/gperl-i11n-field.c
@@ -92,37 +92,72 @@ get_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer)
 }
 
 static void
-set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *value)
+set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *sv)
 {
 	GITypeInfo *field_type;
 	GIBaseInfo *interface_info;
+	GITypeTag tag;
+	GIInfoType info_type;
 	GIArgument arg;
 
 	field_type = g_field_info_get_type (field_info);
+	tag = g_type_info_get_tag (field_type);
 	interface_info = g_type_info_get_interface (field_type);
+	info_type = interface_info
+		? g_base_info_get_type (interface_info)
+		: GI_INFO_TYPE_INVALID;
 
-	/* FIXME: No GIArgInfo and no
-	 * GPerlI11nInvocationInfo here.  What if the
-	 * struct contains an object pointer, or a
-	 * callback field?  And is it OK to always
-	 * allow undef? */
-
-	/* This case is not handled by g_field_info_set_field. */
-	if (!g_type_info_is_pointer (field_type) &&
-	    g_type_info_get_tag (field_type) == GI_TYPE_TAG_INTERFACE &&
-	    g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT)
+	/* Structs are not handled by g_field_info_set_field. */
+	if (tag == GI_TYPE_TAG_INTERFACE &&
+	    info_type == GI_INFO_TYPE_STRUCT)
 	{
-		gsize offset;
-		gssize size;
-		/* Enforce GI_TRANSFER_NOTHING since we will copy into the
-		 * memory that has already been allocated inside 'mem' */
-		sv_to_arg (value, &arg, NULL, field_type,
-		           GI_TRANSFER_NOTHING, TRUE, NULL);
-		offset = g_field_info_get_offset (field_info);
-		size = g_struct_info_get_size (interface_info);
-		g_memmove (mem + offset, arg.v_pointer, size);
-	} else {
-		sv_to_arg (value, &arg, NULL, field_type,
+		/* FIXME: No GIArgInfo and no GPerlI11nInvocationInfo here.
+		 * What if the struct contains an object pointer, or a callback
+		 * field? */
+		gsize offset = g_field_info_get_offset (field_info);
+		if (!g_type_info_is_pointer (field_type)) {	/* By value */
+			gssize size;
+			/* Enforce GI_TRANSFER_NOTHING since we will copy into
+			 * the memory that has already been allocated inside
+			 * 'mem' */
+			arg.v_pointer = sv_to_struct (GI_TRANSFER_NOTHING,
+			                              interface_info,
+			                              info_type,
+			                              sv);
+			size = g_struct_info_get_size (interface_info);
+			g_memmove (mem + offset, arg.v_pointer, size);
+		} else {					/* Pointer */
+			GType gtype = get_gtype (interface_info);
+			if (g_type_is_a (gtype, G_TYPE_BOXED)) {
+				gpointer old = G_STRUCT_MEMBER (gpointer, mem, offset);
+				/* GI_TRANSFER_NOTHING because we handle the
+				 * memory ourselves here. */
+				sv_to_interface (NULL, field_type, GI_TRANSFER_NOTHING,
+				                 TRUE, sv, &arg, NULL);
+				if (arg.v_pointer != old) {
+					if (old)
+						g_boxed_free (gtype, old);
+					G_STRUCT_MEMBER (gpointer, mem, offset) =
+						arg.v_pointer
+						? g_boxed_copy (gtype, arg.v_pointer)
+						: NULL;
+				}
+			} else {
+				g_assert (gtype == G_TYPE_INVALID || gtype == G_TYPE_NONE);
+				/* We have no way to know how to manage the
+				 * memory here, so we just stuff the pointer in
+				 * directly. */
+				G_STRUCT_MEMBER (gpointer, mem, offset) =
+					sv_to_struct (GI_TRANSFER_NOTHING,
+					              interface_info,
+					              info_type,
+					              sv);
+			}
+		}
+	}
+
+	else {
+		sv_to_arg (sv, &arg, NULL, field_type,
 		           transfer, TRUE, NULL);
 		if (!g_field_info_set_field (field_info, mem, &arg))
 			ccroak ("Could not set field '%s'",



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