1//GVariant : GVariant — strongly typed value datatype
2// https://developer.gnome.org/glib/2.26/glib-GVariant.html
3
4package glib
5
6// #include "gvariant.go.h"
7// #include "glib.go.h"
8import "C"
9
10import (
11	"fmt"
12	"unsafe"
13)
14
15/*
16 * GVariant
17 */
18
19// IVariant is an interface type implemented by Variant and all types which embed
20// an Variant.  It is meant to be used as a type for function arguments which
21// require GVariants or any subclasses thereof.
22type IVariant interface {
23	ToGVariant() *C.GVariant
24	ToVariant() *Variant
25}
26
27// A Variant is a representation of GLib's GVariant.
28type Variant struct {
29	GVariant *C.GVariant
30}
31
32// ToGVariant exposes the underlying *C.GVariant type for this Variant,
33// necessary to implement IVariant.
34func (v *Variant) ToGVariant() *C.GVariant {
35	if v == nil {
36		return nil
37	}
38	return v.native()
39}
40
41// ToVariant returns this Variant, necessary to implement IVariant.
42func (v *Variant) ToVariant() *Variant {
43	return v
44}
45
46// newVariant creates a new Variant from a GVariant pointer.
47func newVariant(p *C.GVariant) *Variant {
48	return &Variant{GVariant: p}
49}
50
51// VariantFromUnsafePointer returns a Variant from an unsafe pointer.
52// XXX: unnecessary footgun?
53//func VariantFromUnsafePointer(p unsafe.Pointer) *Variant {
54//	return &Variant{C.toGVariant(p)}
55//}
56
57// native returns a pointer to the underlying GVariant.
58func (v *Variant) native() *C.GVariant {
59	if v == nil || v.GVariant == nil {
60		return nil
61	}
62	return v.GVariant
63}
64
65// Native returns a pointer to the underlying GVariant.
66func (v *Variant) Native() uintptr {
67	return uintptr(unsafe.Pointer(v.native()))
68}
69
70// TypeString returns the g variant type string for this variant.
71func (v *Variant) TypeString() string {
72	// the string returned from this belongs to GVariant and must not be freed.
73	return C.GoString((*C.char)(C.g_variant_get_type_string(v.native())))
74}
75
76// IsContainer returns true if the variant is a container and false otherwise.
77func (v *Variant) IsContainer() bool {
78	return gobool(C.g_variant_is_container(v.native()))
79}
80
81// IsFloating returns true if the variant has a floating reference count.
82// XXX: this isn't useful without ref_sink/take_ref, which are themselves
83// perhaps not useful for most Go code that may use variants.
84//func (v *Variant) IsFloating() bool {
85//	return gobool(C.g_variant_is_floating(v.native()))
86//}
87
88// GetBoolean returns the bool value of this variant.
89func (v *Variant) GetBoolean() bool {
90	return gobool(C.g_variant_get_boolean(v.native()))
91}
92
93// GetString returns the string value of the variant.
94func (v *Variant) GetString() string {
95	var len C.gsize
96	gc := C.g_variant_get_string(v.native(), &len)
97	defer C.g_free(C.gpointer(gc))
98	return C.GoStringN((*C.char)(gc), (C.int)(len))
99}
100
101// GetStrv returns a slice of strings from this variant.  It wraps
102// g_variant_get_strv, but returns copies of the strings instead.
103func (v *Variant) GetStrv() []string {
104	gstrv := C.g_variant_get_strv(v.native(), nil)
105	// we do not own the memory for these strings, so we must not use strfreev
106	// but we must free the actual pointer we receive.
107	c := gstrv
108	defer C.g_free(C.gpointer(gstrv))
109	var strs []string
110
111	for *c != nil {
112		strs = append(strs, C.GoString((*C.char)(*c)))
113		c = C.next_gcharptr(c)
114	}
115	return strs
116}
117
118// GetInt returns the int64 value of the variant if it is an integer type, and
119// an error otherwise.  It wraps variouns `g_variant_get_*` functions dealing
120// with integers of different sizes.
121func (v *Variant) GetInt() (int64, error) {
122	t := v.Type().String()
123	var i int64
124	switch t {
125	case "y":
126		i = int64(C.g_variant_get_byte(v.native()))
127	case "n":
128		i = int64(C.g_variant_get_int16(v.native()))
129	case "q":
130		i = int64(C.g_variant_get_uint16(v.native()))
131	case "i":
132		i = int64(C.g_variant_get_int32(v.native()))
133	case "u":
134		i = int64(C.g_variant_get_uint32(v.native()))
135	case "x":
136		i = int64(C.g_variant_get_int64(v.native()))
137	case "t":
138		i = int64(C.g_variant_get_uint64(v.native()))
139	default:
140		return 0, fmt.Errorf("variant type %s not an integer type", t)
141	}
142	return i, nil
143}
144
145// Type returns the VariantType for this variant.
146func (v *Variant) Type() *VariantType {
147	return newVariantType(C.g_variant_get_type(v.native()))
148}
149
150// IsType returns true if the variant's type matches t.
151func (v *Variant) IsType(t *VariantType) bool {
152	return gobool(C.g_variant_is_of_type(v.native(), t.native()))
153}
154
155// String wraps g_variant_print().  It returns a string understood
156// by g_variant_parse().
157func (v *Variant) String() string {
158	gc := C.g_variant_print(v.native(), gbool(false))
159	defer C.g_free(C.gpointer(gc))
160	return C.GoString((*C.char)(gc))
161}
162
163// AnnotatedString wraps g_variant_print(), but returns a type-annotated
164// string.
165func (v *Variant) AnnotatedString() string {
166	gc := C.g_variant_print(v.native(), gbool(true))
167	defer C.g_free(C.gpointer(gc))
168	return C.GoString((*C.char)(gc))
169}
170
171//void	g_variant_unref ()
172//GVariant *	g_variant_ref ()
173//GVariant *	g_variant_ref_sink ()
174//GVariant *	g_variant_take_ref ()
175//gint	g_variant_compare ()
176//GVariantClass	g_variant_classify ()
177//gboolean	g_variant_check_format_string ()
178//void	g_variant_get ()
179//void	g_variant_get_va ()
180//GVariant *	g_variant_new ()
181//GVariant *	g_variant_new_va ()
182//GVariant *	g_variant_new_boolean ()
183//GVariant *	g_variant_new_byte ()
184//GVariant *	g_variant_new_int16 ()
185//GVariant *	g_variant_new_uint16 ()
186//GVariant *	g_variant_new_int32 ()
187//GVariant *	g_variant_new_uint32 ()
188//GVariant *	g_variant_new_int64 ()
189//GVariant *	g_variant_new_uint64 ()
190//GVariant *	g_variant_new_handle ()
191//GVariant *	g_variant_new_double ()
192//GVariant *	g_variant_new_string ()
193//GVariant *	g_variant_new_take_string ()
194//GVariant *	g_variant_new_printf ()
195//GVariant *	g_variant_new_object_path ()
196//gboolean	g_variant_is_object_path ()
197//GVariant *	g_variant_new_signature ()
198//gboolean	g_variant_is_signature ()
199//GVariant *	g_variant_new_variant ()
200//GVariant *	g_variant_new_strv ()
201//GVariant *	g_variant_new_objv ()
202//GVariant *	g_variant_new_bytestring ()
203//GVariant *	g_variant_new_bytestring_array ()
204//guchar	g_variant_get_byte ()
205//gint16	g_variant_get_int16 ()
206//guint16	g_variant_get_uint16 ()
207//gint32	g_variant_get_int32 ()
208//guint32	g_variant_get_uint32 ()
209//gint64	g_variant_get_int64 ()
210//guint64	g_variant_get_uint64 ()
211//gint32	g_variant_get_handle ()
212//gdouble	g_variant_get_double ()
213//const gchar *	g_variant_get_string ()
214//gchar *	g_variant_dup_string ()
215//GVariant *	g_variant_get_variant ()
216//const gchar **	g_variant_get_strv ()
217//gchar **	g_variant_dup_strv ()
218//const gchar **	g_variant_get_objv ()
219//gchar **	g_variant_dup_objv ()
220//const gchar *	g_variant_get_bytestring ()
221//gchar *	g_variant_dup_bytestring ()
222//const gchar **	g_variant_get_bytestring_array ()
223//gchar **	g_variant_dup_bytestring_array ()
224//GVariant *	g_variant_new_maybe ()
225//GVariant *	g_variant_new_array ()
226//GVariant *	g_variant_new_tuple ()
227//GVariant *	g_variant_new_dict_entry ()
228//GVariant *	g_variant_new_fixed_array ()
229//GVariant *	g_variant_get_maybe ()
230//gsize	g_variant_n_children ()
231//GVariant *	g_variant_get_child_value ()
232//void	g_variant_get_child ()
233//GVariant *	g_variant_lookup_value ()
234//gboolean	g_variant_lookup ()
235//gconstpointer	g_variant_get_fixed_array ()
236//gsize	g_variant_get_size ()
237//gconstpointer	g_variant_get_data ()
238//GBytes *	g_variant_get_data_as_bytes ()
239//void	g_variant_store ()
240//GVariant *	g_variant_new_from_data ()
241//GVariant *	g_variant_new_from_bytes ()
242//GVariant *	g_variant_byteswap ()
243//GVariant *	g_variant_get_normal_form ()
244//gboolean	g_variant_is_normal_form ()
245//guint	g_variant_hash ()
246//gboolean	g_variant_equal ()
247//gchar *	g_variant_print ()
248//GString *	g_variant_print_string ()
249//GVariantIter *	g_variant_iter_copy ()
250//void	g_variant_iter_free ()
251//gsize	g_variant_iter_init ()
252//gsize	g_variant_iter_n_children ()
253//GVariantIter *	g_variant_iter_new ()
254//GVariant *	g_variant_iter_next_value ()
255//gboolean	g_variant_iter_next ()
256//gboolean	g_variant_iter_loop ()
257//void	g_variant_builder_unref ()
258//GVariantBuilder *	g_variant_builder_ref ()
259//GVariantBuilder *	g_variant_builder_new ()
260//void	g_variant_builder_init ()
261//void	g_variant_builder_clear ()
262//void	g_variant_builder_add_value ()
263//void	g_variant_builder_add ()
264//void	g_variant_builder_add_parsed ()
265//GVariant *	g_variant_builder_end ()
266//void	g_variant_builder_open ()
267//void	g_variant_builder_close ()
268//void	g_variant_dict_unref ()
269//GVariantDict *	g_variant_dict_ref ()
270//GVariantDict *	g_variant_dict_new ()
271//void	g_variant_dict_init ()
272//void	g_variant_dict_clear ()
273//gboolean	g_variant_dict_contains ()
274//gboolean	g_variant_dict_lookup ()
275//GVariant *	g_variant_dict_lookup_value ()
276//void	g_variant_dict_insert ()
277//void	g_variant_dict_insert_value ()
278//gboolean	g_variant_dict_remove ()
279//GVariant *	g_variant_dict_end ()
280//#define	G_VARIANT_PARSE_ERROR
281//GVariant *	g_variant_parse ()
282//GVariant *	g_variant_new_parsed_va ()
283//GVariant *	g_variant_new_parsed ()
284//gchar *	g_variant_parse_error_print_context ()
285