/**
 * g_variant_is_normal_form:
 * @value: a #GVariant instance
 * @returns: %TRUE if @value is in normal form
 *
 * 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.
 *
 * 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_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;
  }
}
Exemple #6
0
/**
 * 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);
}