[gtk/docs-gtk-org] glib: Add the GVariant ancillary sections



commit e41d05c48ea56c928507339cc827edaea7a41aae
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Sat Aug 14 13:44:18 2021 +0100

    glib: Add the GVariant ancillary sections

 glib/glib/glib.toml.in               |   2 +
 glib/glib/gvariant-format-strings.md | 503 +++++++++++++++++++++++++++++++++++
 glib/glib/gvariant-text.md           | 347 ++++++++++++++++++++++++
 glib/glib/meson.build                |   2 +
 4 files changed, 854 insertions(+)
---
diff --git a/glib/glib/glib.toml.in b/glib/glib/glib.toml.in
index 66b29ca145..2a52846d50 100644
--- a/glib/glib/glib.toml.in
+++ b/glib/glib/glib.toml.in
@@ -36,6 +36,8 @@ content_files = [
   "building.md",
   "compiling.md",
   "error-reporting.md",
+  "gvariant-format-strings.md",
+  "gvariant-text.md",
   "i18n.md",
   "logging.md",
   "main-loop.md",
diff --git a/glib/glib/gvariant-format-strings.md b/glib/glib/gvariant-format-strings.md
new file mode 100644
index 0000000000..3d04188d3b
--- /dev/null
+++ b/glib/glib/gvariant-format-strings.md
@@ -0,0 +1,503 @@
+Title: GVariant Format Strings
+
+# GVariant Format Strings
+       
+## Variable Argument Conversions
+
+This page attempts to document how to perform variable argument conversions
+with [struct@GLib.Variant].
+
+Conversions occur according to format strings. A format string is a two-way
+mapping between a single `GVariant` value and one or more C values.
+
+A conversion from C values into a `GVariant` value is made using the
+[ctor GLib Variant new] function. A conversion from a `GVariant` into C
+values is made using the [method GLib Variant get] function.
+
+## Syntax
+
+This section exhaustively describes all possibilities for GVariant format
+strings. There are no valid forms of format strings other than those
+described here. Please note that the format string syntax is likely to
+expand in the future.
+
+Valid format strings have one of the following forms:
+
+- any type string
+- a type string prefixed with a `@`
+- `&s`, `&o`, `&g`, `^as`, `^a&s`, `^ao`, `^a&o`, `^ay`, `^&ay`, `^aay` or
+  `^a&ay`.
+- any format string, prefixed with an `m`
+- a sequence of zero or more format strings, concatenated and enclosed in
+  parentheses
+- an opening brace, followed by two format strings, followed by a closing
+  brace (subject to the constraint that the first format string correspond
+  to a type valid for use as the key type of a dictionary)
+
+## Symbols
+
+The following table describes the rough meaning of symbols that may appear inside a GVariant format string. 
Each symbol is described in detail in its own section, including usage examples.
+
+| Symbol | Meaning |
+|--------|---------|
+| `b`, `y`, `n`, `q`, `i`, `u`, `x`, `t`, `h`, `d` | Used for building or deconstructing boolean, byte and 
numeric types. See "Numeric Types" below. |
+| `s`, `o`, `g` | Used for building or deconstructing string types. See "Strings" below. |
+| `v` | Used for building or deconstructing variant types. See "Variants" below. |
+| `a` | Used for building or deconstructing arrays. See "Arrays" below. |
+| `m` | Used for building or deconstructing maybe types. See "Maybe Types" below. |
+| `()` | Used for building or deconstructing tuples. See "Tuples" below. |
+| `{}` | Used for building or deconstructing dictionary entries. See "Dictionaries" below. |
+| `@` | Used as a prefix for a `GVariant` type string (not a prefix for a format string, so `@as` is a valid 
format string but `@^as` is not). Denotes that a pointer to a GVariant should be used in place of the normal 
C type or types. For `g_variant_new()` this means that you must pass a non-`NULL` `(GVariant *)`; if it is a 
floating reference, ownership will be taken, as if by using `g_variant_ref_sink()`. For `g_variant_get()` 
this means that you must pass a pointer to a `(GVariant *)` for the value to be returned by reference or 
`NULL` to ignore the value. See "GVariant \*" below. |
+| `*`, `?`, `r` | Exactly equivalent to `@*`, `@?` and `@r`. Provided only for completeness so that all 
`GVariant` type strings can be used also as format strings. See "GVariant \*" below. |
+| `&` | Used as a prefix for a `GVariant` type string (not a prefix for a format string, so `&s` is a valid 
format string but `&@s` is not). Denotes that a C pointer to serialised data should be used in place of the 
normal C type. See "Pointers" below. |
+| `^` | Used as a prefix on some specific types of format strings. See "Convenience Conversions" below. |
+
+## Numeric Types
+
+Characters: `b`, `y`, `n`, `q`, `i`, `u`, `x`, `t`, `h`, `d`
+
+Variable argument conversions from numeric types work in the most obvious
+way possible. Upon encountering one of these characters, `g_variant_new()`
+takes the equivalent C type as an argument. `g_variant_get()` takes a pointer
+to the equivalent C type (or `NULL` to ignore the value).
+
+The equivalent C types are as follows:
+
+| Character | Equivalent C type |
+|-----------|-------------------|
+| `b`       | `gboolean`        |
+| `y`       | `guchar`          |
+| `n`       | `gint16`          |
+| `q`       | `guint16`         |
+| `i`       | `gint32`          |
+| `u`       | `guint32`         |
+| `x`       | `gint64`          |
+| `t`       | `guint64`         |
+| `h`       | `gint32`          |
+| `d`       | `gdouble`         |
+
+Note that in C, small integer types in variable argument lists are promoted
+up to int or unsigned int as appropriate, and read back accordingly. `int`
+is 32 bits on every platform on which GLib is currently supported. This
+means that you can use C expressions of type int with `g_variant_new()` and
+format characters `b`, `y`, `n`, `q`, `i`, `u` and `h`. Specifically, you
+can use integer literals with these characters.
+
+When using the `x` and `t` characters, you must ensure that the value that
+you provide is 64 bit. This means that you should use a cast or make use of
+the `G_GINT64_CONSTANT` or `G_GUINT64_CONSTANT` macros.
+
+No type promotion occurs when using `g_variant_get()` since it operates with
+pointers. The pointers must always point to a memory region of exactly the
+correct size.
+
+### Examples
+
+```c
+GVariant *value1, *value2, *value3, *value4;
+
+value1 = g_variant_new ("y", 200);
+value2 = g_variant_new ("b", TRUE);
+value3 = g_variant_new ("d", 37.5):
+value4 = g_variant_new ("x", G_GINT64_CONSTANT (998877665544332211));
+
+{
+  gdouble floating;
+  gboolean truth;
+  gint64 bignum;
+
+
+  g_variant_get (value1, "y", NULL);      /* ignore the value. */
+  g_variant_get (value2, "b", &truth);
+  g_variant_get (value3, "d", &floating);
+  g_variant_get (value4, "x", &bignum);
+}
+```
+
+## Strings
+
+Characters: `s`, `o`, `g`
+
+String conversions occur to and from standard nul-terminated C strings. Upon
+encountering an `s`, `o` or `g` in a format string, `g_variant_new()` takes a
+`(const gchar *)` and makes a copy of it. `NULL` is not a valid string; use
+maybe types to encode that. If the `o` or `g` characters are used, care must
+be taken to ensure that the passed string is a valid D-Bus object path or
+D-Bus type signature, respectively.
+
+Upon encountering `s`, `o` or `g`, `g_variant_get()` takes a pointer to a
+`(gchar *)` (ie: `(gchar **)`) and sets it to a newly-allocated copy of the
+string. It is appropriate to free this copy using `g_free()`. `NULL` may
+also be passed to indicate that the value of the string should be ignored
+(in which case no copy is made).
+
+### Examples
+
+```c
+GVariant *value1, *value2, *value3;
+
+value1 = g_variant_new ("s", "hello world!");
+value2 = g_variant_new ("o", "/must/be/a/valid/path");
+value3 = g_variant_new ("g", "iias");
+
+#if 0
+  g_variant_new ("s", NULL);      /* not valid: NULL is not a string. */
+#endif
+
+{
+  gchar *result;
+
+  g_variant_get (value1, "s", &result);
+  g_print ("It was '%s'\n", result);
+  g_free (result);
+}
+```
+
+## Variants
+
+Characters: `v`
+
+Upon encountering a `v`, `g_variant_new()` takes a `(GVariant *)`. The value
+of the `GVariant` is used as the contents of the variant value.
+
+Upon encountering a `v`, `g_variant_get()` takes a pointer to a `(GVariant
+*)` (ie: `(GVariant **)`). It is set to a new reference to a `GVariant`
+instance containing the contents of the variant value. It is appropriate to
+free this reference using `g_variant_unref()`. `NULL` may also be passed to
+indicate that the value should be ignored (in which case no new reference is
+created).
+
+### Examples
+
+```c
+GVariant *x, *y;
+
+/* the following two lines are equivalent: */
+x = g_variant_new ("v", y);
+x = g_variant_new_variant (y);
+
+/* as are these: */
+g_variant_get (x, "v", &y);
+y = g_variant_get_variant (x);
+```
+
+## Arrays
+
+Characters: `a`
+
+Upon encountering an `a` character followed by a type string,
+`g_variant_new()` will take a `(GVariantBuilder *)` that has been created as
+an array builder for an array of the type given in the type string. The
+builder will have `g_variant_builder_end()` called on it and the result will
+be used as the value. As a special exception, if the given type string is a
+definite type, then `NULL` may be given to mean an empty array of that type.
+
+Upon encountering an `a` character followed by a type string,
+`g_variant_get()` will take a pointer to a `(GVariantIter *)` (ie:
+`(GVariantIter **)`). A new heap-allocated iterator is created and returned,
+initialised for iterating over the elements of the array. This iterator
+should be freed when you are done with it, using `g_variant_iter_free()`.
+`NULL` may also be given to indicate that the value of the array should be
+ignored.
+
+### Examples
+
+```c
+GVariantBuilder *builder;
+GVariant *value;
+
+builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+g_variant_builder_add (builder, "s", "when");
+g_variant_builder_add (builder, "s", "in");
+g_variant_builder_add (builder, "s", "the");
+g_variant_builder_add (builder, "s", "course");
+value = g_variant_new ("as", builder);
+g_variant_builder_unref (builder);
+
+{
+  GVariantIter *iter;
+  gchar *str;
+
+  g_variant_get (value, "as", &iter);
+  while (g_variant_iter_loop (iter, "s", &str))
+    g_print ("%s\n", str);
+  g_variant_iter_free (iter);
+}
+
+g_variant_unref (value);
+```
+
+## Maybe Types
+
+Characters: `m`
+
+Maybe types are handled in two separate ways depending on the format string
+that follows the `m`. The method that is used currently depends entirely on
+the character immediately following the `m`.
+
+The first way is used with format strings starting with `a`, `s`, `o`, `g`,
+`v`, `@`, `*`, `?`, `r`, `&`, or `^`. In all of these cases, for non-maybe
+types, `g_variant_new()` takes a pointer to a non-`NULL` value and
+`g_variant_get()` returns (by reference) a non-`NULL` pointer. When any of
+these format strings are prefixed with an `m`, the type of arguments that
+are collected does not change in any way, but `NULL` becomes a permissible
+value, to indicate the Nothing case.
+
+Note that the "special exception" introduced in the array section for
+constructing empty arrays is ignored here. Using a `NULL` pointer with the
+format string `mas` constructs the Nothing value -- not an empty array.
+
+The second way is used with all other format strings. For `g_variant_new()`
+an additional gboolean argument is collected and for `g_variant_get()` an
+additional `(gboolean *)`. Following this argument, the arguments that are
+normally collected for the equivalent non-maybe type will be collected.
+
+If `FALSE` is given to `g_variant_new()` then the Nothing value is
+constructed and the collected arguments are ignored. Otherwise (if `TRUE`
+was given), the arguments are used in the normal way to create the Just
+value.
+
+If `NULL` is given to `g_variant_get()` then the value is ignored. If a
+non-`NULL` pointer is given then it is used to return by reference whether
+the value was Just. In the case that the value was Just, the `gboolean` will
+be set to `TRUE` and the value will be stored in the arguments in the usual
+way. In the case that the value was Nothing, the `gboolean` will be set to
+`FALSE` and the arguments will be collected in the normal way but have their
+values set to binary zero.
+
+### Examples
+
+```c
+GVariant *value1, *value2, *value3, *value4, *value5, *value6;
+value1 = g_variant_new ("ms", "Hello world");
+value2 = g_variant_new ("ms", NULL);
+value3 = g_variant_new ("(m(ii)s)", TRUE, 123, 456, "Done");
+value4 = g_variant_new ("(m(ii)s)", FALSE, -1, -1, "Done");          /* both '-1' are ignored. */
+value5 = g_variant_new ("(m@(ii)s)", NULL, "Done");
+
+{
+  GVariant *contents;
+  const gchar *cstr;
+  gboolean just;
+  gint32 x, y;
+  gchar *str;
+
+  g_variant_get (value1, "ms", &str);
+  if (str != NULL)
+    g_print ("str: %s\n", str);
+  else
+    g_print ("it was null\n");
+  g_free (str);
+
+
+  g_variant_get (value2, "m&s", &cstr);
+  if (cstr != NULL)
+    g_print ("str: %s\n", cstr);
+  else
+    g_print ("it was null\n");
+  /* don't free 'cstr' */
+
+
+  /* NULL passed for the gboolean *, but two 'gint32 *' still collected */
+  g_variant_get (value3, "(m(ii)s)", NULL, NULL, NULL, &str);
+  g_print ("string is %s\n", str);
+  g_free (str);
+
+  /* note: &s used, so g_free() not needed */
+  g_variant_get (value4, "(m(ii)&s)", &just, &x, &y, &cstr);
+  if (just)
+    g_print ("it was (%d, %d)\n", x, y);
+  else
+    g_print ("it was null\n");
+  g_print ("string is %s\n", cstr);
+  /* don't free 'cstr' */
+
+
+  g_variant_get (value5, "(m*s)", &contents, NULL); /* ignore the string. */
+  if (contents != NULL)
+    {
+      g_variant_get (contents, "(ii)", &x, &y);
+      g_print ("it was (%d, %d)\n", x, y);
+      g_variant_unref (contents);
+    }
+  else
+    g_print ("it was null\n");
+}
+```
+
+## Tuples
+
+Characters: `()`
+
+Tuples are handled by handling each item in the tuple, in sequence. Each
+item is handled in the usual way.
+
+### Examples
+
+```c
+GVariant *value1, *value2;
+
+value1 = g_variant_new ("(s(ii))", "Hello", 55, 77);
+value2 = g_variant_new ("()");
+
+{
+  gchar *string;
+  gint x, y;
+
+  g_variant_get (value1, "(s(ii))", &string, &x, &y);
+  g_print ("%s, %d, %d\n", string, x, y);
+  g_free (string);
+
+  g_variant_get (value2, "()");   /* do nothing... */
+}
+```
+
+## `GVariant *`
+
+Characters: `@`, `*`, `?`, `r`
+
+Upon encountering a `@` in front of a type string, `g_variant_new()` takes a
+non-`NULL` pointer to a `GVariant` and uses its value directly instead of
+collecting arguments to create the value. The provided `GVariant` must have
+a type that matches the type string following the `@`. `*` is the same as
+`@*` (ie: take a `GVariant` of any type). `?` is the same as `@?` (ie: take
+a `GVariant` of any basic type). `r` is the same as `@r` (ie: take a
+`GVariant` of any tuple type).
+
+Upon encountering a `@` in front of a type string, `g_variant_get()` takes a
+pointer to a `(GVariant *)` (ie: a `(GVariant **)`) and sets it to a new
+reference to a `GVariant` containing the value (instead of deconstructing
+the value into C types in the usual way). `NULL` can be given to ignore the
+value. `*`, `?` and `r` are handled in a way analogous to what is stated
+above.
+
+You can always use `*` as an alternative to `?`, `r` or any use of `@`.
+Using the other characters where possible is recommended, however, due to
+the improvements in type safety and code self-documentation.
+
+### Examples
+
+```c
+GVariant *value1, *value2;
+
+value1 = g_variant_new ("(i@ii)", 44, g_variant_new_int32 (55), 66);
+
+/* note: consumes floating reference count on 'value1' */
+value2 = g_variant_new ("(@(iii)*)", value1, g_variant_new_string ("foo"));
+
+{
+  const gchar *string;
+  GVariant *tmp;
+  gsize length;
+  gint x, y, z;
+
+  g_variant_get (value2, "((iii)*)", &x, &y, &z, &tmp);
+  string = g_variant_get_string (tmp, &length);
+  g_print ("it is %d %d %d %s (length=%d)\n", x, y, z, string, (int) length);
+  g_variant_unref (tmp);
+
+  /* quick way to skip all the values in a tuple */
+  g_variant_get (value2, "(rs)", NULL, &string); /* or "(@(iii)s)" */
+  g_print ("i only got the string: %s\n", string);
+  g_free (string);
+}
+```
+
+## Dictionaries
+
+Characters: `{}`
+
+Dictionary entries are handled by handling first the key, then the value. Each is handled in the usual way.
+
+### Examples
+
+```c
+GVariantBuilder *b;
+GVariant *dict;
+
+b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
+g_variant_builder_add (b, "{sv}", "name", g_variant_new_string ("foo"));
+g_variant_builder_add (b, "{sv}", "timeout", g_variant_new_int32 (10));
+dict = g_variant_builder_end (b);
+```
+
+To extract data from nested dictionaries you can go through a vardict.
+
+### Examples
+
+```c
+GVariant *data;
+gint value = 1;
+gint max = 3;
+
+/* type (oa{sa{sv}) */
+data = g_variant_new_parsed ("(%o, {'brightness': {'value': <%i>, 'max': <%i>}})",
+                             "/object/path", value, max);
+{
+  GVariant *params;
+  GVariant *p_brightness;
+  gchar *obj
+  gint p_max;
+
+  g_variant_get (data, "(o@a{?*})", &obj, &params);
+  g_print ("object_path: %s\n", obj);
+
+  p_brightness = g_variant_lookup_value (params, "brightness", G_VARIANT_TYPE_VARDICT);
+  g_variant_lookup (p_brightness, "max", "i", &p_max);
+  g_print ("max: %d\n", p_max);
+}
+```
+
+## Pointers
+
+Characters: `&`
+
+The `&` character is used to indicate that serialised data should be
+directly exchanged via a pointer.
+
+Currently, the only use for this character is when it is applied to a string
+(ie: `&s`, `&o` or `&g`). For `g_variant_new()` this has absolutely no
+effect. The string is collected and duplicated normally. For
+`g_variant_get()` it means that instead of creating a newly allocated copy
+of the string, a pointer to the serialised data is returned. This pointer
+should not be freed. Validity checks are performed to ensure that the string
+data will always be properly nul-terminated.
+
+### Examples
+
+```c
+{
+  const gchar *str;
+  GVariant *value;
+
+  value = g_variant_new ("&s", "hello world");
+  g_variant_get (value, "&s", &str);
+  g_print ("string is: %s\n", str);
+  /* no need to free str */
+}
+```
+
+## Convenience Conversions
+
+Characters: `^`
+
+The `^` character currently supports conversion to and from bytestrings or
+to and from arrays of strings or bytestrings. It does not support byte
+arrays. It has a number of forms.
+
+In all forms, when used with `g_variant_new()` one pointer value is
+collected from the variable arguments and passed to a function (as given in
+the table below). The result of that function is used as the value for this
+position. When used with `g_variant_get()` one pointer value is produced by
+using the function (given in the table) and returned by reference.
+
+| Conversion | Used with `g_variant_new()`                              | Used with `g_variant_get()`        
                        |
+|------------|----------------------------------------------------------|------------------------------------------------------------|
+| `^as`      | equivalent to [`ctor@GLib.Variant.new_strv`]             | equivalent to 
[`method@GLib.Variant.dup_strv`]             |
+| `^a&s`     |                                                          | equivalent to 
[`method@GLib.Variant.get_strv`]             |
+| `^ao`      | equivalent to [`ctor@GLib.Variant.new_objv`]             | equivalent to 
[`method@GLib.Variant.dup_objv`]             |
+| `^a&o`     |                                                          | equivalent to 
[`method@GLib.Variant.get_objv`]             |
+| `^ay`      | equivalent to [`ctor@GLib.Variant.new_bytestring`]       | equivalent to 
[`method@GLib.Variant.dup_bytestring`]       |
+| `^&ay`     |                                                          | equivalent to 
[`method@GLib.Variant.get_bytestring`]       |
+| `^aay`     | equivalent to [`ctor@GLib.Variant.new_bytestring_array`] | equivalent to 
[`method@GLib.Variant.dup_bytestring_array`] |
+| `^a&ay`    |                                                          | equivalent to 
[`method@GLib.Variant.get_bytestring_array`] |
diff --git a/glib/glib/gvariant-text.md b/glib/glib/gvariant-text.md
new file mode 100644
index 0000000000..c6c752febb
--- /dev/null
+++ b/glib/glib/gvariant-text.md
@@ -0,0 +1,347 @@
+Title: GVariant Text Format
+
+# GVariant Text Format
+
+This page attempts to document the `GVariant` text format as produced by
+[`method@GLib.Variant.print`] and parsed by the [`func@GLib.Variant.parse`]
+family of functions. In most cases the style closely resembles the
+formatting of literals in Python but there are some additions and
+exceptions.
+
+The functions that deal with `GVariant` text format absolutely always deal
+in UTF-8. Conceptually, `GVariant` text format is a string of Unicode
+characters, not bytes. Non-ASCII but otherwise printable Unicode characters
+are not treated any differently from normal ASCII characters.
+
+The parser makes two passes. The purpose of the first pass is to determine
+the type of the value being parsed. The second pass does the actual parsing.
+Based on the fact that all elements in an array have to have the same type,
+`GVariant` is able to make some deductions that would not otherwise be
+possible. As an example:
+
+    [[1, 2, 3], [4, 5, 6]]
+
+is parsed as an array of arrays of integers (type `aai`), but
+
+    [[1, 2, 3], [4, 5, 6.0]]
+
+is parsed as an array of arrays of doubles (type `aad`).
+
+As another example, `GVariant` is able to determine that
+
+    ["hello", nothing]
+
+is an array of maybe strings (type `ams`).
+
+What the parser accepts as valid input is dependent on context. The API
+permits for out-of-band type information to be supplied to the parser (which
+will change its behaviour). This can be seen in the GSettings and GDBus
+command line utilities where the type information is available from the
+schema or the remote introspection information. The additional information
+can cause parses to succeed when they would not otherwise have been able to
+(by resolving ambiguous type information) or can cause them to fail (due to
+conflicting type information). Unless stated otherwise, the examples given
+in this section assume that no out-of-band type data has been given to the
+parser.
+
+## Syntax Summary
+
+The following table describes the rough meaning of symbols that may appear
+inside GVariant text format. Each symbol is described in detail in its own
+section, including usage examples.
+
+| Symbol | Meaning |
+|--------|---------|
+| `true`, `false` | Booleans. |
+| `""`, `''` | String literal. See Strings below. |
+| numbers | See Numbers below. |
+| `()` | Tuples. |
+| `[]` | Arrays. |
+| `{}` | Dictionaries and Dictionary Entries. |
+| `<>` | Variants. |
+| `just`, `nothing` | Maybe Types. |
+| `@` | Type Annotations. |
+| `boolean`, `byte`, `int16`, `uint16`, `int32`, `uint32`, `handle`, `int64`, `uint64`, `double`, `string`, 
`objectpath`, `signature` | Type Annotations |
+| `b""`, `b''` | Bytestrings. |
+| `%` | Positional Parameters. |
+
+## Booleans
+
+The strings `true` and `false` are parsed as booleans. This is the only way
+to specify a boolean value.
+
+## Strings
+
+Strings literals must be quoted using `""` or `''`. The two are completely
+equivalent (except for the fact that each one is unable to contain itself
+unescaped).
+
+Strings are Unicode strings with no particular encoding. For example, to
+specify the character `é`, you just write `'é'`. You could also give the
+Unicode codepoint of that character (`U+E9`) as the escape sequence
+`'\u00e9'`. Since the strings are pure Unicode, you should not attempt to
+encode the UTF-8 byte sequence corresponding to the string using escapes; it
+won't work and you'll end up with the individual characters corresponding to
+each byte.
+
+Unicode escapes of the form `\uxxxx` and `\Uxxxxxxxx` are supported, in
+hexadecimal. The usual control sequence escapes `\a`, `\b`, `\f`, `\n`,
+`\r`, `\t` and `\v` are supported. Additionally, a `\` before a newline
+character causes the newline to be ignored. Finally, any other character
+following `\` is copied literally (for example, `\"` or `\\`) but for
+forwards compatibility with future additions you should only use this
+feature when necessary for escaping backslashes or quotes.
+
+The usual octal and hexadecimal escapes `\0nnn` and `\xnn` are not supported
+here. Those escapes are used to encode byte values and `GVariant` strings
+are Unicode.
+
+Single-character strings are not interpreted as bytes. Bytes must be
+specified by their numerical value.
+
+## Numbers
+
+Numbers are given by default as decimal values. Octal and hex values can be
+given in the usual way (by prefixing with `0` or `0x`). Note that `GVariant`
+considers bytes to be unsigned integers and will print them as a two digit
+hexadecimal number by default.
+
+Floating point numbers can also be given in the usual ways, including
+scientific and hexadecimal notations.
+
+For lack of additional information, integers will be parsed as `int32`
+values by default. If the number has a point or an `e` in it, then it will
+be parsed as a double precision floating point number by default. If type
+information is available (either explicitly or inferred) then that type will
+be used instead.
+
+Some examples:
+
+`5` parses as the `int32` value five.
+
+`37.5` parses as a floating point value.
+
+`3.75e1` parses the same as the value above.
+
+`uint64 7` parses seven as a `uint64`. See [Type
+Annotations](#type-annotations).
+
+## Tuples
+
+Tuples are formed using the same syntax as Python. Here are some examples:
+
+`()` parses as the empty tuple.
+
+`(5,)` is a tuple containing a single value.
+
+`("hello", 42)` is a pair. Note that values of different types are
+permitted.
+
+## Arrays
+
+Arrays are formed using the same syntax as Python uses for lists (which is
+arguably the term that `GVariant` should have used). Note that, unlike Python
+lists, `GVariant` arrays are statically typed. This has two implications.
+
+First, all items in the array must have the same type. Second, the type of
+the array must be known, even in the case that it is empty. This means that
+(unless there is some other way to infer it) type information will need to
+be given explicitly for empty arrays.
+
+The parser is able to infer some types based on the fact that all items in
+an array must have the same type. See the examples below:
+
+`[1]` parses (without additional type information) as a one-item array of
+signed integers.
+
+`[1, 2, 3]` parses (similarly) as a three-item array.
+
+`[1, 2, 3.0]` parses as an array of doubles. This is the most simple case of
+the type inferencing in action.
+
+`[(1, 2), (3, 4.0)]` causes the 2 to also be parsed as a double (but the 1
+and 3 are still integers).
+
+`["", nothing]` parses as an array of maybe strings. The presence of
+"nothing" clearly implies that the array elements are nullable.
+
+`[[], [""]]` will parse properly because the type of the first (empty) array
+can be inferred to be equal to the type of the second array (both are arrays
+of strings).
+
+`[b'hello', []]` looks odd but will parse properly. See
+[Bytestrings](#bytestrings).
+
+And some examples of errors:
+
+`["hello", 42]` fails to parse due to conflicting types.
+
+`[]` will fail to parse without additional type information.
+
+## Dictionaries and Dictionary Entries
+
+Dictionaries and dictionary entries are both specified using the `{}`
+characters.
+
+The dictionary syntax is more commonly used. This is what the printer elects
+to use in the normal case of dictionary entries appearing in an array (AKA
+"a dictionary"). The separate syntax for dictionary entries is typically
+only used for when the entries appear on their own, outside of an array
+(which is valid but unusual). Of course, you are free to use the dictionary
+entry syntax within arrays but there is no good reason to do so (and the
+printer itself will never do so). Note that, as with arrays, the type of
+empty dictionaries must be established (either explicitly or through
+inference).
+
+The dictionary syntax is the same as Python's syntax for dictionaries. Some
+examples:
+
+`@a{sv} {}` parses as the empty dictionary of everyone's favourite type.
+
+`@a{sv} []` is the same as above (owing to the fact that dictionaries are
+really arrays).
+
+`{1: "one", 2: "two", 3: "three"}` parses as a dictionary mapping integers
+to strings.
+
+The dictionary entry syntax looks just like a pair (2-tuple) that uses
+braces instead of parens. The presence of a comma immediately following the
+key differentiates it from the dictionary syntax (which features a colon
+after the first key). Some examples:
+
+`{1, "one"}` is a free-standing dictionary entry that can be parsed on its
+own or as part of another container value.
+
+`[{1, "one"}, {2, "two"}, {3, "three"}]` is exactly equivalent to the
+dictionary example given above.
+
+## Variants
+
+Variants are denoted using angle brackets (aka "XML brackets"), `<>`. They
+may not be omitted.
+
+Using `<>` effectively disrupts the type inferencing that occurs between
+array elements. This can have positive and negative effects.
+
+`[<"hello">, <42>]` will parse whereas `["hello", 42]` would not.
+
+`[<['']>, <[]>]` will fail to parse even though `[[''], []]` parses
+successfully. You would need to specify `[<['']>, <@as []>]`.
+
+`{"title": <"frobit">, "enabled": <true>, "width": <800>}` is an example of
+perhaps the most pervasive use of both dictionaries and variants.
+
+## Maybe Types
+
+The syntax for specifying maybe types is inspired by Haskell.
+
+The null case is specified using the keyword nothing and the non-null case
+is explicitly specified using the keyword just. GVariant allows just to be
+omitted in every case that it is able to unambiguously determine the
+intention of the writer. There are two cases where it must be specified:
+
+- when using nested maybes, in order to specify the just nothing case
+- to establish the nullability of the type of a value without explicitly
+  specifying its full type
+
+Some examples:
+
+`just 'hello'` parses as a non-null nullable string.
+
+`@ms 'hello'` is the same (demonstrating how just can be dropped if the type is already known).
+
+`nothing` will not parse without extra type information.
+
+`@ms nothing` parses as a null nullable string.
+
+`[just 3, nothing]` is an array of nullable integers
+
+`[3, nothing]` is the same as the above (demonstrating another place were just can be dropped).
+
+`[3, just nothing]` parses as an array of maybe maybe integers (type `ammi`).
+
+## Type Annotations
+
+Type annotations allow additional type information to be given to the
+parser. Depending on the context, this type information can change the
+output of the parser, cause an error when parsing would otherwise have
+succeeded or resolve an error when parsing would have otherwise failed.
+
+Type annotations come in two forms: type codes and type keywords.
+
+Type keywords can be seen as more verbose (and more legible) versions of a
+common subset of the type codes. The type keywords `boolean`, `byte`,
+`int16`, `uint16`, `int32`, `uint32`, `handle`, `int64`, `uint64`, `double`,
+`string`, `objectpath` and literal signature are each exactly equivalent to
+their corresponding type code.
+
+Type codes are an `@` ("at" sign) followed by a definite `GVariant` type
+string. Some examples:
+
+`uint32 5` causes the number to be parsed unsigned instead of signed (the
+default).
+
+`@u 5` is the same
+
+`objectpath "/org/gnome/xyz"` creates an object path instead of a normal
+string
+
+`@au []` specifies the type of the empty array (which would not parse
+otherwise)
+
+`@ms ""` indicates that a string value is meant to have a maybe type
+
+## Bytestrings
+
+The bytestring syntax is a piece of syntactic sugar meant to complement the
+bytestring APIs in GVariant. It constructs arrays of non-`NUL` bytes (type
+`ay`) with a `NUL` terminator at the end. These are normal C strings with no
+particular encoding enforced, so the bytes may not be valid UTF-8.
+Bytestrings are a special case of byte arrays; byte arrays (also type 'ay'),
+in the general case, can contain a `NUL` byte at any position, and need not
+end with a `NUL` byte.
+
+Bytestrings are specified with either `b""` or `b''`. As with strings, there
+is no fundamental difference between the two different types of quotes.
+
+Bytestrings support the full range of escapes that you would expect (ie:
+those supported by `g_strcompress()`. This includes the normal control
+sequence escapes (as mentioned in the section on strings) as well as octal
+and hexadecimal escapes of the forms `\0nnn` and `\xnn`.
+
+`b'abc'` is equivalent to `[byte 0x61, 0x62, 0x63, 0]`.
+
+When formatting arrays of bytes, the printer will choose to display the
+array as a bytestring if it contains a nul character at the end and no other
+nul bytes within. Otherwise, it is formatted as a normal array.
+
+## Positional Parameters
+
+Positional parameters are not a part of the normal `GVariant` text format,
+but they are mentioned here because they can be used with
+[`ctor@GLib.Variant.new_parsed`].
+
+A positional parameter is indicated with a `%` followed by any valid
+[GVariant Format String](gvariant-format-strings.html). Variable arguments
+are collected as specified by the format string and the resulting value is
+inserted at the current position.
+
+This feature is best explained by example:
+
+```c
+char *t = "xyz";
+gboolean en = false;
+GVariant *value;
+
+value = g_variant_new_parsed ("{'title': <%s>, 'enabled': <%b>}", t, en);
+```
+
+This constructs a dictionary mapping strings to variants (type `a{sv}`) with
+two items in it. The key names are parsed from the string and the values for
+those keys are taken as variable arguments parameters.
+
+The arguments are always collected in the order that they appear in the
+string to be parsed. Format strings that collect multiple arguments are
+permitted, so you may require more varargs parameters than the number of `%`
+signs that appear. You can also give format strings that collect no
+arguments, but there's no good reason to do so.
diff --git a/glib/glib/meson.build b/glib/glib/meson.build
index bb60586fbe..b600d62219 100644
--- a/glib/glib/meson.build
+++ b/glib/glib/meson.build
@@ -2,6 +2,8 @@ expand_content_files = [
   'building.md',
   'compiling.md',
   'error-reporting.md',
+  'gvariant-format-strings.md',
+  'gvariant-text.md',
   'i18n.md',
   'logging.md',
   'main-loop.md',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]