X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgvariant-core.c;h=1a0c0415a655b63ddd867cc9ceb2c80af32c4c85;hb=1a3783987be7aa436c4b0789ce019289773d5018;hp=0d501150e73d700dbfd21b0063204d71ae9bb781;hpb=11a21a2a1c2b2d7e0ea1339a8596a2e05c55dfe3;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c index 0d50115..1a0c041 100644 --- a/glib/gvariant-core.c +++ b/glib/gvariant-core.c @@ -19,6 +19,7 @@ #include "config.h" #include +#include "glib-private.h" #include #include @@ -401,15 +402,11 @@ g_variant_fill_gvs (GVariantSerialised *serialised, * that size and serialises the instance into the buffer. The * 'children' array is then released and the instance is set to * serialised form based on the contents of the buffer. - * - * The current thread must hold the lock on @value. */ static void g_variant_ensure_serialised (GVariant *value) { - g_assert (value->state & STATE_LOCKED); - - if (~value->state & STATE_SERIALISED) + if (g_variant_lock_in_tree_form (value)) { GBytes *bytes; gpointer data; @@ -423,9 +420,66 @@ g_variant_ensure_serialised (GVariant *value) value->contents.serialised.data = g_bytes_get_data (bytes, NULL); value->contents.serialised.bytes = bytes; value->state |= STATE_SERIALISED; + + g_variant_unlock (value); } } +/* Now we have the code to recursively serialise a GVariant into a + * GVariantVectors structure. + * + * We want to do this in cases where the GVariant contains large chunks + * of serialised data in order to avoid having to copy this data. + * + * This generally works the same as normal serialising (co-recursion + * with the serialiser) but instead of using a callback we just hard-code + * the callback with the name g_variant_callback_write_to_vectors(). + * + * This is a private API that will be used by GDBus. + */ +gsize +g_variant_callback_write_to_vectors (GVariantVectors *vectors, + gpointer data, + GVariantTypeInfo **type_info) +{ + GVariant *value = data; + + if (g_variant_lock_in_tree_form (value)) + { + g_variant_serialiser_write_to_vectors (vectors, value->type_info, value->size, + (gpointer *) value->contents.tree.children, + value->contents.tree.n_children); + + g_variant_unlock (value); + } + else + g_variant_vectors_append_gbytes (vectors, value->contents.serialised.bytes, + value->contents.serialised.data, value->size); + + if (type_info) + *type_info = value->type_info; + + return value->size; +} + +/* < private > + * g_variant_serialise_to_vectors: + * @value: a #GVariant + * @vectors: (out): the result + * + * Serialises @value into @vectors. + * + * The caller must free @vectors. + */ +void +g_variant_to_vectors (GVariant *value, + GVariantVectors *vectors) +{ + g_variant_vectors_init (vectors); + + g_variant_callback_write_to_vectors (vectors, value, NULL); +} + /* < private > * g_variant_alloc: * @type: the type of the new instance @@ -455,58 +509,6 @@ g_variant_alloc (const GVariantType *type, return value; } -/** - * g_variant_new_from_bytes: - * @type: a #GVariantType - * @bytes: a #GBytes - * @trusted: if the contents of @bytes are trusted - * - * Constructs a new serialised-mode #GVariant instance. This is the - * inner interface for creation of new serialised values that gets - * called from various functions in gvariant.c. - * - * A reference is taken on @bytes. - * - * Returns: (transfer none): a new #GVariant with a floating reference - * - * Since: 2.36 - */ -GVariant * -g_variant_new_from_bytes (const GVariantType *type, - GBytes *bytes, - gboolean trusted) -{ - GVariant *value; - guint alignment; - gsize size; - - value = g_variant_alloc (type, TRUE, trusted); - - value->contents.serialised.bytes = g_bytes_ref (bytes); - - g_variant_type_info_query (value->type_info, - &alignment, &size); - - if (size && g_bytes_get_size (bytes) != size) - { - /* Creating a fixed-sized GVariant with a bytes of the wrong - * size. - * - * We should do the equivalent of pulling a fixed-sized child out - * of a brozen container (ie: data is NULL size is equal to the correct - * fixed size). - */ - value->contents.serialised.data = NULL; - value->size = size; - } - else - { - value->contents.serialised.data = g_bytes_get_data (bytes, &value->size); - } - - return value; -} - /* -- internal -- */ /* < internal > @@ -517,7 +519,7 @@ g_variant_new_from_bytes (const GVariantType *type, * @trusted: %TRUE if every child in @children in trusted * * Constructs a new tree-mode #GVariant instance. This is the inner - * interface for creation of new serialised values that gets called from + * interface for creation of new tree-mode values that gets called from * various functions in gvariant.c. * * @children is consumed by this function. g_free() will be called on @@ -543,6 +545,63 @@ g_variant_new_from_children (const GVariantType *type, } /* < internal > + * g_variant_new_serialised: + * @type: a #GVariantType + * @bytes: the #GBytes holding @data + * @data: a pointer to the serialised data + * @size: the size of @data, in bytes + * @trusted: %TRUE if @data is trusted + * + * Constructs a new serialised #GVariant instance. This is the inner + * interface for creation of new serialised values that gets called from + * various functions in gvariant.c. + * + * @bytes is consumed by this function. g_bytes_unref() will be called + * on it some time later. + * + * Returns: a new #GVariant with a floating reference + */ +GVariant * +g_variant_new_serialised (const GVariantType *type, + GBytes *bytes, + gconstpointer data, + gsize size, + gboolean trusted) +{ + GVariant *value; + gsize fixed_size; + + value = g_variant_alloc (type, TRUE, trusted); + value->contents.serialised.bytes = bytes; + value->contents.serialised.data = data; + value->size = size; + + g_variant_type_info_query (value->type_info, NULL, &fixed_size); + if G_UNLIKELY (fixed_size && size != fixed_size) + { + /* Creating a fixed-sized GVariant with a bytes of the wrong + * size. + * + * We should do the equivalent of pulling a fixed-sized child out + * of a broken container (ie: data is NULL size is equal to the correct + * fixed size). + * + * This really ought not to happen if the data is trusted... + */ + if (trusted) + g_error ("Attempting to create a trusted GVariant instance out of invalid data"); + + /* We hang on to the GBytes (even though we don't use it anymore) + * because every GVariant must have a GBytes. + */ + value->contents.serialised.data = NULL; + value->size = fixed_size; + } + + return value; +} + +/* < internal > * g_variant_get_type_info: * @value: a #GVariant * @@ -580,6 +639,32 @@ g_variant_is_trusted (GVariant *value) return (value->state & STATE_TRUSTED) != 0; } +/* < internal > + * g_variant_get_serialised: + * @value: a #GVariant + * @bytes: (out) (transfer none): a location to store the #GBytes + * @size: (out): a location to store the size of the returned data + * + * Ensures that @value is in serialised form and returns information + * about it. This is called from various APIs in gvariant.c + * + * Returns: data, of length @size + */ +gconstpointer +g_variant_get_serialised (GVariant *value, + GBytes **bytes, + gsize *size) +{ + g_variant_ensure_serialised (value); + + if (bytes) + *bytes = value->contents.serialised.bytes; + + *size = value->size; + + return value->contents.serialised.data; +} + /* -- public -- */ /** @@ -826,49 +911,11 @@ g_variant_get_size (GVariant *value) gconstpointer g_variant_get_data (GVariant *value) { - g_variant_lock (value); g_variant_ensure_serialised (value); - g_variant_unlock (value); return value->contents.serialised.data; } -/** - * g_variant_get_data_as_bytes: - * @value: a #GVariant - * - * Returns a pointer to the serialised form of a #GVariant instance. - * The semantics of this function are exactly the same as - * g_variant_get_data(), except that the returned #GBytes holds - * a reference to the variant data. - * - * Returns: (transfer full): A new #GBytes representing the variant data - * - * Since: 2.36 - */ -GBytes * -g_variant_get_data_as_bytes (GVariant *value) -{ - const gchar *bytes_data; - const gchar *data; - gsize bytes_size; - gsize size; - - g_variant_lock (value); - g_variant_ensure_serialised (value); - g_variant_unlock (value); - - bytes_data = g_bytes_get_data (value->contents.serialised.bytes, &bytes_size); - data = value->contents.serialised.data; - size = value->size; - - if (data == bytes_data && size == bytes_size) - return g_bytes_ref (value->contents.serialised.bytes); - else - return g_bytes_new_from_bytes (value->contents.serialised.bytes, - data - bytes_data, size); -} - /** * g_variant_n_children: