[perl-Glib] Add Glib::Variant and Glib::VariantType
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Glib] Add Glib::Variant and Glib::VariantType
- Date: Sun, 4 Jan 2015 17:05:53 +0000 (UTC)
commit d0c52b8bb864a3377403623589f1c0cd8482717b
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date: Sun Jan 4 18:05:05 2015 +0100
Add Glib::Variant and Glib::VariantType
Wrapping the majority of the GVariant and GVariantType API.
GError.xs | 6 +
GVariant.xs | 685 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Glib.xs | 3 +
Makefile.PL | 4 +
gperl-gtypes.c | 39 ++++
gperl-gtypes.h | 5 +
gperl.h | 16 ++-
lib/Glib.pm | 149 ++++++++++++
t/variant.t | 338 ++++++++++++++++++++++++++++
typemap | 8 +
10 files changed, 1252 insertions(+), 1 deletions(-)
---
diff --git a/GError.xs b/GError.xs
index d358704..1de5306 100644
--- a/GError.xs
+++ b/GError.xs
@@ -369,6 +369,12 @@ BOOT:
gperl_register_error_domain (G_THREAD_ERROR,
GPERL_TYPE_THREAD_ERROR,
"Glib::Thread::Error");
+#if GLIB_CHECK_VERSION (2, 24, 0)
+ /* gvariant.h */
+ gperl_register_error_domain (G_VARIANT_PARSE_ERROR,
+ GPERL_TYPE_VARIANT_PARSE_ERROR,
+ "Glib::Variant::ParseError");
+#endif
PERL_UNUSED_VAR (file);
diff --git a/GVariant.xs b/GVariant.xs
new file mode 100644
index 0000000..e359829
--- /dev/null
+++ b/GVariant.xs
@@ -0,0 +1,685 @@
+/*
+ * Copyright (C) 2014 by the gtk2-perl team (see the file AUTHORS for the full
+ * list)
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "gperl.h"
+
+/* --- GVariant --------------------------------------------------------------*/
+
+/* --- basic wrappers --- */
+
+static SV *
+variant_to_sv (GVariant * variant, gboolean own)
+{
+ SV * sv;
+ SV * rv;
+ HV * stash;
+
+ if (!variant)
+ return &PL_sv_undef;
+
+ sv = newSV (0);
+ _gperl_attach_mg (sv, variant);
+
+ if (own) {
+#if GLIB_CHECK_VERSION (2, 30, 0)
+ g_variant_take_ref (variant);
+#else
+ if (g_variant_is_floating (variant)) {
+ g_variant_ref_sink (variant);
+ }
+#endif
+ } else {
+ g_variant_ref (variant);
+ }
+
+ rv = newRV_noinc (sv);
+ stash = gv_stashpv ("Glib::Variant", TRUE);
+ sv_bless (rv, stash);
+
+ return rv;
+}
+
+static GVariant *
+sv_to_variant (SV * sv)
+{
+ MAGIC * mg;
+ if (!gperl_sv_is_ref (sv) || !(mg = _gperl_find_mg (SvRV (sv))))
+ return NULL;
+ return (GVariant *) mg->mg_ptr;
+}
+
+/* --- GValue wrappers --- */
+
+static SV *
+wrap_variant (const GValue * value)
+{
+ return variant_to_sv (g_value_get_variant (value), FALSE);
+}
+
+static void
+unwrap_variant (GValue * value, SV * sv)
+{
+ g_value_set_variant (value, sv_to_variant (sv));
+}
+
+static GPerlValueWrapperClass variant_wrapper_class = { wrap_variant, unwrap_variant };
+
+/* --- typemap glue --- */
+
+SV *
+newSVGVariant (GVariant * variant)
+{
+ return variant_to_sv (variant, FALSE);
+}
+
+SV *
+newSVGVariant_noinc (GVariant * variant)
+{
+ return variant_to_sv (variant, TRUE);
+}
+
+GVariant *
+SvGVariant (SV * sv)
+{
+ return sv_to_variant (sv);
+}
+
+/* --- GVariantType --------------------------------------------------------- */
+
+/* --- boxed wrappers ---*/
+
+static GPerlBoxedWrapperClass default_boxed_wrapper_class;
+static GPerlBoxedWrapperClass variant_type_wrapper_class;
+
+static gpointer
+unwrap_variant_type (GType gtype, const char * package, SV * sv)
+{
+ if (!gperl_sv_is_ref (sv)) {
+ GVariantType * vtype;
+ vtype = g_variant_type_new (SvPV_nolen (sv));
+ sv = default_boxed_wrapper_class.wrap (gtype, package, vtype, TRUE);
+ /* fall through */
+ }
+ return default_boxed_wrapper_class.unwrap (gtype, package, sv);
+}
+
+/* --- typemap glue --- */
+
+SV *
+newSVGVariantType (const GVariantType * type)
+{
+ if (!type)
+ return &PL_sv_undef;
+ return gperl_new_boxed ((gpointer) type, G_TYPE_VARIANT_TYPE, FALSE);
+}
+
+SV *
+newSVGVariantType_own (const GVariantType * type)
+{
+ return gperl_new_boxed ((gpointer) type, G_TYPE_VARIANT_TYPE, TRUE);
+}
+
+const GVariantType *
+SvGVariantType (SV * sv)
+{
+ if (!gperl_sv_is_defined (sv))
+ return NULL;
+ return gperl_get_boxed_check (sv, G_TYPE_VARIANT_TYPE);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* --- helpers ---*/
+
+static void
+sv_to_variant_array (SV * sv, GVariant *** array_p, gsize * n_p)
+{
+ AV * av;
+ gsize i;
+ if (!gperl_sv_is_array_ref (sv))
+ croak ("Expected an array reference for 'children'");
+ av = (AV *) SvRV (sv);
+ *n_p = av_len (av) + 1;
+ *array_p = g_new0 (GVariant *, *n_p);
+ for (i = 0; i < *n_p; i++) {
+ SV ** svp = av_fetch (av, i, 0);
+ if (svp)
+ (*array_p)[i] = SvGVariant (*svp);
+ }
+}
+
+static void
+sv_to_variant_type_array (SV * sv, const GVariantType *** array_p, gint * n_p)
+{
+ AV * av;
+ gint i;
+ if (!gperl_sv_is_array_ref (sv))
+ croak ("Expected an array reference for 'items'");
+ av = (AV *) SvRV (sv);
+ *n_p = av_len (av) + 1;
+ *array_p = g_new0 (const GVariantType *, *n_p);
+ for (i = 0; i < *n_p; i++) {
+ SV ** svp = av_fetch (av, i, 0);
+ if (svp)
+ (*array_p)[i] = SvGVariantType (*svp);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+MODULE = Glib::Variant PACKAGE = Glib::Variant PREFIX = g_variant_
+
+=for object Glib::Variant strongly typed value datatype
+=cut
+
+=for position SYNOPSIS
+
+=head1 SYNOPSIS
+
+ my $v = Glib::Variant->new ('as', ['GTK+', 'Perl']);
+ my $aref = $v->get ('as');
+
+=for position DESCRIPTION
+
+=head1 DESCRIPTION
+
+There are two sets of APIs for creating and dealing with C<Glib::Variant>s: the
+low-level API described below under L</METHODS>, and the convenience API
+described in this section.
+
+=head2 CONVENIENCE API
+
+=over
+
+=item variant = Glib::Variant->new ($format_string, $value)
+
+=item (variant1, ...) = Glib::Variant->new ($format_string, $value1, ...)
+
+Constructs a variant from C<$format_string> and C<$value>. Also supports
+constructing multiple variants when the format string is a concatenation of
+multiple types.
+
+=item value = $variant->get ($format_string)
+
+Deconstructs C<$variant> according to C<$format_string>.
+
+=back
+
+The following symbols are currently supported in format strings:
+
+ +------------------------------+---------------------------------+
+ | Symbol | Meaning |
+ +------------------------------+---------------------------------+
+ | b, y, n, q, i, u, x, t, h, d | Boolean, byte and numeric types |
+ | s, o, g | String types |
+ | v | Variant types |
+ | a | Arrays |
+ | m | Maybe types |
+ | () | Tuples |
+ | {} | Dictionary entries |
+ +------------------------------+---------------------------------+
+
+Note that if a format string specifies an array, a tuple or a dictionary entry
+("a", "()" or "{}"), then array references are expected by C<new> and produced
+by C<get>. For arrays of dictionary entries ("a{}"), hash references are also
+supported by C<new> and handled as you would expect.
+
+For a complete specification, see the documentation at
+
+=over
+
+=item L<https://developer.gnome.org/glib/stable/glib-GVariantType.html>
+
+=item L<https://developer.gnome.org/glib/stable/glib-GVariant.html>
+
+=item L<https://developer.gnome.org/glib/stable/gvariant-format-strings.html>
+
+=item L<https://developer.gnome.org/glib/stable/gvariant-text.html>
+
+=back
+
+=cut
+
+=for see_also Glib::VariantType
+=cut
+
+BOOT:
+ gperl_register_fundamental_full (G_TYPE_VARIANT, "Glib::Variant",
+ &variant_wrapper_class);
+ default_boxed_wrapper_class = variant_type_wrapper_class =
+ * gperl_default_boxed_wrapper_class ();
+ variant_type_wrapper_class.unwrap = unwrap_variant_type;
+ gperl_register_boxed (G_TYPE_VARIANT_TYPE, "Glib::VariantType",
+ &variant_type_wrapper_class);
+
+const GVariantType * g_variant_get_type (GVariant *value);
+
+const gchar * g_variant_get_type_string (GVariant *value);
+
+gboolean g_variant_is_of_type (GVariant *value, const GVariantType *type);
+
+gboolean g_variant_is_container (GVariant *value);
+
+const char * g_variant_classify (GVariant *value);
+ PREINIT:
+ GVariantClass vclass;
+ CODE:
+ vclass = g_variant_classify (value);
+ RETVAL = (const char *) &vclass;
+ OUTPUT:
+ RETVAL
+
+GVariant_noinc * g_variant_new_boolean (class, gboolean value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_byte (class, guchar value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_int16 (class, gint16 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_uint16 (class, guint16 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_int32 (class, gint32 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_uint32 (class, guint32 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_int64 (class, gint64 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_uint64 (class, guint64 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_handle (class, gint32 value);
+ C_ARGS:
+ value
+
+GVariant_noinc * g_variant_new_double (class, gdouble value);
+ C_ARGS:
+ value
+
+# GVariant * g_variant_new_take_string (gchar *string);
+GVariant_noinc * g_variant_new_string (class, const gchar *string);
+ C_ARGS:
+ string
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_38
+# GVariant * g_variant_new_printf (const gchar *format_string, ...) G_GNUC_PRINTF (1, 2);
+
+GVariant_noinc * g_variant_new_object_path (class, const gchar *object_path);
+ C_ARGS:
+ object_path
+
+gboolean g_variant_is_object_path (const gchar *string);
+
+GVariant_noinc * g_variant_new_signature (class, const gchar *signature);
+ C_ARGS:
+ signature
+
+gboolean g_variant_is_signature (const gchar *string);
+
+GVariant_noinc * g_variant_new_variant (class, GVariant *value);
+ C_ARGS:
+ value
+
+# FIXME:
+# GVariant * g_variant_new_strv (const gchar * const *strv, gssize length);
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_30
+# GVariant * g_variant_new_objv (const gchar * const *strv, gssize length);
+
+#if GLIB_CHECK_VERSION (2, 26, 0)
+
+GVariant_noinc * g_variant_new_bytestring (class, const char_byte * string);
+ C_ARGS:
+ string
+
+# FIXME:
+# GVariant * g_variant_new_bytestring_array (const gchar * const *strv, gssize length);
+
+#endif
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_32
+# GVariant * g_variant_new_fixed_array (const GVariantType *element_type, gconstpointer elements, gsize
n_elements, gsize element_size);
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_36
+# GVariant * g_variant_new_from_bytes (const GVariantType *type, GBytes *bytes, gboolean trusted);
+
+# FIXME:
+# GVariant * g_variant_new_from_data (const GVariantType *type, gconstpointer data, gsize size, gboolean
trusted, GDestroyNotify notify, gpointer user_data);
+
+gboolean g_variant_get_boolean (GVariant *value);
+
+guchar g_variant_get_byte (GVariant *value);
+
+gint16 g_variant_get_int16 (GVariant *value);
+
+guint16 g_variant_get_uint16 (GVariant *value);
+
+gint32 g_variant_get_int32 (GVariant *value);
+
+guint32 g_variant_get_uint32 (GVariant *value);
+
+gint64 g_variant_get_int64 (GVariant *value);
+
+guint64 g_variant_get_uint64 (GVariant *value);
+
+gint32 g_variant_get_handle (GVariant *value);
+
+gdouble g_variant_get_double (GVariant *value);
+
+GVariant_noinc * g_variant_get_variant (GVariant *value);
+
+# gchar * g_variant_dup_string (GVariant *value, gsize *length);
+const gchar * g_variant_get_string (GVariant *value);
+ C_ARGS:
+ value, NULL
+
+# FIXME:
+# gchar ** g_variant_dup_strv (GVariant *value, gsize *length);
+# const gchar ** g_variant_get_strv (GVariant *value, gsize *length);
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_30
+# gchar ** g_variant_dup_objv (GVariant *value, gsize *length);
+# const gchar ** g_variant_get_objv (GVariant *value, gsize *length);
+
+#if GLIB_CHECK_VERSION (2, 26, 0)
+
+# gchar * g_variant_dup_bytestring (GVariant *value, gsize *length);
+const char * g_variant_get_bytestring (GVariant *value);
+
+# FIXME:
+# gchar ** g_variant_dup_bytestring_array (GVariant *value, gsize *length);
+# const gchar ** g_variant_get_bytestring_array (GVariant *value, gsize *length);
+
+#endif
+
+GVariant_noinc * g_variant_new_maybe (class, const GVariantType *child_type, GVariant *child);
+ C_ARGS:
+ child_type, child
+
+GVariant * g_variant_new_array (class, const GVariantType *child_type, SV *children);
+ PREINIT:
+ GVariant ** children_c;
+ gsize n_children;
+ CODE:
+ sv_to_variant_array (children, &children_c, &n_children);
+ RETVAL = g_variant_new_array (child_type, children_c, n_children);
+ g_free (children_c);
+ OUTPUT:
+ RETVAL
+
+GVariant * g_variant_new_tuple (class, SV *children);
+ PREINIT:
+ GVariant ** children_c;
+ gsize n_children;
+ CODE:
+ sv_to_variant_array (children, &children_c, &n_children);
+ RETVAL = g_variant_new_tuple (children_c, n_children);
+ g_free (children_c);
+ OUTPUT:
+ RETVAL
+
+GVariant_noinc * g_variant_new_dict_entry (class, GVariant *key, GVariant *value);
+ C_ARGS:
+ key, value
+
+GVariant_noinc * g_variant_get_maybe (GVariant *value);
+
+gsize g_variant_n_children (GVariant *value);
+
+# void g_variant_get_child (GVariant *value, gsize index_, const gchar *format_string, ...);
+
+GVariant_noinc * g_variant_get_child_value (GVariant *value, gsize index_);
+
+# gboolean g_variant_lookup (GVariant *dictionary, const gchar *key, const gchar *format_string, ...);
+GVariant_noinc * g_variant_lookup_value (GVariant *dictionary, const gchar *key, const GVariantType
*expected_type);
+
+# FIXME:
+# gconstpointer g_variant_get_fixed_array (GVariant *value, gsize *n_elements, gsize element_size);
+
+gsize g_variant_get_size (GVariant *value);
+
+# FIXME:
+# gconstpointer g_variant_get_data (GVariant *value);
+# GLIB_AVAILABLE_IN_2_36
+# GBytes * g_variant_get_data_as_bytes (GVariant *value);
+# void g_variant_store (GVariant *value, gpointer data);
+
+# GString * g_variant_print_string (GVariant *value, GString *string, gboolean type_annotate);
+gchar_own * g_variant_print (GVariant *value, gboolean type_annotate);
+
+guint g_variant_hash (const GVariant * value);
+
+gboolean g_variant_equal (const GVariant * one, const GVariant * two);
+
+#if GLIB_CHECK_VERSION (2, 26, 0)
+
+gint g_variant_compare (const GVariant * one, const GVariant * two);
+
+#endif
+
+GVariant_noinc * g_variant_get_normal_form (GVariant *value);
+
+gboolean g_variant_is_normal_form (GVariant *value);
+
+GVariant_noinc * g_variant_byteswap (GVariant *value);
+
+# FIXME:
+# GLIB_AVAILABLE_IN_2_36
+# GVariant * g_variant_new_from_bytes (const GVariantType *type, GBytes *bytes, gboolean trusted);
+
+# FIXME:
+# GVariant * g_variant_new_from_data (const GVariantType *type, gconstpointer data, gsize size, gboolean
trusted, GDestroyNotify notify, gpointer user_data);
+
+void
+DESTROY (GVariant * variant)
+ CODE:
+ g_variant_unref (variant);
+
+# --------------------------------------------------------------------------- #
+
+# GVariantIter * g_variant_iter_new (GVariant *value);
+# gsize g_variant_iter_init (GVariantIter *iter, GVariant *value);
+# GVariantIter * g_variant_iter_copy (GVariantIter *iter);
+# gsize g_variant_iter_n_children (GVariantIter *iter);
+# void g_variant_iter_free (GVariantIter *iter);
+# GVariant * g_variant_iter_next_value (GVariantIter *iter);
+# gboolean g_variant_iter_next (GVariantIter *iter, const gchar *format_string, ...);
+# gboolean g_variant_iter_loop (GVariantIter *iter, const gchar *format_string, ...);
+
+# --------------------------------------------------------------------------- #
+
+# GLIB_AVAILABLE_IN_2_40 {
+# GVariantDict * g_variant_dict_new (GVariant *from_asv);
+# void g_variant_dict_init (GVariantDict *dict, GVariant *from_asv);
+# gboolean g_variant_dict_lookup (GVariantDict *dict, const gchar *key, const gchar *format_string, ...);
+# GVariant * g_variant_dict_lookup_value (GVariantDict *dict, const gchar *key, const GVariantType
*expected_type);
+# gboolean g_variant_dict_contains (GVariantDict *dict, const gchar *key);
+# void g_variant_dict_insert (GVariantDict *dict, const gchar *key, const gchar *format_string, ...);
+# void g_variant_dict_insert_value (GVariantDict *dict, const gchar *key, GVariant *value);
+# gboolean g_variant_dict_remove (GVariantDict *dict, const gchar *key);
+# void g_variant_dict_clear (GVariantDict *dict);
+# GVariant * g_variant_dict_end (GVariantDict *dict);
+# GVariantDict * g_variant_dict_ref (GVariantDict *dict);
+# void g_variant_dict_unref (GVariantDict *dict);
+# }
+
+# --------------------------------------------------------------------------- #
+
+# GVariantBuilder * g_variant_builder_new (const GVariantType *type);
+# void g_variant_builder_unref (GVariantBuilder *builder);
+# GVariantBuilder * g_variant_builder_ref (GVariantBuilder *builder);
+# void g_variant_builder_init (GVariantBuilder *builder, const GVariantType *type);
+# GVariant * g_variant_builder_end (GVariantBuilder *builder);
+# void g_variant_builder_clear (GVariantBuilder *builder);
+# void g_variant_builder_open (GVariantBuilder *builder, const GVariantType *type);
+# void g_variant_builder_close (GVariantBuilder *builder);
+# void g_variant_builder_add_value (GVariantBuilder *builder, GVariant *value);
+# void g_variant_builder_add (GVariantBuilder *builder, const gchar *format_string, ...);
+# void g_variant_builder_add_parsed (GVariantBuilder *builder, const gchar *format, ...);
+
+# --------------------------------------------------------------------------- #
+
+# These are re-created in lib/Glib.pm.
+# GVariant * g_variant_new (const gchar *format_string, ...);
+# GVariant * g_variant_new_va (const gchar *format_string, const gchar **endptr, va_list *app);
+# void g_variant_get (GVariant *value, const gchar *format_string, ...);
+# void g_variant_get_va (GVariant *value, const gchar *format_string, const gchar **endptr, va_list *app);
+# GLIB_AVAILABLE_IN_2_34
+# gboolean g_variant_check_format_string (GVariant *value, const gchar *format_string, gboolean copy_only);
+
+# --------------------------------------------------------------------------- #
+
+=for apidoc __function__ __gerror__
+=cut
+GVariant_noinc *
+g_variant_parse (const GVariantType *type, const gchar *text)
+ PREINIT:
+ GError *error = NULL;
+ CODE:
+ RETVAL = g_variant_parse (type, text, NULL, NULL, &error);
+ if (error)
+ gperl_croak_gerror (NULL, error);
+ OUTPUT:
+ RETVAL
+
+# GVariant * g_variant_new_parsed (const gchar *format, ...);
+# GVariant * g_variant_new_parsed_va (const gchar *format, va_list *app);
+# GLIB_AVAILABLE_IN_2_40
+# gchar * g_variant_parse_error_print_context (GError *error, const gchar *source_str);
+
+# --------------------------------------------------------------------------- #
+
+MODULE = Glib::Variant PACKAGE = Glib::VariantType PREFIX = g_variant_type_
+
+=for see_also Glib::Variant
+=cut
+
+=for apidoc __function__
+=cut
+gboolean g_variant_type_string_is_valid (const gchar *type_string);
+
+=for apidoc
+=for signature (type_string, rest) = Glib::VariantType::string_scan ($string)
+Scans the start of C<$string> for a complete type string and extracts it. If
+no type string can be found, an exception is thrown.
+=cut
+# gboolean g_variant_type_string_scan (const gchar *string, const gchar *limit, const gchar **endptr);
+void
+g_variant_type_string_scan (const char *string)
+ PREINIT:
+ const char *limit = NULL;
+ const char *endptr = NULL;
+ PPCODE:
+ if (!g_variant_type_string_scan (string, limit, &endptr))
+ croak ("Could not find type string at the start of '%s'",
+ string);
+ PUSHs (sv_2mortal (newSVpvn (string, endptr-string)));
+ if (endptr && *endptr)
+ XPUSHs (sv_2mortal (newSVpv (endptr, 0)));
+
+GVariantType_own * g_variant_type_new (class, const gchar *type_string);
+ C_ARGS:
+ type_string
+
+# const gchar * g_variant_type_peek_string (const GVariantType *type);
+# gchar * g_variant_type_dup_string (const GVariantType *type);
+SV * g_variant_type_get_string (const GVariantType *type)
+ PREINIT:
+ const char * string;
+ CODE:
+ string = g_variant_type_peek_string (type);
+ RETVAL = newSVpv (string, g_variant_type_get_string_length (type));
+ OUTPUT:
+ RETVAL
+
+gboolean g_variant_type_is_definite (const GVariantType *type);
+
+gboolean g_variant_type_is_container (const GVariantType *type);
+
+gboolean g_variant_type_is_basic (const GVariantType *type);
+
+gboolean g_variant_type_is_maybe (const GVariantType *type);
+
+gboolean g_variant_type_is_array (const GVariantType *type);
+
+gboolean g_variant_type_is_tuple (const GVariantType *type);
+
+gboolean g_variant_type_is_dict_entry (const GVariantType *type);
+
+gboolean g_variant_type_is_variant (const GVariantType *type);
+
+guint g_variant_type_hash (const GVariantType *type);
+
+gboolean g_variant_type_equal (const GVariantType *type1, const GVariantType *type2);
+
+gboolean g_variant_type_is_subtype_of (const GVariantType *type, const GVariantType *supertype);
+
+const GVariantType * g_variant_type_element (const GVariantType *type);
+
+const GVariantType * g_variant_type_first (const GVariantType *type);
+
+const GVariantType * g_variant_type_next (const GVariantType *type);
+
+gsize g_variant_type_n_items (const GVariantType *type);
+
+const GVariantType * g_variant_type_key (const GVariantType *type);
+
+const GVariantType * g_variant_type_value (const GVariantType *type);
+
+GVariantType_own * g_variant_type_new_array (class, const GVariantType *element);
+ C_ARGS:
+ element
+
+GVariantType_own * g_variant_type_new_maybe (class, const GVariantType *element);
+ C_ARGS:
+ element
+
+GVariantType_own * g_variant_type_new_tuple (class, SV *items);
+ PREINIT:
+ const GVariantType ** items_c;
+ gint n_items;
+ CODE:
+ sv_to_variant_type_array (items, &items_c, &n_items);
+ RETVAL = g_variant_type_new_tuple (items_c, n_items);
+ g_free (items_c);
+ OUTPUT:
+ RETVAL
+
+GVariantType_own * g_variant_type_new_dict_entry (class, const GVariantType *key, const GVariantType *value);
+ C_ARGS:
+ key, value
diff --git a/Glib.xs b/Glib.xs
index 8466bb7..8d54088 100644
--- a/Glib.xs
+++ b/Glib.xs
@@ -470,6 +470,9 @@ BOOT:
#if GLIB_CHECK_VERSION (2, 12, 0)
GPERL_CALL_BOOT (boot_Glib__BookmarkFile);
#endif /* GLIB_CHECK_VERSION (2, 12, 0) */
+#if GLIB_CHECK_VERSION (2, 24, 0)
+ GPERL_CALL_BOOT (boot_Glib__Variant);
+#endif /* GLIB_CHECK_VERSION (2, 24, 0) */
/* make sure that we're running/linked against a version at least as
* new as we built against, otherwise bad things will happen. */
if ((((int)glib_major_version) < GLIB_MAJOR_VERSION)
diff --git a/Makefile.PL b/Makefile.PL
index 6a3936d..bf99935 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -89,6 +89,10 @@ if (ExtUtils::PkgConfig->atleast_version ('glib-2.0', '2.12.0')) {
push @xs_files, 'GBookmarkFile.xs';
}
+if (ExtUtils::PkgConfig->atleast_version ('glib-2.0', '2.24.0')) {
+ push @xs_files, 'GVariant.xs';
+}
+
my %meta_merge = (
q(meta-spec) => {
version => '2',
diff --git a/gperl-gtypes.c b/gperl-gtypes.c
index ff09c81..79ec9f6 100644
--- a/gperl-gtypes.c
+++ b/gperl-gtypes.c
@@ -510,3 +510,42 @@ gperl_thread_error_get_type (void)
#define GPERL_TYPE_THREAD_ERROR gperl_thread_error_get_type()
GType gperl_thread_error_get_type (void);
+
+/* -------------------------------------------------------------------------- */
+
+#if GLIB_CHECK_VERSION (2, 24, 0)
+
+GType
+gperl_variant_parse_error_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GEnumValue values[] = {
+ { G_VARIANT_PARSE_ERROR_FAILED, "G_VARIANT_PARSE_ERROR_FAILED", "failed" },
+ { G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED, "G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED",
"basic-type-expected" },
+ { G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE, "G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE",
"cannot-infer-type" },
+ { G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED, "G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED",
"definite-type-expected" },
+ { G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END, "G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END", "input-not-at-end"
},
+ { G_VARIANT_PARSE_ERROR_INVALID_CHARACTER, "G_VARIANT_PARSE_ERROR_INVALID_CHARACTER",
"invalid-character" },
+ { G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING, "G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING",
"invalid-format-string" },
+ { G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH, "G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH",
"invalid-object-path" },
+ { G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE, "G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE",
"invalid-signature" },
+ { G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING, "G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING",
"invalid-type-string" },
+ { G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE, "G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE", "no-common-type" },
+ { G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE, "G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE",
"number-out-of-range" },
+ { G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG, "G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG", "number-too-big" },
+ { G_VARIANT_PARSE_ERROR_TYPE_ERROR, "G_VARIANT_PARSE_ERROR_TYPE_ERROR", "type-error" },
+ { G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN, "G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN", "unexpected-token"
},
+ { G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD, "G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD", "unknown-keyword" },
+ { G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
"G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT", "unterminated-string-constant" },
+ { G_VARIANT_PARSE_ERROR_VALUE_EXPECTED, "G_VARIANT_PARSE_ERROR_VALUE_EXPECTED", "value-expected" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("GVariantParseError", values);
+ }
+
+ return type;
+}
+
+#endif
diff --git a/gperl-gtypes.h b/gperl-gtypes.h
index b51f448..7c5573e 100644
--- a/gperl-gtypes.h
+++ b/gperl-gtypes.h
@@ -79,6 +79,11 @@ GType gperl_spawn_error_get_type (void) G_GNUC_CONST;
#define GPERL_TYPE_THREAD_ERROR gperl_thread_error_get_type ()
GType gperl_thread_error_get_type (void) G_GNUC_CONST;
+#if GLIB_CHECK_VERSION (2, 24, 0)
+#define GPERL_TYPE_VARIANT_PARSE_ERROR gperl_variant_parse_error_get_type ()
+GType gperl_variant_parse_error_get_type (void);
+#endif
+
G_END_DECLS
#endif /* __GPERL_GTYPES_H__ */
diff --git a/gperl.h b/gperl.h
index 2f060a9..7074dcc 100644
--- a/gperl.h
+++ b/gperl.h
@@ -362,8 +362,22 @@ SV * newSVGUserDirectory (GUserDirectory dir);
#endif
/*
- * miscellaneous
+ * -- GVariant ----------------------------------------------------------------
*/
+#if GLIB_CHECK_VERSION (2, 24, 0)
+
+typedef GVariant GVariant_noinc;
+SV * newSVGVariant (GVariant * variant);
+SV * newSVGVariant_noinc (GVariant * variant);
+GVariant * SvGVariant (SV * sv);
+
+typedef GVariantType GVariantType_own;
+SV * newSVGVariantType (const GVariantType * type);
+SV * newSVGVariantType_own (const GVariantType * type);
+const GVariantType * SvGVariantType (SV * sv);
+
+#endif /* 2.24.0 */
+
/*
* --- miscellaneous ----------------------------------------------------------
*/
diff --git a/lib/Glib.pm b/lib/Glib.pm
index 5cb267d..db3ebeb 100644
--- a/lib/Glib.pm
+++ b/lib/Glib.pm
@@ -216,6 +216,155 @@ sub AUTOLOAD {
return $object_or_type->$method (@_);
}
+package Glib::Variant;
+
+my %LEAF_HANDLERS = (
+ b => ['new_boolean', 'get_boolean'],
+ y => ['new_byte', 'get_byte'],
+ n => ['new_int16', 'get_int16'],
+ q => ['new_uint16', 'get_uint16'],
+ i => ['new_int32', 'get_int32'],
+ u => ['new_uint32', 'get_uint32'],
+ x => ['new_int64', 'get_int64'],
+ t => ['new_uint64', 'get_uint64'],
+ h => ['new_handle', 'get_handle'],
+ d => ['new_double', 'get_double'],
+ s => ['new_string', 'get_string'],
+ o => ['new_object_path', 'get_string'],
+ g => ['new_signature', 'get_string'],
+);
+
+# Documented in GVariant.xs.
+sub new {
+ my ($class, $format, @values) = @_;
+ if (!defined $format || $format eq '') {
+ return;
+ }
+
+ my ($ts, $format_rest) = Glib::VariantType::string_scan ($format);
+ my ($value, @values_rest) = @values;
+ my $t = Glib::VariantType->new ($ts);
+ my $v;
+
+ if ($t->is_basic) {
+ my $ctor = $LEAF_HANDLERS{$t->get_string}->[0];
+ $v = Glib::Variant->$ctor ($value);
+ }
+
+ elsif ($t->is_variant) {
+ $v = Glib::Variant->new_variant ($value);
+ }
+
+ elsif ($t->is_array) {
+ my $et = $t->element;
+ my @children;
+ if (eval { defined $#$value }) {
+ @children = map { Glib::Variant->new ($et->get_string, $_) } @$value;
+ } elsif ($et->is_dict_entry && eval { defined scalar %$value }) {
+ while (my ($ek, $ev) = each %$value) {
+ push @children, Glib::Variant->new ($et->get_string, [$ek, $ev]);
+ }
+ } else {
+ Carp::croak ('Expected an array ref');
+ }
+ $v = Glib::Variant->new_array ($et, \ children);
+ }
+
+ elsif ($t->is_maybe) {
+ my $et = $t->element;
+ my $child = defined $value ? Glib::Variant->new ($et->get_string, $value) : undef;
+ $v = Glib::Variant->new_maybe ($et, $child);
+ }
+
+ elsif ($t->is_tuple) {
+ my $n = $t->n_items;
+ if ($n && !eval { $#$value+1 == $n }) {
+ Carp::croak ("Expected an array ref with $n elements");
+ }
+ my @children;
+ for (my ($i, $et) = (0, $t->first); $et; $i++, $et = $et->next) {
+ push @children, Glib::Variant->new ($et->get_string, $value->[$i]);
+ }
+ $v = Glib::Variant->new_tuple (\ children);
+ }
+
+ elsif ($t->is_dict_entry) {
+ my $kt = $t->first;
+ my $vt = $kt->next;
+ my $kv = Glib::Variant->new ($kt->get_string, $value->[0]);
+ my $vv = Glib::Variant->new ($vt->get_string, $value->[1]);
+ $v = Glib::Variant->new_dict_entry ($kv, $vv);
+ }
+
+ else {
+ Carp::croak ("Cannot handle the part '$ts' in the format string '$format'");
+ }
+
+ return wantarray ? ($v, Glib::Variant->new ($format_rest, @values_rest)) : $v;
+}
+
+# Documented in GVariant.xs.
+sub get {
+ my ($v, $format) = @_;
+ if (!defined $format || $format eq '') {
+ return;
+ }
+
+ my ($ts, $format_rest) = Glib::VariantType::string_scan ($format);
+ if (defined $format_rest) {
+ Carp::carp ("Unhandled rest of format string detected: '$format_rest'");
+ }
+ my $t = Glib::VariantType->new ($ts);
+ my $value;
+
+ if ($t->is_basic) {
+ my $getter = $LEAF_HANDLERS{$t->get_string}->[1];
+ $value = $v->$getter;
+ }
+
+ elsif ($t->is_variant) {
+ $value = $v->get_variant;
+ }
+
+ elsif ($t->is_array) {
+ my $et = $t->element;
+ my @children;
+ foreach my $i (1 .. $v->n_children) {
+ push @children, $v->get_child_value ($i-1)->get ($et->get_string);
+ }
+ $value = \ children;
+ }
+
+ elsif ($t->is_maybe) {
+ my $et = $t->element;
+ my $wrapper = $v->get_maybe;
+ $value = defined $wrapper ? $wrapper->get ($et->get_string) : undef;
+ }
+
+ elsif ($t->is_tuple) {
+ my $n = $t->n_items;
+ my @children;
+ for (my ($i, $et) = (0, $t->first); $et; $i++, $et = $et->next) {
+ push @children, $v->get_child_value ($i)->get ($et->get_string);
+ }
+ $value = \ children;
+ }
+
+ elsif ($t->is_dict_entry) {
+ my $kt = $t->first;
+ my $vt = $kt->next;
+ my $kv = $v->get_child_value (0)->get ($kt->get_string);
+ my $vv = $v->get_child_value (1)->get ($vt->get_string);
+ $value = [$kv, $vv];
+ }
+
+ else {
+ Carp::croak ("Cannot handle the part '$ts' in the format string '$format'");
+ }
+
+ return $value;
+}
+
package Glib;
1;
diff --git a/t/variant.t b/t/variant.t
new file mode 100644
index 0000000..8766e5a
--- /dev/null
+++ b/t/variant.t
@@ -0,0 +1,338 @@
+#!perl
+use strict;
+use warnings;
+use utf8;
+use Glib qw/TRUE FALSE/;
+use Test::More;
+
+use constant {
+ MIN_INT64 => "-9223372036854775807",
+ MAX_INT64 => "9223372036854775807",
+
+ MIN_UINT64 => "0",
+ MAX_UINT64 => "18446744073709551615"
+};
+
+if (Glib->CHECK_VERSION (2, 24, 0)) {
+ plan tests => 211;
+} else {
+ plan skip_all => 'Need libglib >= 2.24';
+}
+
+my @leafs = (
+ [ 'new_boolean', 'get_boolean', 'b', TRUE ],
+ [ 'new_byte', 'get_byte', 'y', 2**8-1 ],
+ [ 'new_int16', 'get_int16', 'n', 2**15-1 ],
+ [ 'new_uint16', 'get_uint16', 'q', 2**16-1 ],
+ [ 'new_int32', 'get_int32', 'i', 2**31-1 ],
+ [ 'new_uint32', 'get_uint32', 'u', 2**32-1 ],
+ [ 'new_int64', 'get_int64', 'x', MAX_INT64 ],
+ [ 'new_uint64', 'get_uint64', 't', MAX_UINT64 ],
+ [ 'new_handle', 'get_handle', 'h', 2**31-1 ],
+ [ 'new_double', 'get_double', 'd', 0.25 ],
+ [ 'new_string', 'get_string', 's', 'äöü⁂üöä' ],
+ [ 'new_object_path', 'get_string', 'o', '/a/b/c' ],
+ [ 'new_signature', 'get_string', 'g', 'ii' ],
+);
+
+{
+ foreach my $l (@leafs) {
+ my ($ctor, $getter, $type_string, $value) = @$l;
+ note ($ctor);
+ my $v = Glib::Variant->$ctor ($value);
+ isa_ok ($v, 'Glib::Variant');
+ isa_ok ($v->get_type, 'Glib::VariantType');
+ ok ($v->is_of_type ($v->get_type));
+ is ($v->get_type_string, $type_string);
+ ok (!$v->is_container);
+ is ($v->classify, $type_string);
+ is ($v->$getter, $value);
+ }
+
+ ok (Glib::Variant::is_object_path ('/a/b/c'));
+ ok (Glib::Variant::is_signature ('ii'));
+}
+
+note ('new_variant');
+{
+ {
+ my $child = Glib::Variant->new_byte (23);
+ my $wrapper = Glib::Variant->new_variant ($child);
+ isa_ok ($wrapper, 'Glib::Variant');
+ is ($wrapper->get_type_string, 'v');
+ is ($wrapper->classify, 'v');
+ {
+ my $wrapped_child = $wrapper->get_variant;
+ is ($wrapped_child->get_byte, 23);
+ }
+ undef $child;
+ {
+ my $wrapped_child = $wrapper->get_variant;
+ is ($wrapped_child->get_byte, 23);
+ }
+ }
+ {
+ my $child = Glib::Variant->new_byte (23);
+ my $wrapper = Glib::Variant->new_variant ($child);
+ undef $wrapper;
+ is ($child->get_byte, 23);
+ }
+}
+
+note ('new_bytestring');
+SKIP: {
+ skip 'new_bytestring', 6
+ unless Glib->CHECK_VERSION (2, 26, 0);
+
+ {
+ my $bs = "\x{a3}\x{ff}";
+ my $v = Glib::Variant->new_bytestring ($bs);
+ isa_ok ($v, 'Glib::Variant');
+ is ($v->get_type_string, 'ay');
+ is ($v->classify, 'a');
+ is ($v->get_bytestring, $bs);
+ }
+
+ {
+ my $bs = "\x{a3}\x{ff}";
+ utf8::upgrade ($bs);
+ my $v = Glib::Variant->new_bytestring ($bs);
+ is ($v->get_bytestring, $bs);
+ }
+
+ {
+ my $bs = "\x{a3}\x{ff}";
+ utf8::encode ($bs);
+ my $v = Glib::Variant->new_bytestring ($bs);
+ is ($v->get_bytestring, $bs);
+ }
+}
+
+note ('new_maybe');
+{
+ my $child_type = 'y';
+ my $child = Glib::Variant->new_byte (42);
+ {
+ my $wrapper = Glib::Variant->new_maybe ($child_type, undef);
+ isa_ok ($wrapper, 'Glib::Variant');
+ is ($wrapper->get_type_string, 'my');
+ is ($wrapper->classify, 'm');
+ ok (! defined $wrapper->get_maybe);
+ is ($wrapper->n_children, 0);
+ }
+ {
+ my $wrapper = Glib::Variant->new_maybe (undef, $child);
+ isa_ok ($wrapper, 'Glib::Variant');
+ is ($wrapper->get_type_string, 'my');
+ is ($wrapper->classify, 'm');
+ is ($wrapper->get_maybe->get_byte, $child->get_byte);
+ is ($wrapper->n_children, 1);
+ is ($wrapper->get_child_value (0)->get_byte, 42);
+ }
+ {
+ my $wrapper = Glib::Variant->new_maybe ($child_type, $child);
+ isa_ok ($wrapper, 'Glib::Variant');
+ is ($wrapper->get_type_string, 'my');
+ is ($wrapper->classify, 'm');
+ is ($wrapper->get_maybe->get_byte, $child->get_byte);
+ is ($wrapper->n_children, 1);
+ is ($wrapper->get_child_value (0)->get_byte, $child->get_byte);
+ }
+}
+
+note ('new_array');
+{
+ my $child_type = 'y';
+ my $children = [map { Glib::Variant->new_byte ($_) } (23, 42, 65)];
+ {
+ my $array = Glib::Variant->new_array ($child_type, []);
+ isa_ok ($array, 'Glib::Variant');
+ is ($array->get_type_string, 'ay');
+ is ($array->classify, 'a');
+ is ($array->n_children, 0);
+ }
+ {
+ my $array = Glib::Variant->new_array (undef, $children);
+ isa_ok ($array, 'Glib::Variant');
+ is ($array->get_type_string, 'ay');
+ is ($array->classify, 'a');
+ is ($array->n_children, 3);
+ is ($array->get_child_value (2)->get_byte, $children->[2]->get_byte);
+ }
+ {
+ my $array = Glib::Variant->new_array ($child_type, $children);
+ isa_ok ($array, 'Glib::Variant');
+ is ($array->get_type_string, 'ay');
+ is ($array->classify, 'a');
+ is ($array->n_children, 3);
+ is ($array->get_child_value (2)->get_byte, $children->[2]->get_byte);
+ }
+}
+
+note ('new_tuple');
+{
+ my $children = [Glib::Variant->new_byte (23),
+ Glib::Variant->new_string ('forty-two'),
+ Glib::Variant->new_double (0.25)];
+ {
+ my $tuple = Glib::Variant->new_tuple ([]);
+ isa_ok ($tuple, 'Glib::Variant');
+ is ($tuple->get_type_string, '()');
+ is ($tuple->classify, '(');
+ is ($tuple->n_children, 0);
+ }
+ {
+ my $tuple = Glib::Variant->new_tuple ($children);
+ isa_ok ($tuple, 'Glib::Variant');
+ is ($tuple->get_type_string, '(ysd)');
+ is ($tuple->classify, '(');
+ is ($tuple->n_children, 3);
+ is ($tuple->get_child_value (2)->get_double, $children->[2]->get_double);
+ }
+}
+
+note ('new_dict_entry');
+{
+ my $key = Glib::Variant->new_string ('forty-two');
+ my $value = Glib::Variant->new_byte (23);
+ {
+ my $entry = Glib::Variant->new_dict_entry ($key, $value);
+ isa_ok ($entry, 'Glib::Variant');
+ is ($entry->get_type_string, '{sy}');
+ is ($entry->classify, '{');
+ is ($entry->get_child_value (1)->get_byte, $value->get_byte);
+ }
+}
+
+note ('lookup_value');
+{
+ my $entries = [map { Glib::Variant->new_dict_entry (Glib::Variant->new_string ($_->[0]),
+ Glib::Variant->new_byte ($_->[1])) }
+ (['one' => 1], ['two' => 2], ['four' => 4], ['eight' => 8])];
+ my $array = Glib::Variant->new_array ('{sy}', $entries);
+ is ($array->lookup_value ('one', 'y')->get_byte, 1);
+ is ($array->lookup_value ('two', undef)->get_byte, 2);
+ ok (! defined $array->lookup_value ('fourr', undef));
+}
+
+note ('printing and parsing');
+{
+ {
+ my $a = Glib::Variant->new_byte (23);
+ my $text = $a->print (TRUE);
+ is ($text, 'byte 0x17');
+ is (Glib::Variant::parse (undef, $text)->get_byte, 23);
+ is (Glib::Variant::parse ('y', $text)->get_byte, 23);
+ }
+
+ {
+ my $text = 'byte 0x17';
+ eval { Glib::Variant::parse ('b', $text)->get_byte };
+ ok (Glib::Error::matches ($@, 'Glib::Variant::ParseError', 'type-error'));
+ }
+}
+
+note ('misc.');
+{
+ my $a = Glib::Variant->new_byte (23);
+ my $b = Glib::Variant->new_byte (42);
+
+ ok (defined $a->get_size);
+ ok (defined $a->hash);
+ ok ($a->equal ($a));
+ ok (! $a->equal ($b));
+ is ($a->get_normal_form->get_byte, $a->get_byte);
+ ok ($a->is_normal_form);
+ is ($a->byteswap->get_byte, $a->get_byte);
+
+ SKIP: {
+ skip 'compare', 2
+ unless Glib->CHECK_VERSION (2, 26, 0);
+ cmp_ok ($a->compare ($b), '<', 0);
+ cmp_ok ($b->compare ($a), '>', 1);
+ }
+}
+
+note ('convenience constructor and accessor');
+{
+ note (' leafs');
+ foreach my $l (@leafs) {
+ my ($ctor, $getter, $type_string, $value) = @$l;
+ my $v = Glib::Variant->new ($type_string, $value);
+ is ($v->get_type_string, $type_string);
+ is ($v->get ($type_string), $value);
+ }
+
+ note (' list context');
+ {
+ my ($v) = Glib::Variant->new ('i', 23);
+ is ($v->get ('i'), 23);
+
+ my ($v1, $v2, $v3) = Glib::Variant->new ('ids', 23, 0.25, 'äöü');
+ is ($v1->get ('i'), 23);
+ is ($v2->get ('d'), 0.25);
+ is ($v3->get ('s'), 'äöü');
+ }
+
+ note (' variant');
+ {
+ my $child = Glib::Variant->new_byte (23);
+ my $wrapper = Glib::Variant->new ('v', $child);
+ is ($wrapper->get_type_string, 'v');
+ {
+ my $wrapped_child = $wrapper->get ('v');
+ is ($wrapped_child->get_byte, 23);
+ }
+ }
+
+ note (' array');
+ {
+ my $v1 = Glib::Variant->new ('as', ['äöü', 'Perl', '💑']);
+ is_deeply ($v1->get ('as'), ['äöü', 'Perl', '💑']);
+
+ my $v2 = Glib::Variant->new ('aai', [[23, 42], [2, 3], [4, 2]]);
+ is_deeply ($v2->get ('aai'), [[23, 42], [2, 3], [4, 2]]);
+
+ is (Glib::Variant->new ('ai', [])->n_children, 0);
+ is (Glib::Variant->new ('ai', undef)->n_children, 0);
+ }
+
+ note (' maybe');
+ {
+ my $v1 = Glib::Variant->new ('mi', undef);
+ ok (! defined $v1->get ('mi'));
+
+ my $v2 = Glib::Variant->new ('mi', 23);
+ is ($v2->get ('mi'), 23);
+
+ my $v3 = Glib::Variant->new ('mai', undef);
+ ok (! defined $v3->get ('mai'));
+
+ my $v4 = Glib::Variant->new ('mai', [23, 42]);
+ is_deeply ($v4->get ('mai'), [23, 42]);
+ }
+
+ note (' tuple');
+ {
+ my $v1 = Glib::Variant->new ('()');
+ is ($v1->n_children, 0);
+
+ my $v2 = Glib::Variant->new ('(si)', ['äöü', 23]);
+ is_deeply ($v2->get ('(si)'), ['äöü', 23]);
+
+ my $v3 = Glib::Variant->new ('a(si)', [['äöü', 23], ['Perl', 42], ['💑', 2342]]);
+ is_deeply ($v3->get ('a(si)'), [['äöü', 23], ['Perl', 42], ['💑', 2342]]);
+ }
+
+ note (' dict entry');
+ {
+ my $v1 = Glib::Variant->new ('{si}', ['äöü', 23]);
+ is_deeply ($v1->get ('{si}'), ['äöü', 23]);
+
+ my $v2 = Glib::Variant->new ('a{si}', [['äöü', 23], ['Perl', 42], ['💑', 2342]]);
+ is_deeply ($v2->get ('a{si}'), [['äöü', 23], ['Perl', 42], ['💑', 2342]]);
+
+ my $v3 = Glib::Variant->new ('a{si}', {'äöü' => 23, 'Perl' => 42, '💑' => 2342});
+ is_deeply ($v2->get ('a{si}'), [['äöü', 23], ['Perl', 42], ['💑', 2342]]);
+ }
+}
diff --git a/typemap b/typemap
index 7307291..5aec2fb 100644
--- a/typemap
+++ b/typemap
@@ -100,6 +100,14 @@ GOptionGroup_own * T_GPERL_GENERIC_WRAPPER
GUserDirectory T_GPERL_GENERIC_WRAPPER
+GVariant * T_GPERL_GENERIC_WRAPPER
+const GVariant * T_GPERL_GENERIC_WRAPPER
+GVariant_noinc * T_GPERL_GENERIC_WRAPPER
+
+GVariantType * T_GPERL_GENERIC_WRAPPER
+const GVariantType * T_GPERL_GENERIC_WRAPPER
+GVariantType_own * T_GPERL_GENERIC_WRAPPER
+
###############################################################################
INPUT
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]