/** * g_variant_get_child_value: * @value: a container #GVariant * @index_: the index of the child to fetch * * Reads a child item out of a container #GVariant instance. This * includes variants, maybes, arrays, tuples and dictionary * entries. It is an error to call this function on any other type of * #GVariant. * * It is an error if @index_ is greater than the number of child items * in the container. See g_variant_n_children(). * * The returned value is never floating. You should free it with * g_variant_unref() when you're done with it. * * This function is O(1). * * Returns: (transfer full): the child at the specified index * * Since: 2.24 **/ GVariant * g_variant_get_child_value (GVariant *value, gsize index_) { g_return_val_if_fail (index_ < g_variant_n_children (value), NULL); if (~g_atomic_int_get (&value->state) & STATE_SERIALISED) { g_variant_lock (value); if (~value->state & STATE_SERIALISED) { GVariant *child; child = g_variant_ref (value->contents.tree.children[index_]); g_variant_unlock (value); return child; } g_variant_unlock (value); } { GVariantSerialised serialised = { value->type_info, (gpointer) value->contents.serialised.data, value->size }; GVariantSerialised s_child; GVariant *child; /* get the serialiser to extract the serialised data for the child * from the serialised data for the container */ s_child = g_variant_serialised_get_child (serialised, index_); /* create a new serialised instance out of it */ child = g_slice_new (GVariant); #ifdef GSTREAMER_LITE if (child == NULL) { return NULL; } #endif // GSTREAMER_LITE child->type_info = s_child.type_info; child->state = (value->state & STATE_TRUSTED) | STATE_SERIALISED; child->size = s_child.size; child->ref_count = 1; child->contents.serialised.bytes = g_bytes_ref (value->contents.serialised.bytes); child->contents.serialised.data = s_child.data; return child; } }
/** * g_variant_is_normal_form: * @value: a #GVariant instance * * Checks if @value is in normal form. * * The main reason to do this is to detect if a given chunk of * serialised data is in normal form: load the data into a #GVariant * using g_variant_new_from_data() and then use this function to * check. * * If @value is found to be in normal form then it will be marked as * being trusted. If the value was already marked as being trusted then * this function will immediately return %TRUE. * * Returns: %TRUE if @value is in normal form * * Since: 2.24 **/ gboolean g_variant_is_normal_form (GVariant *value) { if (value->state & STATE_TRUSTED) return TRUE; g_variant_lock (value); if (value->state & STATE_SERIALISED) { GVariantSerialised serialised = { value->type_info, (gpointer) value->contents.serialised.data, value->size }; if (g_variant_serialised_is_normal (serialised)) value->state |= STATE_TRUSTED; } else { gboolean normal = TRUE; gsize i; for (i = 0; i < value->contents.tree.n_children; i++) normal &= g_variant_is_normal_form (value->contents.tree.children[i]); if (normal) value->state |= STATE_TRUSTED; } g_variant_unlock (value); return (value->state & STATE_TRUSTED) != 0; }
/** * g_variant_get_data: * @value: a #GVariant instance * * Returns a pointer to the serialised form of a #GVariant instance. * The returned data may not be in fully-normalised form if read from an * untrusted source. The returned data must not be freed; it remains * valid for as long as @value exists. * * If @value is a fixed-sized value that was deserialised from a * corrupted serialised container then %NULL may be returned. In this * case, the proper thing to do is typically to use the appropriate * number of nul bytes in place of @value. If @value is not fixed-sized * then %NULL is never returned. * * In the case that @value is already in serialised form, this function * is O(1). If the value is not already in serialised form, * serialisation occurs implicitly and is approximately O(n) in the size * of the result. * * To deserialise the data returned by this function, in addition to the * serialised data, you must know the type of the #GVariant, and (if the * machine might be different) the endianness of the machine that stored * it. As a result, file formats or network messages that incorporate * serialised #GVariants must include this information either * implicitly (for instance "the file always contains a * %G_VARIANT_TYPE_VARIANT and it is always in little-endian order") or * explicitly (by storing the type and/or endianness in addition to the * serialised data). * * Returns: (transfer none): the serialised form of @value, or %NULL * * Since: 2.24 **/ 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_size: * @value: a #GVariant instance * * Determines the number of bytes that would be required to store @value * with g_variant_store(). * * If @value has a fixed-sized type then this function always returned * that fixed size. * * In the case that @value is already in serialised form or the size has * already been calculated (ie: this function has been called before) * then this function is O(1). Otherwise, the size is calculated, an * operation which is approximately O(n) in the number of values * involved. * * Returns: the serialised size of @value * * Since: 2.24 **/ gsize g_variant_get_size (GVariant *value) { g_variant_lock (value); g_variant_ensure_size (value); g_variant_unlock (value); return value->size; }
/** * 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) { g_variant_lock (value); g_variant_ensure_serialised (value); g_variant_unlock (value); return g_bytes_ref (value->contents.serialised.bytes); }
/** * g_variant_ref_sink: * @value: a #GVariant * @returns: the same @value * * #GVariant uses a floating reference count system. All functions with * names starting with <literal>g_variant_new_</literal> return floating * references. * * Calling g_variant_ref_sink() on a #GVariant with a floating reference * will convert the floating reference into a full reference. Calling * g_variant_ref_sink() on a non-floating #GVariant results in an * additional normal reference being added. * * In other words, if the @value is floating, then this call "assumes * ownership" of the floating reference, converting it to a normal * reference. If the @value is not floating, then this call adds a * new normal reference increasing the reference count by one. * * All calls that result in a #GVariant instance being inserted into a * container will call g_variant_ref_sink() on the instance. This means * that if the value was just created (and has only its floating * reference) then the container will assume sole ownership of the value * at that point and the caller will not need to unreference it. This * makes certain common styles of programming much easier while still * maintaining normal refcounting semantics in situations where values * are not floating. * * Since: 2.24 **/ GVariant * g_variant_ref_sink (GVariant *value) { g_variant_lock (value); if (~value->state & STATE_FLOATING) g_variant_ref (value); else value->state &= ~STATE_FLOATING; g_variant_unlock (value); return value; }
/** * g_variant_ref_sink: * @value: a #GVariant * * #GVariant uses a floating reference count system. All functions with * names starting with `g_variant_new_` return floating * references. * * Calling g_variant_ref_sink() on a #GVariant with a floating reference * will convert the floating reference into a full reference. Calling * g_variant_ref_sink() on a non-floating #GVariant results in an * additional normal reference being added. * * In other words, if the @value is floating, then this call "assumes * ownership" of the floating reference, converting it to a normal * reference. If the @value is not floating, then this call adds a * new normal reference increasing the reference count by one. * * All calls that result in a #GVariant instance being inserted into a * container will call g_variant_ref_sink() on the instance. This means * that if the value was just created (and has only its floating * reference) then the container will assume sole ownership of the value * at that point and the caller will not need to unreference it. This * makes certain common styles of programming much easier while still * maintaining normal refcounting semantics in situations where values * are not floating. * * Returns: the same @value * * Since: 2.24 **/ GVariant * g_variant_ref_sink (GVariant *value) { g_return_val_if_fail (value != NULL, NULL); g_return_val_if_fail (value->ref_count > 0, NULL); g_variant_lock (value); if (~value->state & STATE_FLOATING) g_variant_ref (value); else value->state &= ~STATE_FLOATING; g_variant_unlock (value); return value; }
/** * g_variant_store: * @value: the #GVariant to store * @data: the location to store the serialised data at * * Stores the serialised form of @value at @data. @data should be * large enough. See g_variant_get_size(). * * The stored data is in machine native byte order but may not be in * fully-normalised form if read from an untrusted source. See * g_variant_get_normal_form() for a solution. * * As with g_variant_get_data(), to be able to deserialise the * serialised variant successfully, its type and (if the destination * machine might be different) its endianness must also be available. * * This function is approximately O(n) in the size of @data. * * Since: 2.24 **/ void g_variant_store (GVariant *value, gpointer data) { g_variant_lock (value); if (value->state & STATE_SERIALISED) { if (value->contents.serialised.data != NULL) memcpy (data, value->contents.serialised.data, value->size); else memset (data, 0, value->size); } else g_variant_serialise (value, data); g_variant_unlock (value); }
/** * 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: * @value: a container #GVariant * * Determines the number of children in a container #GVariant instance. * This includes variants, maybes, arrays, tuples and dictionary * entries. It is an error to call this function on any other type of * #GVariant. * * For variants, the return value is always 1. For values with maybe * types, it is always zero or one. For arrays, it is the length of the * array. For tuples it is the number of tuple items (which depends * only on the type). For dictionary entries, it is always 2 * * This function is O(1). * * Returns: the number of children in the container * * Since: 2.24 **/ gsize g_variant_n_children (GVariant *value) { gsize n_children; g_variant_lock (value); if (value->state & STATE_SERIALISED) { GVariantSerialised serialised = { value->type_info, (gpointer) value->contents.serialised.data, value->size }; n_children = g_variant_serialised_n_children (serialised); } else n_children = value->contents.tree.n_children; g_variant_unlock (value); return n_children; }
/* < private > * g_variant_fill_gvs: * @serialised: a pointer to a #GVariantSerialised * @data: a #GVariant instance * * This is the callback that is passed by a tree-form container instance * to the serialiser. This callback gets called on each child of the * container. Each child is responsible for performing the following * actions: * * - reporting its type * * - reporting its serialised size (requires knowing the size first) * * - possibly storing its serialised form into the provided buffer */ static void g_variant_fill_gvs (GVariantSerialised *serialised, gpointer data) { GVariant *value = data; g_variant_lock (value); g_variant_ensure_size (value); g_variant_unlock (value); if (serialised->type_info == NULL) serialised->type_info = value->type_info; g_assert (serialised->type_info == value->type_info); if (serialised->size == 0) serialised->size = value->size; g_assert (serialised->size == value->size); if (serialised->data) /* g_variant_store() is a public API, so it * it will reacquire the lock if it needs to. */ g_variant_store (value, serialised->data); }