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; }
/** * g_value_init_from_instance: * @value: An uninitialized #GValue structure. * @instance: (type GObject.TypeInstance): the instance * * Initializes and sets @value from an instantiatable type via the * value_table's collect_value() function. * * Note: The @value will be initialised with the exact type of * @instance. If you wish to set the @value's type to a different GType * (such as a parent class GType), you need to manually call * g_value_init() and g_value_set_instance(). * * Since: 2.42 */ void g_value_init_from_instance (GValue *value, gpointer instance) { g_return_if_fail (value != NULL && G_VALUE_TYPE(value) == 0); if (G_IS_OBJECT (instance)) { /* Fast-path. * If G_IS_OBJECT() succeeds we know: * * that instance is present and valid * * that it is a GObject, and therefore we can directly * use the collect implementation (g_object_ref) */ value_meminit (value, G_TYPE_FROM_INSTANCE (instance)); value->data[0].v_pointer = g_object_ref (instance); } else { GType g_type; GTypeValueTable *value_table; GTypeCValue cvalue; gchar *error_msg; g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_type = G_TYPE_FROM_INSTANCE (instance); value_table = g_type_value_table_peek (g_type); g_return_if_fail (strcmp (value_table->collect_format, "p") == 0); memset (&cvalue, 0, sizeof (cvalue)); cvalue.v_pointer = instance; /* setup and collect */ value_meminit (value, g_type); value_table->value_init (value); error_msg = value_table->collect_value (value, 1, &cvalue, 0); if (error_msg) { g_warning ("%s: %s", G_STRLOC, error_msg); g_free (error_msg); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ value_meminit (value, g_type); value_table->value_init (value); } } }
/** * g_value_transform: * @src_value: Source value. * @dest_value: Target value. * * Tries to cast the contents of @src_value into a type appropriate * to store in @dest_value, e.g. to transform a %G_TYPE_INT value * into a %G_TYPE_FLOAT value. Performing transformations between * value types might incur precision lossage. Especially * transformations into strings might reveal seemingly arbitrary * results and shouldn't be relied upon for production code (such * as rcfile value or object property serialization). * * Returns: Whether a transformation rule was found and could be applied. * Upon failing transformations, @dest_value is left untouched. */ gboolean g_value_transform (const GValue *src_value, GValue *dest_value) { GType dest_type; g_return_val_if_fail (G_IS_VALUE (src_value), FALSE); g_return_val_if_fail (G_IS_VALUE (dest_value), FALSE); dest_type = G_VALUE_TYPE (dest_value); if (g_value_type_compatible (G_VALUE_TYPE (src_value), dest_type)) { g_value_copy (src_value, dest_value); return TRUE; } else { GValueTransform transform = transform_func_lookup (G_VALUE_TYPE (src_value), dest_type); if (transform) { g_value_unset (dest_value); /* setup and transform */ value_meminit (dest_value, dest_type); transform (src_value, dest_value); return TRUE; } } return FALSE; }
/** * g_value_init: * @value: A zero-filled (uninitialized) #GValue structure. * @g_type: Type the #GValue should hold values of. * * Initializes @value with the default value of @type. * * Returns: (transfer none): the #GValue structure that has been passed in */ GValue* g_value_init (GValue *value, GType g_type) { /* g_return_val_if_fail (G_TYPE_IS_VALUE (g_type), NULL); be more elaborate below */ g_return_val_if_fail (value != NULL, NULL); /* g_return_val_if_fail (G_VALUE_TYPE (value) == 0, NULL); be more elaborate below */ if (G_TYPE_IS_VALUE (g_type) && G_VALUE_TYPE (value) == 0) { GTypeValueTable *value_table = g_type_value_table_peek (g_type); /* setup and init */ value_meminit (value, g_type); value_table->value_init (value); } else if (G_VALUE_TYPE (value)) g_warning ("%s: cannot initialize GValue with type '%s', the value has already been initialized as '%s'", G_STRLOC, g_type_name (g_type), g_type_name (G_VALUE_TYPE (value))); else /* !G_TYPE_IS_VALUE (g_type) */ g_warning ("%s: cannot initialize GValue with type '%s', %s", G_STRLOC, g_type_name (g_type), g_type_value_table_peek (g_type) ? "this type is abstract with regards to GValue use, use a more specific (derived) type" : "this type has no GTypeValueTable implementation"); return value; }
/** * 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); } }
/** * g_value_set_instance: * @value: An initialized #GValue structure. * @instance: (allow-none): the instance * * Sets @value from an instantiatable type via the * value_table's collect_value() function. */ void g_value_set_instance (GValue *value, gpointer instance) { GType g_type; GTypeValueTable *value_table; GTypeCValue cvalue; gchar *error_msg; g_return_if_fail (G_IS_VALUE (value)); if (instance) { g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (instance), G_VALUE_TYPE (value))); } g_type = G_VALUE_TYPE (value); value_table = g_type_value_table_peek (g_type); g_return_if_fail (strcmp (value_table->collect_format, "p") == 0); memset (&cvalue, 0, sizeof (cvalue)); cvalue.v_pointer = instance; /* make sure value's value is free()d */ if (value_table->value_free) value_table->value_free (value); /* setup and collect */ value_meminit (value, g_type); error_msg = value_table->collect_value (value, 1, &cvalue, 0); if (error_msg) { g_warning ("%s: %s", G_STRLOC, error_msg); g_free (error_msg); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ value_meminit (value, g_type); value_table->value_init (value); } }
/** * g_value_reset: * @value: An initialized #GValue structure. * * Clears the current value in @value and resets it to the default value * (as if the value had just been initialized). * * Returns: the #GValue structure that has been passed in */ GValue* g_value_reset (GValue *value) { GTypeValueTable *value_table; GType g_type; g_return_val_if_fail (G_IS_VALUE (value), NULL); g_type = G_VALUE_TYPE (value); value_table = g_type_value_table_peek (g_type); /* make sure value's value is free()d */ if (value_table->value_free) value_table->value_free (value); /* setup and init */ value_meminit (value, g_type); value_table->value_init (value); return value; }
/** * g_value_copy: * @src_value: An initialized #GValue structure. * @dest_value: An initialized #GValue structure of the same type as @src_value. * * Copies the value of @src_value into @dest_value. */ void g_value_copy (const GValue *src_value, GValue *dest_value) { g_return_if_fail (G_IS_VALUE (src_value)); g_return_if_fail (G_IS_VALUE (dest_value)); g_return_if_fail (g_value_type_compatible (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value))); if (src_value != dest_value) { GType dest_type = G_VALUE_TYPE (dest_value); GTypeValueTable *value_table = g_type_value_table_peek (dest_type); /* make sure dest_value's value is free()d */ if (value_table->value_free) value_table->value_free (dest_value); /* setup and copy */ value_meminit (dest_value, dest_type); value_table->value_copy (src_value, dest_value); } }