/** * g_value_register_transform_func: (skip) * @src_type: Source type. * @dest_type: Target type. * @transform_func: a function which transforms values of type @src_type * into value of type @dest_type * * Registers a value transformation function for use in g_value_transform(). * A previously registered transformation function for @src_type and @dest_type * will be replaced. */ void g_value_register_transform_func (GType src_type, GType dest_type, GValueTransform transform_func) { TransformEntry entry; /* these checks won't pass for dynamic types. * g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (src_type)); * g_return_if_fail (G_TYPE_HAS_VALUE_TABLE (dest_type)); */ g_return_if_fail (transform_func != NULL); entry.src_type = src_type; entry.dest_type = dest_type; #if 0 /* let transform function replacement be a valid operation */ if (g_bsearch_array_lookup (transform_array, &transform_bconfig, &entry)) g_warning ("reregistering value transformation function (%p) for '%s' to '%s'", transform_func, g_type_name (src_type), g_type_name (dest_type)); #endif entry.func = transform_func; transform_array = g_bsearch_array_replace (transform_array, &transform_bconfig, &entry); }
static gchar* boxed_proxy_lcopy_value (const GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags) { gpointer *boxed_p = collect_values[0].v_pointer; if (!boxed_p) return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); if (!value->data[0].v_pointer) *boxed_p = NULL; else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) *boxed_p = value->data[0].v_pointer; else { BoxedNode key, *node; key.type = G_VALUE_TYPE (value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); *boxed_p = node->copy (value->data[0].v_pointer); } return NULL; }
static GValueTransform transform_func_lookup (GType src_type, GType dest_type) { TransformEntry entry; entry.src_type = src_type; do { entry.dest_type = dest_type; do { TransformEntry *e; e = g_bsearch_array_lookup (transform_array, &transform_bconfig, &entry); if (e) { /* need to check that there hasn't been a change in value handling */ if (g_type_value_table_peek (entry.dest_type) == g_type_value_table_peek (dest_type) && g_type_value_table_peek (entry.src_type) == g_type_value_table_peek (src_type)) return e->func; } entry.dest_type = g_type_parent (entry.dest_type); } while (entry.dest_type); entry.src_type = g_type_parent (entry.src_type); } while (entry.src_type); return NULL; }
/** * g_boxed_free: * @boxed_type: The type of @boxed. * @boxed: The boxed structure to be freed. * * Free the boxed structure @boxed which is of type @boxed_type. */ void g_boxed_free (GType boxed_type, gpointer boxed) { GTypeValueTable *value_table; g_return_if_fail (G_TYPE_IS_BOXED (boxed_type)); g_return_if_fail (G_TYPE_IS_ABSTRACT (boxed_type) == FALSE); g_return_if_fail (boxed != NULL); value_table = g_type_value_table_peek (boxed_type); if (!value_table) g_return_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type)); /* check if our proxying implementation is used, we can short-cut here */ if (value_table->value_free == boxed_proxy_value_free) { BoxedNode key, *node; key.type = boxed_type; node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); node->free (boxed); } else { GValue value; /* see g_boxed_copy() on why we think we can do this */ value_meminit (&value, boxed_type); value.data[0].v_pointer = boxed; value_table->value_free (&value); } }
static gchar* boxed_proxy_collect_value (GValue *value, guint n_collect_values, GTypeCValue *collect_values, guint collect_flags) { BoxedNode key, *node; key.type = G_VALUE_TYPE (value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); if (!collect_values[0].v_pointer) value->data[0].v_pointer = NULL; else { if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { value->data[0].v_pointer = collect_values[0].v_pointer; value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS; } else value->data[0].v_pointer = node->copy (collect_values[0].v_pointer); } return NULL; }
gpointer g_boxed_copy (GType boxed_type, gconstpointer src_boxed) { GTypeValueTable *value_table; gpointer dest_boxed; g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL); g_return_val_if_fail (G_TYPE_IS_ABSTRACT (boxed_type) == FALSE, NULL); g_return_val_if_fail (src_boxed != NULL, NULL); value_table = g_type_value_table_peek (boxed_type); if (!value_table) g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL); /* check if our proxying implementation is used, we can short-cut here */ if (value_table->value_copy == boxed_proxy_value_copy) { BoxedNode key, *node; key.type = boxed_type; node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); dest_boxed = node->copy ((gpointer) src_boxed); } else { GValue src_value, dest_value; /* we heavil rely on third-party boxed type value vtable * implementations to follow normal boxed value storage * (data[0].v_pointer is the boxed struct, and * data[1].v_uint holds the G_VALUE_NOCOPY_CONTENTS flag, * rest zero). * but then, we can expect that since we layed out the * g_boxed_*() API. * data[1].v_uint&G_VALUE_NOCOPY_CONTENTS shouldn't be set * after a copy. */ /* equiv. to g_value_set_static_boxed() */ value_meminit (&src_value, boxed_type); src_value.data[0].v_pointer = (gpointer) src_boxed; src_value.data[1].v_uint = G_VALUE_NOCOPY_CONTENTS; /* call third-party code copy fucntion, fingers-crossed */ value_meminit (&dest_value, boxed_type); value_table->value_copy (&src_value, &dest_value); /* double check and grouse if things went wrong */ if (dest_value.data[1].v_ulong || dest_value.data[2].v_ulong) g_warning ("the copy_value() implementation of type `%s' seems to make use of reserved GValue fields", g_type_name (boxed_type)); dest_boxed = dest_value.data[0].v_pointer; } return dest_boxed; }
static void boxed_proxy_value_init (GValue *value) { BoxedNode key, *node; key.type = G_VALUE_TYPE (value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); value->data[0].v_pointer = NULL; }
static void boxed_proxy_value_free (GValue *value) { if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)) { BoxedNode key, *node; key.type = G_VALUE_TYPE (value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); node->free (value->data[0].v_pointer); } }
static void boxed_proxy_value_copy (const GValue *src_value, GValue *dest_value) { if (src_value->data[0].v_pointer) { BoxedNode key, *node; key.type = G_VALUE_TYPE (src_value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); dest_value->data[0].v_pointer = node->copy (src_value->data[0].v_pointer); } else dest_value->data[0].v_pointer = src_value->data[0].v_pointer; }
static inline void value_set_boxed_internal (GValue *value, gconstpointer const_boxed, gboolean need_copy, gboolean need_free) { BoxedNode key, *node; gpointer boxed = (gpointer) const_boxed; if (!boxed) { /* just resetting to NULL might not be desired, need to * have value reinitialized also (for values defaulting * to other default value states than a NULL data pointer), * g_value_reset() will handle this */ g_value_reset (value); return; } key.type = G_VALUE_TYPE (value); node = g_bsearch_array_lookup (boxed_bsa, &boxed_bconfig, &key); if (node) { /* we proxy this type, free contents and copy right away */ if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)) node->free (value->data[0].v_pointer); value->data[1].v_uint = need_free ? 0 : G_VALUE_NOCOPY_CONTENTS; value->data[0].v_pointer = need_copy ? node->copy (boxed) : boxed; } else { /* we don't handle this type, free contents and let g_boxed_copy() * figure what's required */ if (value->data[0].v_pointer && !(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)) g_boxed_free (G_VALUE_TYPE (value), value->data[0].v_pointer); value->data[1].v_uint = need_free ? 0 : G_VALUE_NOCOPY_CONTENTS; value->data[0].v_pointer = need_copy ? g_boxed_copy (G_VALUE_TYPE (value), boxed) : boxed; } }