[kdbus] sync with kdbus (kdbus.h - commit: 5ae1ecac44cb)
[platform/upstream/glib.git] / glib / gvariant.c
index 93d2278..2fc71ab 100644 (file)
  * in the gio library, for those.)
  *
  * For space-efficiency, the #GVariant serialisation format does not
- * automatically include the variant's type or endianness, which must
- * either be implied from context (such as knowledge that a particular
- * file format always contains a little-endian %G_VARIANT_TYPE_VARIANT)
- * or supplied out-of-band (for instance, a type and/or endianness
+ * automatically include the variant's length, type or endianness,
+ * which must either be implied from context (such as knowledge that a
+ * particular file format always contains a little-endian
+ * %G_VARIANT_TYPE_VARIANT which occupies the whole length of the file)
+ * or supplied out-of-band (for instance, a length, type and/or endianness
  * indicator could be placed at the beginning of a file, network message
  * or network stream).
  *
  *
  * This is the memory that is used for storing GVariant data in
  * serialised form.  This is what would be sent over the network or
- * what would end up on disk.
+ * what would end up on disk, not counting any indicator of the
+ * endianness, or of the length or type of the top-level variant.
  *
  * The amount of memory required to store a boolean is 1 byte. 16,
- * 32 and 64 bit integers and double precision floating point numbers
+ * 32 and 64 bit integers and floating point numbers
  * use their "natural" size.  Strings (including object path and
  * signature strings) are stored with a nul terminator, and as such
  * use the length of the string plus 1 byte.
  * padding bytes.  That makes a total of 6 + 2 + 3 = 11 bytes.
  *
  * We now require extra padding between the two items in the array.
- * After the 14 bytes of the first item, that's 2 bytes required. We
- * now require 2 framing offsets for an extra two bytes.  14 + 2 + 11
- * + 2 = 29 bytes to encode the entire two-item dictionary.
+ * After the 14 bytes of the first item, that's 2 bytes required.
+ * We now require 2 framing offsets for an extra two
+ * bytes. 14 + 2 + 11 + 2 = 29 bytes to encode the entire two-item
+ * dictionary.
  *
  * ## Type Information Cache
  *
@@ -285,14 +288,10 @@ g_variant_new_from_trusted (const GVariantType *type,
                             gconstpointer       data,
                             gsize               size)
 {
-  GVariant *value;
-  GBytes *bytes;
-
-  bytes = g_bytes_new (data, size);
-  value = g_variant_new_from_bytes (type, bytes, TRUE);
-  g_bytes_unref (bytes);
+  gpointer mydata = g_memdup (data, size);
 
-  return value;
+  return g_variant_new_serialised (g_variant_type_info_get (type),
+                                   g_bytes_new_take (mydata, size), mydata, size, TRUE);
 }
 
 /**
@@ -339,7 +338,7 @@ g_variant_get_boolean (GVariant *value)
 }
 
 /* the constructors and accessors for byte, int{16,32,64}, handles and
- * doubles all look pretty much exactly the same, so we reduce
+ * floats all look pretty much exactly the same, so we reduce
  * copy/pasting here.
  */
 #define NUMERIC_TYPE(TYPE, type, ctype) \
@@ -564,6 +563,31 @@ NUMERIC_TYPE (UINT64, uint64, guint64)
 NUMERIC_TYPE (HANDLE, handle, gint32)
 
 /**
+ * g_variant_new_float:
+ * @value: a #gfloat floating point value
+ *
+ * Creates a new float #GVariant instance.
+ *
+ * Returns: (transfer none): a floating reference to a new float #GVariant instance
+ *
+ * Since: 2.44
+ **/
+/**
+ * g_variant_get_float:
+ * @value: a float #GVariant instance
+ *
+ * Returns the single precision floating point value of @value.
+ *
+ * It is an error to call this function with a @value of any type
+ * other than %G_VARIANT_TYPE_FLOAT.
+ *
+ * Returns: a #gfloat
+ *
+ * Since: 2.44
+ **/
+NUMERIC_TYPE (FLOAT, float, gfloat)
+
+/**
  * g_variant_new_double:
  * @value: a #gdouble floating point value
  *
@@ -613,8 +637,8 @@ GVariant *
 g_variant_new_maybe (const GVariantType *child_type,
                      GVariant           *child)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *maybe_type;
-  GVariant *value;
 
   g_return_val_if_fail (child_type == NULL || g_variant_type_is_definite
                         (child_type), 0);
@@ -627,6 +651,8 @@ g_variant_new_maybe (const GVariantType *child_type,
     child_type = g_variant_get_type (child);
 
   maybe_type = g_variant_type_new_maybe (child_type);
+  type_info = g_variant_type_info_get (maybe_type);
+  g_variant_type_free (maybe_type);
 
   if (child != NULL)
     {
@@ -637,14 +663,10 @@ g_variant_new_maybe (const GVariantType *child_type,
       children[0] = g_variant_ref_sink (child);
       trusted = g_variant_is_trusted (children[0]);
 
-      value = g_variant_new_from_children (maybe_type, children, 1, trusted);
+      return g_variant_new_from_children (type_info, children, 1, trusted);
     }
   else
-    value = g_variant_new_from_children (maybe_type, NULL, 0, TRUE);
-
-  g_variant_type_free (maybe_type);
-
-  return value;
+    return g_variant_new_from_children (type_info, NULL, 0, TRUE);
 }
 
 /**
@@ -690,7 +712,7 @@ g_variant_new_variant (GVariant *value)
 
   g_variant_ref_sink (value);
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_VARIANT),
                                       g_memdup (&value, sizeof value),
                                       1, g_variant_is_trusted (value));
 }
@@ -746,10 +768,10 @@ g_variant_new_array (const GVariantType *child_type,
                      GVariant * const   *children,
                      gsize               n_children)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *array_type;
   GVariant **my_children;
   gboolean trusted;
-  GVariant *value;
   gsize i;
 
   g_return_val_if_fail (n_children > 0 || child_type != NULL, NULL);
@@ -763,6 +785,8 @@ g_variant_new_array (const GVariantType *child_type,
   if (child_type == NULL)
     child_type = g_variant_get_type (children[0]);
   array_type = g_variant_type_new_array (child_type);
+  type_info = g_variant_type_info_get (array_type);
+  g_variant_type_free (array_type);
 
   for (i = 0; i < n_children; i++)
     {
@@ -771,11 +795,7 @@ g_variant_new_array (const GVariantType *child_type,
       trusted &= g_variant_is_trusted (children[i]);
     }
 
-  value = g_variant_new_from_children (array_type, my_children,
-                                       n_children, trusted);
-  g_variant_type_free (array_type);
-
-  return value;
+  return g_variant_new_from_children (type_info, my_children, n_children, trusted);
 }
 
 /*< private >
@@ -826,10 +846,10 @@ GVariant *
 g_variant_new_tuple (GVariant * const *children,
                      gsize             n_children)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *tuple_type;
   GVariant **my_children;
   gboolean trusted;
-  GVariant *value;
   gsize i;
 
   g_return_val_if_fail (n_children == 0 || children != NULL, NULL);
@@ -844,11 +864,10 @@ g_variant_new_tuple (GVariant * const *children,
     }
 
   tuple_type = g_variant_make_tuple_type (children, n_children);
-  value = g_variant_new_from_children (tuple_type, my_children,
-                                       n_children, trusted);
+  type_info = g_variant_type_info_get (tuple_type);
   g_variant_type_free (tuple_type);
 
-  return value;
+  return g_variant_new_from_children (type_info, my_children, n_children, trusted);
 }
 
 /*< private >
@@ -886,6 +905,7 @@ GVariant *
 g_variant_new_dict_entry (GVariant *key,
                           GVariant *value)
 {
+  GVariantTypeInfo *type_info;
   GVariantType *dict_type;
   GVariant **children;
   gboolean trusted;
@@ -899,10 +919,10 @@ g_variant_new_dict_entry (GVariant *key,
   trusted = g_variant_is_trusted (key) && g_variant_is_trusted (value);
 
   dict_type = g_variant_make_dict_entry_type (key, value);
-  value = g_variant_new_from_children (dict_type, children, 2, trusted);
+  type_info = g_variant_type_info_get (dict_type);
   g_variant_type_free (dict_type);
 
-  return value;
+  return g_variant_new_from_children (type_info, children, 2, trusted);
 }
 
 /**
@@ -922,7 +942,7 @@ g_variant_new_dict_entry (GVariant *key,
  * @format_string determines the C types that are used for unpacking
  * the values and also determines if the values are copied or borrowed,
  * see the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * This function is currently implemented with a linear scan.  If you
  * plan to do many lookups then #GVariantDict may be more efficient.
@@ -1069,27 +1089,17 @@ g_variant_lookup_value (GVariant           *dictionary,
  *
  * @element_size must be the size of a single element in the array,
  * as given by the section on
- * <link linkend='gvariant-serialised-data-memory'>Serialised Data
- * Memory</link>.
+ * [serialized data memory][gvariant-serialised-data-memory].
  *
  * In particular, arrays of these fixed-sized types can be interpreted
  * as an array of the given C type, with @element_size set to the size
  * the appropriate type:
- *
- * <informaltable>
- * <tgroup cols='2'>
- * <thead><row><entry>element type</entry> <entry>C type</entry></row></thead>
- * <tbody>
- * <row><entry>%G_VARIANT_TYPE_INT16 (etc.)</entry>
- *   <entry>#gint16 (etc.)</entry></row>
- * <row><entry>%G_VARIANT_TYPE_BOOLEAN</entry>
- *   <entry>#guchar (not #gboolean!)</entry></row>
- * <row><entry>%G_VARIANT_TYPE_BYTE</entry> <entry>#guchar</entry></row>
- * <row><entry>%G_VARIANT_TYPE_HANDLE</entry> <entry>#guint32</entry></row>
- * <row><entry>%G_VARIANT_TYPE_DOUBLE</entry> <entry>#gdouble</entry></row>
- * </tbody>
- * </tgroup>
- * </informaltable>
+ * - %G_VARIANT_TYPE_INT16 (etc.): #gint16 (etc.)
+ * - %G_VARIANT_TYPE_BOOLEAN: #guchar (not #gboolean!)
+ * - %G_VARIANT_TYPE_BYTE: #guchar
+ * - %G_VARIANT_TYPE_HANDLE: #guint32
+ * - %G_VARIANT_TYPE_FLOAT: #gfloat
+ * - %G_VARIANT_TYPE_DOUBLE: #gdouble
  *
  * For example, if calling this function for an array of 32-bit integers,
  * you might say sizeof(gint32). This value isn't used except for the purpose
@@ -1538,7 +1548,7 @@ g_variant_new_strv (const gchar * const *strv,
   for (i = 0; i < length; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_string (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_STRING_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_STRING_ARRAY),
                                       strings, length, TRUE);
 }
 
@@ -1674,7 +1684,7 @@ g_variant_new_objv (const gchar * const *strv,
   for (i = 0; i < length; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_object_path (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_OBJECT_PATH_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_OBJECT_PATH_ARRAY),
                                       strings, length, TRUE);
 }
 
@@ -1911,7 +1921,7 @@ g_variant_new_bytestring_array (const gchar * const *strv,
   for (i = 0; i < length; i++)
     strings[i] = g_variant_ref_sink (g_variant_new_bytestring (strv[i]));
 
-  return g_variant_new_from_children (G_VARIANT_TYPE_BYTESTRING_ARRAY,
+  return g_variant_new_from_children (g_variant_type_info_get (G_VARIANT_TYPE_BYTESTRING_ARRAY),
                                       strings, length, TRUE);
 }
 
@@ -2121,6 +2131,8 @@ g_variant_is_container (GVariant *value)
  * @G_VARIANT_CLASS_INT64: The #GVariant is a signed 64 bit integer.
  * @G_VARIANT_CLASS_UINT64: The #GVariant is an unsigned 64 bit integer.
  * @G_VARIANT_CLASS_HANDLE: The #GVariant is a file handle index.
+ * @G_VARIANT_CLASS_FLOAT: The #GVariant is a single precision floating
+ *                         point value.
  * @G_VARIANT_CLASS_DOUBLE: The #GVariant is a double precision floating 
  *                          point value.
  * @G_VARIANT_CLASS_STRING: The #GVariant is a normal string.
@@ -2524,6 +2536,32 @@ g_variant_print_string (GVariant *value,
                               g_variant_get_uint64 (value));
       break;
 
+    case G_VARIANT_CLASS_FLOAT:
+      {
+        gchar buffer[100];
+        gint i;
+
+        g_ascii_dtostr (buffer, sizeof buffer, g_variant_get_float (value));
+
+        for (i = 0; buffer[i]; i++)
+          if (buffer[i] == '.' || buffer[i] == 'e' ||
+              buffer[i] == 'n' || buffer[i] == 'N')
+            break;
+
+        /* if there is no '.' or 'e' in the float then add one */
+        if (buffer[i] == '\0')
+          {
+            buffer[i++] = '.';
+            buffer[i++] = '0';
+            buffer[i++] = '\0';
+          }
+
+        if (type_annotate)
+          g_string_append (string, "float ");
+        g_string_append (string, buffer);
+      }
+      break;
+
     case G_VARIANT_CLASS_DOUBLE:
       {
         gchar buffer[100];
@@ -2577,7 +2615,7 @@ g_variant_print_string (GVariant *value,
  *
  * Pretty-prints @value in the format understood by g_variant_parse().
  *
- * The format is described <link linkend='gvariant-text'>here</link>.
+ * The format is described [here][gvariant-text].
  *
  * If @type_annotate is %TRUE, then type information is included in
  * the output.
@@ -2648,6 +2686,7 @@ g_variant_hash (gconstpointer value_)
     case G_VARIANT_CLASS_INT32:
     case G_VARIANT_CLASS_UINT32:
     case G_VARIANT_CLASS_HANDLE:
+    case G_VARIANT_CLASS_FLOAT:
       {
         const guint *ptr;
 
@@ -2767,15 +2806,15 @@ g_variant_equal (gconstpointer one,
  * two values that have types that are not exactly equal.  For example,
  * you cannot compare a 32-bit signed integer with a 32-bit unsigned
  * integer.  Also note that this function is not particularly
- * well-behaved when it comes to comparison of doubles; in particular,
+ * well-behaved when it comes to comparison of floats; in particular,
  * the handling of incomparable values (ie: NaN) is undefined.
  *
  * If you only require an equality comparison, g_variant_equal() is more
  * general.
  *
- * Returns: negative value if a &lt; b;
+ * Returns: negative value if a < b;
  *          zero if a = b;
- *          positive value if a &gt; b.
+ *          positive value if a > b.
  *
  * Since: 2.26
  **/
@@ -2838,6 +2877,14 @@ g_variant_compare (gconstpointer one,
         return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
       }
 
+    case G_VARIANT_CLASS_FLOAT:
+      {
+        gfloat a_val = g_variant_get_float (a);
+        gfloat b_val = g_variant_get_float (b);
+
+        return (a_val == b_val) ? 0 : (a_val > b_val) ? 1 : -1;
+      }
+
     case G_VARIANT_CLASS_DOUBLE:
       {
         gdouble a_val = g_variant_get_double (a);
@@ -3042,7 +3089,7 @@ g_variant_iter_free (GVariantIter *iter)
  *
  * Here is an example for iterating with g_variant_iter_next_value():
  * |[<!-- language="C" --> 
- *   /&ast; recursively iterate a container &ast;/
+ *   // recursively iterate a container
  *   void
  *   iterate_container_recursive (GVariant *container)
  *   {
@@ -3617,7 +3664,7 @@ g_variant_builder_end (GVariantBuilder *builder)
   else
     g_assert_not_reached ();
 
-  value = g_variant_new_from_children (my_type,
+  value = g_variant_new_from_children (g_variant_type_info_get (my_type),
                                        g_renew (GVariant *,
                                                 GVSB(builder)->children,
                                                 GVSB(builder)->offset),
@@ -3635,7 +3682,7 @@ g_variant_builder_end (GVariantBuilder *builder)
 /* GVariantDict {{{1 */
 
 /**
- * GVariantDict: (skip)
+ * GVariantDict:
  *
  * #GVariantDict is a mutable interface to #GVariant dictionaries.
  *
@@ -3673,9 +3720,9 @@ g_variant_builder_end (GVariantBuilder *builder)
  * key is not found.  Each returns the new dictionary as a floating
  * #GVariant.
  *
- * <example>
- *  <title>Using stack-allocated #GVariantDict</title>
- *  <programlisting>
+ * ## Using a stack-allocated GVariantDict
+ *
+ * |[<!-- language="C" -->
  *   GVariant *
  *   add_to_count (GVariant  *orig,
  *                 GError   **error)
@@ -3683,24 +3730,23 @@ g_variant_builder_end (GVariantBuilder *builder)
  *     GVariantDict dict;
  *     guint32 count;
  *
- *     g_variant_dict_init (&amp;dict, orig);
- *     if (!g_variant_dict_lookup (&amp;dict, "count", "u", &amp;count))
+ *     g_variant_dict_init (&dict, orig);
+ *     if (!g_variant_dict_lookup (&dict, "count", "u", &count))
  *       {
  *         g_set_error (...);
- *         g_variant_dict_clear (&amp;dict);
+ *         g_variant_dict_clear (&dict);
  *         return NULL;
  *       }
  *
- *     g_variant_dict_insert (&amp;dict, "count", "u", count + 1);
+ *     g_variant_dict_insert (&dict, "count", "u", count + 1);
  *
- *     return g_variant_dict_end (&amp;dict);
+ *     return g_variant_dict_end (&dict);
  *   }
- *  </programlisting>
- * </example>
+ * ]|
+ *
+ * ## Using heap-allocated GVariantDict
  *
- * <example>
- *  <title>Using heap-allocated #GVariantDict</title>
- *  <programlisting>
+ * |[<!-- language="C" -->
  *   GVariant *
  *   add_to_count (GVariant  *orig,
  *                 GError   **error)
@@ -3711,7 +3757,7 @@ g_variant_builder_end (GVariantBuilder *builder)
  *
  *     dict = g_variant_dict_new (orig);
  *
- *     if (g_variant_dict_lookup (dict, "count", "u", &amp;count))
+ *     if (g_variant_dict_lookup (dict, "count", "u", &count))
  *       {
  *         g_variant_dict_insert (dict, "count", "u", count + 1);
  *         result = g_variant_dict_end (dict);
@@ -3726,8 +3772,7 @@ g_variant_builder_end (GVariantBuilder *builder)
  *
  *     return result;
  *   }
- *  </programlisting>
- * </example>
+ * ]|
  *
  * Since: 2.40
  **/
@@ -3844,10 +3889,9 @@ g_variant_dict_init (GVariantDict *dict,
  * this function returns %FALSE.  Otherwise, it unpacks the returned
  * value and returns %TRUE.
  *
- * @format_string determines the C types that are used for unpacking
- * the values and also determines if the values are copied or borrowed,
- * see the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * @format_string determines the C types that are used for unpacking the
+ * values and also determines if the values are copied or borrowed, see the
+ * section on [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Returns: %TRUE if a value was unpacked
  *
@@ -4158,8 +4202,7 @@ g_variant_dict_unref (GVariantDict *dict)
  * not be accessed and the effect is otherwise equivalent to if the
  * character at @limit were nul.
  *
- * See the section on <link linkend='gvariant-format-strings'>GVariant
- * Format Strings</link>.
+ * See the section on [GVariant format strings][gvariant-format-strings].
  *
  * Returns: %TRUE if there was a valid format string
  *
@@ -4177,8 +4220,8 @@ g_variant_format_string_scan (const gchar  *string,
   switch (next_char())
     {
     case 'b': case 'y': case 'n': case 'q': case 'i': case 'u':
-    case 'x': case 't': case 'h': case 'd': case 's': case 'o':
-    case 'g': case 'v': case '*': case '?': case 'r':
+    case 'x': case 't': case 'h': case 'f': case 'd': case 's':
+    case 'o': case 'g': case 'v': case '*': case '?': case 'r':
       break;
 
     case 'm':
@@ -4841,6 +4884,7 @@ g_variant_valist_skip_leaf (const gchar **str,
       va_arg (*app, guint64);
       return;
 
+    case 'f':
     case 'd':
       va_arg (*app, gdouble);
       return;
@@ -4886,6 +4930,9 @@ g_variant_valist_new_leaf (const gchar **str,
     case 'h':
       return g_variant_new_handle (va_arg (*app, gint));
 
+    case 'f':
+      return g_variant_new_float (va_arg (*app, gdouble));
+
     case 'd':
       return g_variant_new_double (va_arg (*app, gdouble));
 
@@ -4896,6 +4943,7 @@ g_variant_valist_new_leaf (const gchar **str,
 
 /* The code below assumes this */
 G_STATIC_ASSERT (sizeof (gboolean) == sizeof (guint32));
+G_STATIC_ASSERT (sizeof (gfloat) == sizeof (guint32));
 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
 
 static void
@@ -4969,6 +5017,10 @@ g_variant_valist_get_leaf (const gchar **str,
           *(gint32 *) ptr = g_variant_get_handle (value);
           return;
 
+        case 'f':
+          *(gfloat *) ptr = g_variant_get_float (value);
+          return;
+
         case 'd':
           *(gdouble *) ptr = g_variant_get_double (value);
           return;
@@ -4991,6 +5043,7 @@ g_variant_valist_get_leaf (const gchar **str,
         case 'u':
         case 'h':
         case 'b':
+        case 'f':
           *(guint32 *) ptr = 0;
           return;
 
@@ -5158,11 +5211,11 @@ g_variant_valist_get (const gchar **str,
  *
  * Think of this function as an analogue to g_strdup_printf().
  *
- * The type of the created instance and the arguments that are
- * expected by this function are determined by @format_string.  See the
- * section on <link linkend='gvariant-format-strings'>GVariant Format
- * Strings</link>.  Please note that the syntax of the format string is
- * very likely to be extended in the future.
+ * The type of the created instance and the arguments that are expected
+ * by this function are determined by @format_string. See the section on
+ * [GVariant format strings][gvariant-format-strings]. Please note that
+ * the syntax of the format string is very likely to be extended in the
+ * future.
  *
  * The first character of the format string must not be '*' '?' '@' or
  * 'r'; in essence, a new #GVariant must always be constructed by this
@@ -5170,9 +5223,9 @@ g_variant_valist_get (const gchar **str,
  *
  * Note that the arguments must be of the correct width for their types
  * specified in @format_string. This can be achieved by casting them. See
- * the <link linkend='gvariant-varargs'>GVariant varargs documentation</link>.
+ * the [GVariant varargs documentation][gvariant-varargs].
  *
- * <programlisting>
+ * |[<!-- language="C" -->
  * MyFlags some_flags = FLAG_ONE | FLAG_TWO;
  * const gchar *some_strings[] = { "a", "b", "c", NULL };
  * GVariant *new_variant;
@@ -5181,7 +5234,7 @@ g_variant_valist_get (const gchar **str,
  *                              /<!-- -->* This cast is required. *<!-- -->/
  *                              (guint64) some_flags,
  *                              some_strings);
- * </programlisting>
+ * ]|
  *
  * Returns: a new floating #GVariant instance
  *
@@ -5229,9 +5282,9 @@ g_variant_new (const gchar *format_string,
  * @format_string, are collected from this #va_list and the list is left
  * pointing to the argument following the last.
  *
- * Note that the arguments in @app must be of the correct width for their types
- * specified in @format_string when collected into the #va_list. See
- * the <link linkend='gvariant-varargs'>GVariant varargs documentation</link>.
+ * Note that the arguments in @app must be of the correct width for their
+ * types specified in @format_string when collected into the #va_list.
+ * See the [GVariant varargs documentation][gvariant-varargs.
  *
  * These two generalisations allow mixing of multiple calls to
  * g_variant_new_va() and g_variant_get_va() within a single actual
@@ -5286,15 +5339,15 @@ g_variant_new_va (const gchar  *format_string,
  * The arguments that are expected by this function are entirely
  * determined by @format_string.  @format_string also restricts the
  * permissible types of @value.  It is an error to give a value with
- * an incompatible type.  See the section on <link
- * linkend='gvariant-format-strings'>GVariant Format Strings</link>.
+ * an incompatible type.  See the section on
+ * [GVariant format strings][gvariant-format-strings].
  * Please note that the syntax of the format string is very likely to be
  * extended in the future.
  *
  * @format_string determines the C types that are used for unpacking
  * the values and also determines if the values are copied or borrowed,
  * see the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Since: 2.24
  **/
@@ -5347,7 +5400,7 @@ g_variant_get (GVariant    *value,
  * @format_string determines the C types that are used for unpacking
  * the values and also determines if the values are copied or borrowed,
  * see the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Since: 2.24
  **/
@@ -5386,7 +5439,7 @@ g_variant_get_va (GVariant     *value,
  *
  * Note that the arguments must be of the correct width for their types
  * specified in @format_string. This can be achieved by casting them. See
- * the <link linkend='gvariant-varargs'>GVariant varargs documentation</link>.
+ * the [GVariant varargs documentation][gvariant-varargs].
  *
  * This function might be used as follows:
  *
@@ -5442,7 +5495,7 @@ g_variant_builder_add (GVariantBuilder *builder,
  * @format_string determines the C types that are used for unpacking
  * the values and also determines if the values are copied or borrowed,
  * see the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Since: 2.24
  **/
@@ -5483,7 +5536,7 @@ g_variant_get_child (GVariant    *value,
  *
  * Here is an example for memory management with g_variant_iter_next():
  * |[<!-- language="C" --> 
- *   /&ast; Iterates a dictionary of type 'a{sv}' &ast;/
+ *   // Iterates a dictionary of type 'a{sv}'
  *   void
  *   iterate_dictionary (GVariant *dictionary)
  *   {
@@ -5497,7 +5550,7 @@ g_variant_get_child (GVariant    *value,
  *         g_print ("Item '%s' has type '%s'\n", key,
  *                  g_variant_get_type_string (value));
  *
- *         /&ast; must free data for ourselves &ast;/
+ *         // must free data for ourselves
  *         g_variant_unref (value);
  *         g_free (key);
  *       }
@@ -5511,7 +5564,7 @@ g_variant_get_child (GVariant    *value,
  * the values and also determines if the values are copied or borrowed.
  *
  * See the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Returns: %TRUE if a value was unpacked, or %FALSE if there as no value
  *
@@ -5575,7 +5628,7 @@ g_variant_iter_next (GVariantIter *iter,
  *
  * Here is an example for memory management with g_variant_iter_loop():
  * |[<!-- language="C" --> 
- *   /&ast; Iterates a dictionary of type 'a{sv}' &ast;/
+ *   // Iterates a dictionary of type 'a{sv}'
  *   void
  *   iterate_dictionary (GVariant *dictionary)
  *   {
@@ -5589,9 +5642,8 @@ g_variant_iter_next (GVariantIter *iter,
  *         g_print ("Item '%s' has type '%s'\n", key,
  *                  g_variant_get_type_string (value));
  *
- *         /&ast; no need to free 'key' and 'value' here
- *          &ast; unless breaking out of this loop
- *          &ast;/
+ *         // no need to free 'key' and 'value' here
+ *         // unless breaking out of this loop
  *       }
  *   }
  * ]|
@@ -5611,7 +5663,7 @@ g_variant_iter_next (GVariantIter *iter,
  * the values and also determines if the values are copied or borrowed.
  *
  * See the section on
- * <link linkend='gvariant-format-strings-pointers'>GVariant Format Strings</link>.
+ * [GVariant format strings][gvariant-format-strings-pointers].
  *
  * Returns: %TRUE if a value was unpacked, or %FALSE if there was no
  *          value
@@ -5711,6 +5763,9 @@ g_variant_deep_copy (GVariant *value)
     case G_VARIANT_CLASS_HANDLE:
       return g_variant_new_handle (g_variant_get_handle (value));
 
+    case G_VARIANT_CLASS_FLOAT:
+      return g_variant_new_float (g_variant_get_float (value));
+
     case G_VARIANT_CLASS_DOUBLE:
       return g_variant_new_double (g_variant_get_double (value));
 
@@ -5773,8 +5828,7 @@ g_variant_get_normal_form (GVariant *value)
  * Performs a byteswapping operation on the contents of @value.  The
  * result is that all multi-byte numeric data contained in @value is
  * byteswapped.  That includes 16, 32, and 64bit signed and unsigned
- * integers as well as file handles and double precision floating point
- * values.
+ * integers as well as file handles and floating point values.
  *
  * This function is an identity mapping on any value that does not
  * contain multi-byte numeric data.  That include strings, booleans,
@@ -5870,21 +5924,99 @@ g_variant_new_from_data (const GVariantType *type,
                          GDestroyNotify      notify,
                          gpointer            user_data)
 {
-  GVariant *value;
   GBytes *bytes;
 
   g_return_val_if_fail (g_variant_type_is_definite (type), NULL);
   g_return_val_if_fail (data != NULL || size == 0, NULL);
 
+  if (size == 0)
+    {
+      if (notify)
+        {
+          (* notify) (user_data);
+          notify = NULL;
+        }
+
+      data = NULL;
+    }
+
   if (notify)
     bytes = g_bytes_new_with_free_func (data, size, notify, user_data);
   else
     bytes = g_bytes_new_static (data, size);
 
-  value = g_variant_new_from_bytes (type, bytes, trusted);
-  g_bytes_unref (bytes);
+  return g_variant_new_serialised (g_variant_type_info_get (type), bytes, data, size, trusted);
+}
 
-  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)
+{
+  gconstpointer data;
+  gsize size;
+
+  g_return_val_if_fail (g_variant_type_is_definite (type), NULL);
+
+  data = g_bytes_get_data (bytes, &size);
+
+  return g_variant_new_serialised (g_variant_type_info_get (type), g_bytes_ref (bytes), data, size, trusted);
+}
+
+/**
+ * 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)
+{
+  gconstpointer data;
+  GBytes *bytes;
+  gsize size;
+  gconstpointer bytes_data;
+  gsize bytes_size;
+
+  data = g_variant_get_serialised (value, &bytes, &size);
+  bytes_data = g_bytes_get_data (bytes, &bytes_size);
+
+  /* Try to reuse the GBytes held internally by GVariant, if it exists
+   * and is covering exactly the correct range.
+   */
+  if (data == bytes_data && size == bytes_size)
+    return g_bytes_ref (bytes);
+
+  /* See g_variant_get_data() about why it can return NULL... */
+  else if (data == NULL)
+    return g_bytes_new_take (g_malloc0 (size), size);
+
+  /* Otherwise, make a new GBytes with reference to the old. */
+  else
+    return g_bytes_new_with_free_func (data, size, (GDestroyNotify) g_bytes_unref, g_bytes_ref (bytes));
 }
 
 /* Epilogue {{{1 */