1/* Copyright 2010 The glibmm Development Team 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17_DEFS(glibmm,glib) 18 19#include <glibmmconfig.h> 20#include <glibmm/varianttype.h> 21#include <glibmm/variantiter.h> 22#include <glibmm/variantdbusstring.h> 23#include <glibmm/refptr.h> 24#include <glibmm/ustring.h> 25#include <glibmm/error.h> 26#include <utility> 27#include <vector> 28#include <map> 29#include <memory> 30#include <tuple> 31#include <stdexcept> 32#include <typeinfo> 33#include <cstddef> 34 35namespace Glib 36{ 37class Bytes; 38 39/** @defgroup Variant Variant Data Types 40 * 41 * The Variant classes deal with strongly typed 42 * variant data. A Variant stores a value along with 43 * information about the type of that value. The range of possible 44 * values is determined by the type. The type system used is VariantType. 45 * 46 * See the VariantBase class and its derived types, such as VariantContainerBase, 47 * and the Variant<> template type. 48 * 49 * Variant instances always have a type and a value (which are given 50 * at construction time). The type and value of a Variant 51 * can never change other than by the Variant itself being 52 * destroyed. A Variant cannot contain a pointer. 53 * 54 * Variant is heavily optimised for dealing with data in serialised 55 * form. It works particularly well with data located in memory-mapped 56 * files. It can perform nearly all deserialisation operations in a 57 * small constant time, usually touching only a single memory page. 58 * Serialised Variant data can also be sent over the network. 59 * 60 * Variant is largely compatible with D-Bus. Almost all types of 61 * Variant instances can be sent over D-Bus. See VariantType for 62 * exceptions. 63 * 64 * There is a Python-inspired text language for describing Variant 65 * values. Variant includes a printer for this language and a parser 66 * with type inferencing. 67 */ 68 69//Note: We wrap this because it is thrown by GtkBuilder's functions. 70// See https://bugzilla.gnome.org/show_bug.cgi?id=708206 71// It would also be thrown by parse() if we wrap g_variant_parse(). 72// Now (2014-01-30) it's also thrown by Gio::Action::parse_detailed_name(). 73/** %Exception class for Variant parse errors. 74 */ 75_WRAP_GERROR(VariantParseError, GVariantParseError, G_VARIANT_PARSE_ERROR, NO_GTYPE, decl_prefix GLIBMM_API) 76 77//TODO: Add this documentation from the API if we are confident of it for the C++ wrapper: 78// #GVariant is completely threadsafe. A #GVariant instance can be 79// concurrently accessed in any way from any number of threads without 80// problems. 81// Note that we don't copy GVariant's documentation about Memory Use because 82// it seems easy to get out of sync and people can look at that C documentation if necessary. 83 84/** This is the base class for all Variant types. 85 * 86 * If the actual type is known at compile-time then you should use a specific 87 * Variant<>, such as Variant<int>. Otherwise, you may use get_type(), 88 * is_of_type(), or cast_dynamic(). 89 * 90 * @newin{2,28} 91 * @ingroup Variant 92 */ 93class GLIBMM_API VariantBase 94{ 95 _CLASS_OPAQUE_COPYABLE(VariantBase, GVariant, NONE, g_variant_ref_sink, g_variant_unref, GLIBMM_API) 96 _CUSTOM_CTOR_CAST() 97 _IGNORE(g_variant_ref, g_variant_ref_sink, g_variant_take_ref, g_variant_unref, 98 g_variant_get, g_variant_get_va) 99public: 100 101_DEPRECATE_IFDEF_START 102 /** This typedef is just to make it more obvious that 103 * our operator const void* should be used like operator bool(). 104 * 105 * @deprecated Use the explicit operator bool() instead. 106 */ 107 using BoolExpr = const void*; 108 109 /** Test whether the Variant has an underlying instance. 110 * 111 * Mimics usage of pointers: 112 * @code 113 * if (variant) 114 * do_something(); 115 * @endcode 116 * 117 * @deprecated Use the explicit operator bool() instead. 118 * 119 * @newin{2,36} 120 */ 121 operator BoolExpr() const; 122_DEPRECATE_IFDEF_END 123 124 /** Test whether the Variant has an underlying instance. 125 * 126 * @newin{2,50} 127 */ 128 explicit operator bool() const; 129 130 /** Replace the underlying GVariant. 131 * This is for use by methods that take a VariantBase& as an output 132 * parameter. 133 * 134 * @param cobject The GVariant* obtained from a C function. 135 * @param take_a_reference Whether this method should take a reference, for 136 * instance if the C function has not given one. 137 */ 138 void init(const GVariant* cobject, bool take_a_reference = false); 139 140// It's necessary to take an extra reference of the 'const GVariantType*' 141// returned by g_variant_get_type() because it doesn't do that already. 142#m4 _CONVERSION(`const GVariantType*',`VariantType',`Glib::wrap(const_cast<GVariantType*>($3), true)') 143 _WRAP_METHOD(VariantType get_type() const, g_variant_get_type) 144 145 _WRAP_METHOD(std::string get_type_string() const, g_variant_get_type_string) 146 _WRAP_METHOD(bool is_floating() const, g_variant_is_floating) 147 _WRAP_METHOD(bool is_of_type(const VariantType& type) const, g_variant_is_of_type) 148 _WRAP_METHOD(bool is_container() const, g_variant_is_container) 149 _WRAP_METHOD(GVariantClass classify() const, g_variant_classify) 150 151 _WRAP_METHOD(gsize get_size() const, g_variant_get_size) 152 _WRAP_METHOD(gconstpointer get_data(), g_variant_get_data, deprecated "Use the const version instead.") 153 _WRAP_METHOD(gconstpointer get_data() const, g_variant_get_data, newin "2,46") 154 _WRAP_METHOD(Glib::RefPtr<const Glib::Bytes> get_data_as_bytes() const, g_variant_get_data_as_bytes, newin "2,46") 155 _WRAP_METHOD(void store(gpointer data) const, g_variant_store) 156 157 _WRAP_METHOD(Glib::ustring print(bool type_annotate = false) const, g_variant_print) 158 _IGNORE(g_variant_print_string) 159 160 #m4 _CONVERSION(`const VariantBase&',`gconstpointer',`const_cast<GVariant*>(($3).gobj())') 161 _WRAP_METHOD(guint hash() const, g_variant_hash) 162 163 /** Checks if @a *this and @a other have the same type and value. 164 * 165 * @newin{2,24} 166 * 167 * @param other The Variant to compare with. 168 * @return <tt>true</tt> if @a *this and @a other are equal. 169 */ 170 _WRAP_METHOD(bool equal(const VariantBase& other) const, g_variant_equal) 171 172 /** Gets a VariantBase instance that has the same value as this variant and 173 * is trusted to be in normal form. 174 * 175 * If this variant is already trusted to be in normal form then a new 176 * reference to the variant is returned. 177 * 178 * If this variant is not already trusted, then it is scanned to check if it 179 * is in normal form. If it is found to be in normal form then it is marked 180 * as trusted and a new reference to it is returned. 181 * 182 * If this variant is found not to be in normal form then a new trusted 183 * VariantBase is created with the same value as this variant. 184 * 185 * It makes sense to call this function if you've received variant data from 186 * untrusted sources and you want to ensure your serialised output is 187 * definitely in normal form. 188 * 189 * @param result A location in which to store the trusted VariantBase. 190 * @newin{2,24} 191 */ 192 void get_normal_form(VariantBase& result) const; 193 _IGNORE(g_variant_get_normal_form) 194 195 _WRAP_METHOD(bool is_normal_form() const, g_variant_is_normal_form) 196 197 /** Performs a byteswapping operation on the contents of this variant. The 198 * result is that all multi-byte numeric data contained in the variant is 199 * byteswapped. That includes 16, 32, and 64bit signed and unsigned integers 200 * as well as file handles and double precision floating point values. 201 * 202 * This function is an identity mapping on any value that does not contain 203 * multi-byte numeric data. That include strings, booleans, bytes and 204 * containers containing only these things (recursively). 205 * 206 * The returned value is always in normal form and is marked as trusted. 207 * 208 * @param result A location in which to store the byteswapped form of this 209 * variant. 210 * @newin{2,24} 211 */ 212 void byteswap(VariantBase& result) const; 213 _IGNORE(g_variant_byteswap) 214 215 _WRAP_METHOD(bool check_format_string(const std::string& format_string, bool copy_only = false) const, g_variant_check_format_string) 216 217 //Ignore private API from gvariant-core.h: 218 _IGNORE(g_variant_is_trusted, g_variant_get_type_info) 219 220 /** Cast to a specific variant type. 221 * For instance: 222 * @code 223 * Variant<std::string> derived = VariantBase::cast_dynamic< Variant<std::string> >(base); 224 * @endcode 225 * 226 * @param v The variant to cast to a specific type. 227 * @result The variant as a specific type. 228 * @throws std::bad_cast if the Variant was not of the expected type. 229 */ 230 template<class V_CastTo> 231 static V_CastTo cast_dynamic(const VariantBase& v); 232 233 _IGNORE(g_variant_dict_new) 234 235protected: 236#ifndef DOXYGEN_SHOULD_SKIP_THIS 237 /** Used by cast_dynamic(). 238 * In addition to an exact match, the following casts are possible: 239 * - VARIANT_TYPE_OBJECT_PATH and VARIANT_TYPE_SIGNATURE can be cast to 240 * VARIANT_TYPE_STRING (Glib::ustring). 241 * - VARIANT_TYPE_STRING, VARIANT_TYPE_OBJECT_PATH and VARIANT_TYPE_SIGNATURE 242 * can be cast to VARIANT_TYPE_BYTESTRING (std::string). 243 * - VARIANT_TYPE_HANDLE can be cast to VARIANT_TYPE_INT32. 244 * 245 * These casts are possible also when they are parts of a more complicated type. 246 * E.g. in Variant<std::map<Glib::ustring, std::vector<std::string> > > the map's keys 247 * can be VARIANT_TYPE_OBJECT_PATH and the vector's elements can be VARIANT_TYPE_SIGNATURE. 248 * @newin{2,46} 249 */ 250 bool is_castable_to(const VariantType& supertype) const; 251#endif //DOXYGEN_SHOULD_SKIP_THIS 252 253private: 254 /** Relational operators are deleted to prevent invalid conversion 255 * to const void*. 256 */ 257 bool operator<(const VariantBase& src) const; 258 259 /// See operator<(). 260 bool operator<=(const VariantBase& src) const; 261 262 /// See operator<(). 263 bool operator>(const VariantBase& src) const; 264 265 /// See operator<(). 266 bool operator>=(const VariantBase& src) const; 267 268 /// See operator<(). 269 bool operator==(const VariantBase& src) const; 270 271 /// See operator<(). 272 bool operator!=(const VariantBase& src) const; 273}; 274 275template<class V_CastTo> 276V_CastTo VariantBase::cast_dynamic(const VariantBase& v) 277{ 278 if(!(v.gobj())) 279 { 280 return V_CastTo(); 281 } 282 if(v.is_castable_to(V_CastTo::variant_type())) 283 { 284 return V_CastTo(const_cast<GVariant*>(v.gobj()), true); 285 } 286 else 287 { 288 throw std::bad_cast(); 289 } 290} 291 292/** Base class from which string variant classes derive. 293 * @newin{2,28} 294 * @ingroup Variant 295 */ 296class GLIBMM_API VariantStringBase : public VariantBase 297{ 298 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 299 _CLASS_GENERIC(VariantStringBase, GVariant) 300 301public: 302 using CType = GVariant*; 303 using CppType = VariantStringBase; 304 305 /// Default constructor. 306 VariantStringBase(); 307 308 /** GVariant constructor. 309 * @param castitem The GVariant to wrap. 310 * @param take_a_reference Whether to take an extra reference of the 311 * GVariant or not (not taking one could destroy the GVariant with the 312 * wrapper). 313 */ 314 explicit VariantStringBase(GVariant* castitem, bool take_a_reference = false); 315 316 /** Creates a D-Bus object path variant with the contents of @a object_path. 317 * @a object_path must be a valid D-Bus object path. Use is_object_path() if unsure. 318 * 319 * @param[out] output A location in which to store the new object path variant 320 * instance. 321 * @param object_path An object path string. 322 * @newin{2,28} 323 */ 324 static void create_object_path(VariantStringBase& output, 325 const std::string& object_path); 326 _IGNORE(g_variant_new_object_path) 327 328 _WRAP_METHOD(static bool is_object_path(const std::string& string), g_variant_is_object_path) 329 330 /** Creates a D-Bus type signature variant with the contents of @a signature. 331 * @a signature must be a valid D-Bus type signature. Use is_signature() if unsure. 332 * 333 * @param[out] output A location in which to store the new signature variant 334 * instance. 335 * @param signature A signature string. 336 * @newin{2,28} 337 */ 338 static void create_signature(VariantStringBase& output, 339 const std::string& signature); 340 _IGNORE(g_variant_new_signature) 341 342 _WRAP_METHOD(static bool is_signature(const std::string& string), g_variant_is_signature) 343}; 344 345/** The base class for multiple-item Variants, such as Variants containing 346 * tuples or arrays, and also for maybe-typed (that is, nullable) Variant types. 347 * 348 * @newin{2,28} 349 * @ingroup Variant 350 */ 351class GLIBMM_API VariantContainerBase : public VariantBase 352{ 353 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 354 _CLASS_GENERIC(VariantContainerBase, GVariant) 355 356public: 357 using CType = GVariant*; 358 using CppType = VariantContainerBase; 359 360 /// Default constructor. 361 VariantContainerBase(); 362 363 /** GVariant constructor. 364 * @param castitem The GVariant to wrap. 365 * @param take_a_reference Whether to take an extra reference of the 366 * GVariant or not (not taking one could destroy the GVariant with the 367 * wrapper). 368 */ 369 explicit VariantContainerBase(GVariant* castitem, bool take_a_reference = false); 370 371 /** Create a tuple variant from a vector of its variant children. 372 * @param children The vector containing the children of the container. 373 * @return The newly created tuple variant (as a VariantContainerBase). 374 */ 375 static VariantContainerBase create_tuple(const std::vector<VariantBase>& children); 376 377 /** Create a tuple variant with a single variant child. 378 * @param child The child variant. 379 * @return The newly created tuple variant (as a VariantContainerBase). 380 */ 381 static VariantContainerBase create_tuple(const VariantBase& child); 382 383 _WRAP_METHOD_DOCS_ONLY(g_variant_new_maybe) 384 static VariantContainerBase create_maybe(const VariantType& child_type, 385 const VariantBase& child = VariantBase()); 386 387 _WRAP_METHOD(gsize get_n_children() const, g_variant_n_children) 388 389 /** Reads a child item out of this instance. This method is valid for 390 * variants, maybes, arrays, tuples and dictionary entries. 391 * 392 * It is an error if @a index is greater than the number of child items in 393 * the container. See get_n_children(). 394 * 395 * This function is O(1). 396 * 397 * @param index The index of the child to fetch. 398 * @param child A location in which to store the child at the specified 399 * index. 400 * @throw std::out_of_range 401 * @newin{2,28} 402 */ 403 void get_child(VariantBase& child, gsize index = 0) const; 404 _IGNORE(g_variant_get_child, g_variant_get_child_value) 405 406#m4 _CONVERSION(`GVariant*',`VariantBase',`Glib::wrap($3)') 407 408 _WRAP_METHOD(VariantBase get_child(gsize index = 0), g_variant_get_child_value) 409 410 /* TODO?: 411 /// A get() method to return the contents of the variant in the container. 412 template <class DataType> 413 DataType get_child(gsize index = 0) const; 414 */ 415 416 /** If this is a maybe-typed instance, try to extract its value. If there is 417 * no value (the value is <tt>nothing</tt>), return <tt>false</tt>. Otherwise, 418 * the value is copied to the supplied Variant and <tt>true</tt> is returned. 419 * 420 * @param maybe A place in which to return the value, if it isn’t 421 * <tt>nothing</tt>. 422 * @newin{2,28} 423 */ 424 bool get_maybe(VariantBase& maybe) const; 425 _IGNORE(g_variant_get_maybe) 426 427protected: 428#ifndef DOXYGEN_SHOULD_SKIP_THIS 429 /** Used by get_iter() in the subclasses. 430 * @newin{2,46} 431 */ 432 VariantIter get_iter(const VariantType& container_variant_type) const; 433#endif //DOXYGEN_SHOULD_SKIP_THIS 434}; 435 436template<> 437GLIBMM_API VariantContainerBase VariantBase::cast_dynamic<VariantContainerBase>(const VariantBase& v); 438 439/** Template class used for the specialization of the Variant<> classes. 440 * @newin{2,28} 441 * @ingroup Variant 442 */ 443template<class T> 444class Variant : public VariantBase 445{ 446public: 447 using CppType = T; 448}; 449 450/****************** Specializations ***********************************/ 451 452/** Specialization of Variant containing a VariantBase. 453 * Perhaps the main use of this is as a maybe-typed (i.e. nullable) Variant, as 454 * it inherits the methods create_maybe() and get_maybe() from 455 * VariantContainerBase, plus get_n_children() to allow checking whether there 456 * is a contained value, i.e. the inner Variant is not <tt>nothing</tt>. 457 * 458 * @newin{2,28} 459 * @ingroup Variant 460 */ 461template<> 462class GLIBMM_API Variant<VariantBase> : public VariantContainerBase 463{ 464 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 465 _CLASS_GENERIC(Variant<VariantBase>, GVariant) 466 467public: 468 using CType = GVariant*; 469 using CppType = VariantBase; 470 using CppContainerType = Variant<VariantBase>; 471 472 /// Default constructor. 473 Variant<VariantBase>(); 474 475 /** GVariant constructor. 476 * @param castitem The GVariant to wrap. 477 * @param take_a_reference Whether to take an extra reference of the 478 * GVariant or not (not taking one could destroy the GVariant with the 479 * wrapper). 480 */ 481 explicit Variant<VariantBase>(GVariant* castitem, bool take_a_reference = false); 482 483 /** Gets the VariantType. 484 * @return The VariantType. 485 * @newin{2,28} 486 */ 487 static const VariantType& variant_type() G_GNUC_CONST; 488 489 //This must have a create() method because otherwise it would be a copy 490 //constructor. 491 /** Creates a new Variant<VariantBase>. 492 * @param data The value of the new Variant. 493 * @return The new Variant. 494 * @newin{2,28} 495 */ 496 static Variant<VariantBase> create(const VariantBase& data); 497 _IGNORE(g_variant_new_variant) 498 499 //TODO: Documentation 500 void get(VariantBase& variant) const; 501 502 //TODO: Deprecate this in favour of get(VariantBase&)? 503 _WRAP_METHOD(VariantBase get() const, g_variant_get_variant) 504}; 505 506/** Specialization of Variant containing a Variant<T>. 507 * Perhaps the main use of this is as a maybe-typed (i.e. nullable) Variant, as 508 * it inherits the methods create_maybe() and get_maybe() from 509 * VariantContainerBase, plus get_n_children() to allow checking whether there 510 * is a contained value, i.e. the inner Variant is not <tt>nothing</tt>. 511 * 512 * @newin{2,36} 513 * @ingroup Variant 514 */ 515template<class T> 516class Variant< Variant<T> > : public VariantContainerBase 517{ 518public: 519 using CType = GVariant*; 520 using CppType = Variant<T>; 521 using CppContainerType = Variant<CppType>; 522 523 /// Default constructor. 524 Variant< Variant<T> >(); 525 526 /** GVariant constructor. 527 * @param castitem The GVariant to wrap. 528 * @param take_a_reference Whether to take an extra reference of the 529 * GVariant or not (not taking one could destroy the GVariant with the 530 * wrapper). 531 * @newin{2,36} 532 */ 533 explicit Variant< Variant<T> >(GVariant* castitem, bool take_a_reference = false); 534 535 /** Gets the VariantType. 536 * @return The VariantType. 537 * @newin{2,36} 538 */ 539 static const VariantType& variant_type() G_GNUC_CONST; 540 541 /** Creates a new Variant< Variant<T> >. 542 * @param data The value of the new Variant. 543 * @return The new Variant. 544 * @newin{2,36} 545 */ 546 static Variant< Variant<T> > create(const Variant<T>& data); 547 548 /** Gets the contents of the Variant. 549 * @return The contents of the Variant. 550 * @newin{2,36} 551 */ 552 Variant<T> get() const; 553}; 554 555/** Specialization of Variant containing a Glib::ustring, for variants of type 556 * string, object path, or signature. 557 * @newin{2,28} 558 * @ingroup Variant 559 */ 560template<> 561class GLIBMM_API Variant<Glib::ustring> : public VariantStringBase 562{ 563 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 564 _CLASS_GENERIC(Variant<Glib::ustring>, GVariant) 565public: 566 using CType = char*; 567 using CppType = Glib::ustring; 568 569 /// Default constructor. 570 Variant<Glib::ustring>(); 571 572 /** GVariant constructor. 573 * @param castitem The GVariant to wrap. 574 * @param take_a_reference Whether to take an extra reference of the 575 * GVariant or not (not taking one could destroy the GVariant with the 576 * wrapper). 577 */ 578 explicit Variant<Glib::ustring>(GVariant* castitem, bool take_a_reference = false); 579 580 /** Gets the VariantType. 581 * @return The VariantType. 582 * @newin{2,28} 583 */ 584 static const VariantType& variant_type() G_GNUC_CONST; 585 586 /** Creates a new Variant<Glib::ustring>. 587 * @param data The value of the new Variant. 588 * @return The new Variant. 589 * @newin{2,28} 590 */ 591 static Variant<Glib::ustring> create(const Glib::ustring& data); 592 593 //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter. 594 /** Gets the contents of the Variant. 595 * @return The contents of the Variant. 596 * @newin{2,28} 597 */ 598 Glib::ustring get() const; 599 _IGNORE(g_variant_get_string, g_variant_dup_string) 600}; 601 602//TODO: When we can break ABI, remove this template specialization. 603template<> 604GLIBMM_API Variant<Glib::ustring> VariantBase::cast_dynamic< Variant<Glib::ustring> >(const VariantBase& v); 605 606/** Specialization of Variant containing a Glib::DBusObjectPathString, 607 * for variants of type object path. 608 * @newin{2,54} 609 * @ingroup Variant 610 */ 611template<> 612class GLIBMM_API Variant<Glib::DBusObjectPathString> : public VariantStringBase 613{ 614 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 615 _CLASS_GENERIC(Variant<Glib::DBusObjectPathString>, GVariant) 616public: 617 using CType = char*; 618 using CppType = Glib::DBusObjectPathString; 619 620 /// Default constructor. 621 Variant(); 622 623 /** GVariant constructor. 624 * @param castitem The GVariant to wrap. 625 * @param take_a_reference Whether to take an extra reference of the 626 * GVariant or not (not taking one could destroy the GVariant with the 627 * wrapper). 628 */ 629 explicit Variant(GVariant* castitem, bool take_a_reference = false); 630 631 /** Gets the VariantType. 632 * @return The VariantType. 633 * @newin{2,54} 634 */ 635 static const VariantType& variant_type() G_GNUC_CONST; 636 637 /** Creates a new Variant<Glib::DBusObjectPathString>. 638 * @param data The value of the new Variant. 639 * @return The new Variant. 640 * @newin{2,54} 641 */ 642 static Variant<CppType> create(const CppType& data); 643 644 //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter. 645 /** Gets the contents of the Variant. 646 * @return The contents of the Variant. 647 * @newin{2,54} 648 */ 649 CppType get() const; 650}; 651 652/** Specialization of Variant containing a Glib::DBusSignatureString, 653 * for variants of type signature. 654 * @newin{2,54} 655 * @ingroup Variant 656 */ 657template<> 658class GLIBMM_API Variant<Glib::DBusSignatureString> : public VariantStringBase 659{ 660 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 661 _CLASS_GENERIC(Variant<Glib::DBusSignatureString>, GVariant) 662public: 663 using CType = char*; 664 using CppType = Glib::DBusSignatureString; 665 666 /// Default constructor. 667 Variant(); 668 669 /** GVariant constructor. 670 * @param castitem The GVariant to wrap. 671 * @param take_a_reference Whether to take an extra reference of the 672 * GVariant or not (not taking one could destroy the GVariant with the 673 * wrapper). 674 */ 675 explicit Variant(GVariant* castitem, bool take_a_reference = false); 676 677 /** Gets the VariantType. 678 * @return The VariantType. 679 * @newin{2,54} 680 */ 681 static const VariantType& variant_type() G_GNUC_CONST; 682 683 /** Creates a new Variant<Glib::DBusSignatureString>. 684 * @param data The value of the new Variant. 685 * @return The new Variant. 686 * @newin{2,54} 687 */ 688 static Variant<CppType> create(const CppType& data); 689 690 //We can't use WRAP_METHOD() here because g_variant_get_string() takes an extra length parameter. 691 /** Gets the contents of the Variant. 692 * @return The contents of the Variant. 693 * @newin{2,54} 694 */ 695 CppType get() const; 696}; 697 698/** Specialization of Variant containing a std::string, for variants of type 699 * bytestring, string, object path, or signature. 700 * See also Variant<Glib::ustring> for UTF-8 strings. 701 * @newin{2,28} 702 * @ingroup Variant 703 */ 704template<> 705class GLIBMM_API Variant<std::string> : public VariantStringBase 706{ 707 // Trick gmmproc into thinking this is derived from GVariant to wrap some methods. 708 _CLASS_GENERIC(Variant<std::string>, GVariant) 709public: 710 using CType = char* ; 711 using CppType = std::string; 712 713 /// Default constructor. 714 Variant<std::string>(); 715 716 /** GVariant constructor. 717 * @param castitem The GVariant to wrap. 718 * @param take_a_reference Whether to take an extra reference of the 719 * GVariant or not (not taking one could destroy the GVariant with the 720 * wrapper). 721 */ 722 explicit Variant<std::string>(GVariant* castitem, bool take_a_reference = false); 723 724 /** Gets the VariantType. 725 * @return The VariantType. 726 * @newin{2,28} 727 */ 728 static const VariantType& variant_type() G_GNUC_CONST; 729 730 /** Creates a new Variant<std::string>. 731 * @param data The value of the new Variant. 732 * @return The new Variant. 733 * @newin{2,28} 734 */ 735 static Variant<std::string> create(const std::string& data); 736 737 //TODO: Documentation. 738 std::string get() const; 739 _IGNORE(g_variant_get_bytestring, g_variant_dup_bytestring) 740}; 741 742//TODO: When we can break ABI, remove this template specialization. 743template<> 744GLIBMM_API Variant<std::string> VariantBase::cast_dynamic< Variant<std::string> >(const VariantBase& v); 745 746/** Specialization of Variant containing a dictionary entry. See also 747 * Variant< std::map<K, V> >. 748 * @newin{2,28} 749 * @ingroup Variant 750 */ 751template<class K, class V> 752class Variant< std::pair<K, V> > : public VariantContainerBase 753{ 754public: 755 using CppType = std::pair<K, V>; 756 using CppContainerType = Variant<CppType>; 757 758 /// Default constructor. 759 Variant< std::pair<K, V> >() 760 : VariantContainerBase() 761 {} 762 763 /** GVariant constructor. 764 * @param castitem The GVariant to wrap. 765 * @param take_a_reference Whether to take an extra reference of the 766 * GVariant or not (not taking one could destroy the GVariant with the 767 * wrapper). 768 */ 769 explicit Variant< std::pair<K, V> >(GVariant* castitem, 770 bool take_a_reference = false) 771 : VariantContainerBase(castitem, take_a_reference) 772 {} 773 774 /** Gets the VariantType. 775 * @return The VariantType. 776 * @newin{2,28} 777 */ 778 static const VariantType& variant_type() G_GNUC_CONST; 779 780 /** Creates a new Variant< std::pair<K, V> >. 781 * @param data The value of the new Variant. 782 * @return The new Variant. 783 * @newin{2,28} 784 */ 785 static Variant< std::pair<K, V> > create(const std::pair<K, V>& data); 786 _IGNORE(g_variant_new_dict_entry) 787 788 /** Gets the contents of the Variant. 789 * @return The contents of the Variant. 790 * @throw std::out_of_range 791 * @newin{2,28} 792 */ 793 std::pair<K, V> get() const; 794}; 795 796/** Specialization of Variant containing an array of items. 797 * @newin{2,28} 798 * @ingroup Variant 799 */ 800template<class T> 801class Variant< std::vector<T> > : public VariantContainerBase 802{ 803public: 804 using CppType = T ; 805 using CppContainerType = std::vector<T>; 806 807 /// Default constructor. 808 Variant< std::vector<T> >() 809 : VariantContainerBase() 810 {} 811 812 /** GVariant constructor. 813 * @param castitem The GVariant to wrap. 814 * @param take_a_reference Whether to take an extra reference of the 815 * GVariant or not (not taking one could destroy the GVariant with the 816 * wrapper). 817 */ 818 explicit Variant< std::vector<T> >(GVariant* castitem, 819 bool take_a_reference = false) 820 : VariantContainerBase(castitem, take_a_reference) 821 {} 822 823 /** Gets the VariantType. 824 * @return The VariantType. 825 * @newin{2,28} 826 */ 827 static const VariantType& variant_type() G_GNUC_CONST; 828 829 /** Creates a new Variant from an array of numeric types. 830 * @param data The array to use for creation. 831 * @return The new Variant. 832 * @newin{2,28} 833 */ 834 static Variant< std::vector<T> > create(const std::vector<T>& data); 835 _IGNORE(g_variant_new_array) 836 837 /** Gets a specific element of the array. It is an error if @a index is 838 * greater than the number of child items in the container. See 839 * VariantContainerBase::get_n_children(). 840 * 841 * This function is O(1). 842 * 843 * @param index The index of the element. 844 * @return The element at index @a index. 845 * @throw std::out_of_range 846 * @newin{2,28} 847 */ 848 T get_child(gsize index) const; 849 850 /** Gets the vector of the Variant. 851 * @return The vector. 852 * @newin{2,28} 853 */ 854 std::vector<T> get() const; 855 _IGNORE(g_variant_get_fixed_array) 856 857 /** Gets a VariantIter of the Variant. 858 * @return the VariantIter. 859 * @newin{2,28} 860 */ 861 VariantIter get_iter() const; 862}; 863 864/** Specialization of Variant containing an array of UTF-8 capable 865 * strings. 866 * @newin{2,28} 867 * @ingroup Variant 868 */ 869template<> 870class GLIBMM_API Variant< std::vector<Glib::ustring> > : public VariantContainerBase 871{ 872public: 873 using CppType = Glib::ustring ; 874 using CppContainerType = std::vector<Glib::ustring>; 875 876 /// Default constructor. 877 Variant< std::vector<Glib::ustring> >(); 878 879 /** GVariant constructor. 880 * @param castitem The GVariant to wrap. 881 * @param take_a_reference Whether to take an extra reference of the 882 * GVariant or not (not taking one could destroy the GVariant with the 883 * wrapper). 884 */ 885 explicit Variant< std::vector<Glib::ustring> >(GVariant* castitem, bool take_a_reference = false); 886 887 /** Gets the VariantType. 888 * @return The VariantType. 889 * @newin{2,28} 890 */ 891 static const VariantType& variant_type() G_GNUC_CONST; 892 893 /** Creates a new Variant from an array of strings. 894 * @param data The array to use for creation. 895 * @return The new Variant. 896 * @newin{2,28} 897 */ 898 static Variant< std::vector<Glib::ustring> > 899 create(const std::vector<Glib::ustring>& data); 900 901 /** Gets a specific element of the string array. It is an error if @a index 902 * is greater than the number of child items in the container. See 903 * VariantContainerBase::get_n_children(). 904 * 905 * This function is O(1). 906 * 907 * @param index The index of the element. 908 * @return The element at index @a index. 909 * @throw std::out_of_range 910 * @newin{2,28} 911 */ 912 Glib::ustring get_child(gsize index) const; 913 914 /** Gets the string vector of the Variant. 915 * @return The vector. 916 * @newin{2,28} 917 */ 918 std::vector<Glib::ustring> get() const; 919 _IGNORE(g_variant_get_strv, g_variant_dup_strv) 920 921 /** Gets a VariantIter of the Variant. 922 * @return the VariantIter. 923 * @newin{2,28} 924 */ 925 VariantIter get_iter() const; 926}; 927 928/** Specialization of Variant containing an array of D-Bus object paths. 929 * 930 * @newin{2,54} 931 * @ingroup Variant 932 */ 933template<> 934class GLIBMM_API Variant<std::vector<Glib::DBusObjectPathString>> : public VariantContainerBase 935{ 936public: 937 using CppType = Glib::DBusObjectPathString; 938 using CppContainerType = std::vector<Glib::DBusObjectPathString>; 939 940 /// Default constructor. 941 Variant(); 942 943 /** GVariant constructor. 944 * @param castitem The GVariant to wrap. 945 * @param take_a_reference Whether to take an extra reference of the 946 * GVariant or not (not taking one could destroy the GVariant with the 947 * wrapper). 948 */ 949 explicit Variant(GVariant* castitem, bool take_a_reference = false); 950 951 /** Gets the VariantType. 952 * @return The VariantType. 953 * @newin{2,54} 954 */ 955 static const VariantType& variant_type() G_GNUC_CONST; 956 957 /** Creates a new Variant from an array of strings. 958 * @param data The array to use for creation. 959 * @return The new Variant. 960 * @newin{2,54} 961 */ 962 static Variant<CppContainerType> create(const CppContainerType& data); 963 964 /** Gets a specific element of the string array. It is an error if @a index 965 * is greater than the number of child items in the container. See 966 * VariantContainerBase::get_n_children(). 967 * 968 * This function is O(1). 969 * 970 * @param index The index of the element. 971 * @return The element at index @a index. 972 * @throw std::out_of_range 973 * @newin{2,54} 974 */ 975 CppType get_child(gsize index) const; 976 977 /** Gets the string vector of the Variant. 978 * @return The vector. 979 * @newin{2,54} 980 */ 981 CppContainerType get() const; 982 983 /** Gets a VariantIter of the Variant. 984 * @return the VariantIter. 985 * @newin{2,54} 986 */ 987 VariantIter get_iter() const; 988}; 989 990/** Specialization of Variant containing an array of non-UTF-8 strings 991 * (byte string arrays). 992 * @newin{2,28} 993 * @ingroup Variant 994 */ 995template<> 996class GLIBMM_API Variant< std::vector<std::string> > : public VariantContainerBase 997{ 998public: 999 using CppType = std::string ; 1000 using CppContainerType = std::vector<std::string>; 1001 1002 /// Default constructor. 1003 Variant< std::vector<std::string> >(); 1004 1005 /** GVariant constructor. 1006 * @param castitem The GVariant to wrap. 1007 * @param take_a_reference Whether to take an extra reference of the 1008 * GVariant or not (not taking one could destroy the GVariant with the 1009 * wrapper). 1010 */ 1011 explicit Variant< std::vector<std::string> >(GVariant* castitem, bool take_a_reference = false); 1012 1013 /** Gets the VariantType. 1014 * @return The VariantType. 1015 * @newin{2,28} 1016 */ 1017 static const VariantType& variant_type() G_GNUC_CONST; 1018 1019 /** Creates a new Variant from an array of strings. 1020 * @param data The array to use for creation. 1021 * @return The new Variant. 1022 * @newin{2,28} 1023 */ 1024 static Variant< std::vector<std::string> > 1025 create(const std::vector<std::string>& data); 1026 1027 /** Creates a new Variant from an array of D-Bus object paths. 1028 * @param paths The array to use for creation. 1029 * @return The new Variant. 1030 * @newin{2,36} 1031 */ 1032 static Variant< std::vector<std::string> > 1033 create_from_object_paths(const std::vector<std::string>& paths); 1034 1035 /** Gets a specific element of the string array. It is an error if @a index 1036 * is greater than the number of child items in the container. See 1037 * VariantContainerBase::get_n_children(). 1038 * 1039 * This function is O(1). 1040 * 1041 * @param index The index of the element. 1042 * @return The element at index @a index. 1043 * @throw std::out_of_range 1044 * @newin{2,28} 1045 */ 1046 std::string get_child(gsize index) const; 1047 1048 /** Gets the string vector of the Variant. 1049 * @return The vector. 1050 * @newin{2,28} 1051 */ 1052 std::vector<std::string> get() const; 1053 _IGNORE(g_variant_get_bytestring_array, g_variant_dup_bytestring_array) 1054 1055 // Object paths are merely strings so it is possible to get them already with 1056 // the existing get() methods in this class. 1057 _IGNORE(g_variant_get_objv, g_variant_dup_objv) 1058 1059 /** Gets a VariantIter of the Variant. 1060 * @return the VariantIter. 1061 * @newin{2,28} 1062 */ 1063 VariantIter get_iter() const; 1064}; 1065 1066/** Specialization of Variant containing a dictionary (a map of (key, 1067 * value) elements). 1068 * @newin{2,28} 1069 * @ingroup Variant 1070 */ 1071template<class K, class V> 1072class Variant< std::map<K, V> >: public VariantContainerBase 1073{ 1074public: 1075 using CppType = std::pair<K, V>; 1076 using CppContainerType = std::map<K, V>; 1077 1078 /// Default constructor. 1079 Variant< std::map<K, V> >() 1080 : VariantContainerBase() 1081 {} 1082 1083 /** GVariant constructor. 1084 * @param castitem The GVariant to wrap. 1085 * @param take_a_reference Whether to take an extra reference of the 1086 * GVariant or not (not taking one could destroy the GVariant with the 1087 * wrapper). 1088 */ 1089 explicit Variant< std::map<K, V> >(GVariant* castitem, 1090 bool take_a_reference = false) 1091 : VariantContainerBase(castitem, take_a_reference) 1092 {} 1093 1094 /** Gets the VariantType. 1095 * @return The VariantType. 1096 * @newin{2,28} 1097 */ 1098 static const VariantType& variant_type() G_GNUC_CONST; 1099 1100 /** Creates a new Variant containing a dictionary from a map. 1101 * @param data The map to use for creation. 1102 * @return The new Variant holding a dictionary. 1103 * @newin{2,28} 1104 */ 1105 static Variant< std::map<K, V> > create(const std::map<K, V>& data); 1106 1107 /** Gets a specific dictionary entry from the string array. It is an error 1108 * if @a index is greater than the number of child items in the container. 1109 * See VariantContainerBase::get_n_children(). 1110 * 1111 * This function is O(1). 1112 * 1113 * @param index The index of the element. 1114 * @return The dictionary entry at index @a index. 1115 * @throw std::out_of_range 1116 * @newin{2,28} 1117 */ 1118 std::pair<K, V> get_child(gsize index) const; 1119 1120 /** Looks up a value in a dictionary Variant. 1121 * @param key The key to look up. 1122 * @param value A location in which to store the value if found. 1123 * @return <tt>true</tt> if the key is found, <tt>false</tt> otherwise. 1124 */ 1125 bool lookup(const K& key, V& value) const; 1126 _IGNORE(g_variant_lookup_value, g_variant_lookup) 1127 1128 /** Gets the map (the dictionary) of the Variant. 1129 * @return The vector. 1130 * @newin{2,28} 1131 */ 1132 std::map<K, V> get() const; 1133 1134 /** Gets a VariantIter of the Variant. 1135 * @return the VariantIter. 1136 * @newin{2,28} 1137 */ 1138 VariantIter get_iter() const; 1139}; 1140 1141/** Specialization of Variant containing a tuple. 1142 * @newin{2,54} 1143 * @ingroup Variant 1144 */ 1145template <class... Types> 1146class Variant<std::tuple<Types...>> : public VariantContainerBase 1147{ 1148public: 1149 using CppContainerType = std::tuple<Types...>; 1150 1151 /// Default constructor 1152 Variant<std::tuple<Types...>>() 1153 : VariantContainerBase() 1154 {} 1155 1156 /** GVariant constructor. 1157 * @param castitem The GVariant to wrap. 1158 * @param take_a_reference Whether to take an extra reference of the GVariant 1159 * or not (not taking one could destroy the GVariant with the wrapper). 1160 */ 1161 explicit Variant<std::tuple<Types...>>(GVariant* castitem, bool take_a_reference = false) 1162 : VariantContainerBase(castitem, take_a_reference) 1163 {} 1164 1165 /** Creates a new Variant containing a tuple. 1166 * @param data The tuple to use for creation. 1167 * @return The new Variant holding a tuple. 1168 * @newin{2,54} 1169 */ 1170 static Variant<std::tuple<Types...>> create(const std::tuple<Types...>& data); 1171 1172 /** Gets the VariantType. 1173 * @return The VariantType. 1174 * @newin{2,54} 1175 */ 1176 static const VariantType& variant_type() G_GNUC_CONST; 1177 1178 /** Gets a specific element from the tuple. 1179 * It is an error if @a index is greater than or equal to the number of 1180 * elements in the tuple. See VariantContainerBase::get_n_children(). 1181 * 1182 * @param index The index of the element. 1183 * @return The tuple element at index @a index. 1184 * @throw std::out_of_range 1185 * @newin{2,54} 1186 */ 1187 template<class T> 1188 T get_child(gsize index) const; 1189 1190 template<class T> 1191 Variant<T> get_child_variant(gsize index) const; 1192 1193 /** Gets the tuple of the Variant. 1194 * @return The tuple. 1195 * @newin{2,54} 1196 */ 1197 std::tuple<Types...> get() const; 1198 1199 /** Gets a VariantIter of the Variant. 1200 * @return The VariantIter. 1201 * @newin{2,54} 1202 */ 1203 VariantIter get_iter() const; 1204}; 1205 1206} // namespace Glib 1207 1208 1209//We ignore g_variant_get_*() methods that are wrapped by Variant<> specializations, such as in variant_basictypes.h.m4. 1210_IGNORE( 1211 g_variant_get_boolean, 1212 g_variant_get_byte, 1213 g_variant_get_int16, 1214 g_variant_get_uint16, 1215 g_variant_get_int32, 1216 g_variant_get_handle, 1217 g_variant_get_uint32, 1218 g_variant_get_int64, 1219 g_variant_get_uint64, 1220 g_variant_get_double, 1221 g_variant_iter_new 1222) 1223 1224/* Include generated specializations of Variant<> for fundamental types: 1225 */ 1226#define _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H 1227#include <glibmm/variant_basictypes.h> 1228#undef _GLIBMM_VARIANT_H_INCLUDE_VARIANT_BASICTYPES_H 1229 1230namespace Glib 1231{ 1232 1233/*--------------------Variant< Variant<T> >---------------------*/ 1234 1235template<class T> 1236Variant< Variant<T> >::Variant() 1237: VariantContainerBase() 1238{ 1239} 1240 1241template<class T> 1242Variant< Variant<T> >::Variant(GVariant* castitem, bool take_a_reference) 1243: VariantContainerBase(castitem, take_a_reference) 1244{ 1245} 1246 1247// static 1248template<class T> 1249const VariantType& Variant< Variant<T> >::variant_type() 1250{ 1251 return VARIANT_TYPE_VARIANT; 1252} 1253 1254template<class T> 1255Variant< Variant<T> > Variant< Variant<T> >::create(const Variant<T>& data) 1256{ 1257 Variant< Variant<T> > result = Variant< Variant<T> >( 1258 g_variant_new_variant(const_cast<GVariant*>(data.gobj()))); 1259 return result; 1260} 1261 1262template<class T> 1263Variant<T> Variant< Variant<T> >::get() const 1264{ 1265 GVariant* const gvariant = g_variant_get_variant(gobject_); 1266 return Variant<T>(gvariant); 1267} 1268 1269/*--------------------Variant< std::pair<K, V> >---------------------*/ 1270 1271// static 1272template<class K, class V> 1273const VariantType& Variant< std::pair<K, V> >::variant_type() 1274{ 1275 static VariantType type( 1276 g_variant_type_new_dict_entry(Variant<K>::variant_type().gobj(), 1277 Variant<V>::variant_type().gobj())); 1278 1279 return type; 1280} 1281 1282template<class K, class V> 1283Variant< std::pair<K, V> > 1284Variant< std::pair<K, V> >::create(const std::pair<K, V>& data) 1285{ 1286 Variant<K> key = Variant<K>::create(data.first); 1287 Variant<V> value = Variant<V>::create(data.second); 1288 1289 Variant< std::pair<K, V> > result = Variant< std::pair<K, V> >( 1290 g_variant_new_dict_entry(key.gobj(), value.gobj())); 1291 1292 return result; 1293} 1294 1295template<class K, class V> 1296std::pair<K, V> Variant< std::pair<K, V> >::get() const 1297{ 1298 // Get the key (the first element of this VariantContainerBase). 1299 Variant<K> key; 1300 VariantContainerBase::get_child(key, 0); 1301 1302 // Get the value (the second element of this VariantContainerBase). 1303 Variant<V> value; 1304 VariantContainerBase::get_child(value, 1); 1305 1306 std::pair<K, V> result(key.get(), value.get()); 1307 1308 return result; 1309} 1310 1311/*---------------------Variant< std::vector<T> >---------------------*/ 1312 1313// static 1314template<class T> 1315const VariantType& Variant< std::vector<T> >::variant_type() 1316{ 1317 static VariantType type = 1318 VariantType::create_array(Variant<T>::variant_type()); 1319 1320 return type; 1321} 1322 1323template<class T> 1324Variant< std::vector<T> > 1325Variant< std::vector<T> >::create(const std::vector<T>& data) 1326{ 1327 // Get the variant type of the array. 1328 VariantType array_variant_type = Variant< std::vector<T> >::variant_type(); 1329 1330 // Create a GVariantBuilder to build the array. 1331 GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj()); 1332 1333 // Add the elements of the vector into the builder. 1334 for(const auto& element : data) 1335 { 1336 Glib::Variant<T> variant = Glib::Variant<T>::create(element); 1337 g_variant_builder_add_value(builder, variant.gobj()); 1338 } 1339 1340 // Create the variant using the builder. 1341 Variant< std::vector<T> > result = 1342 Variant< std::vector<T> >(g_variant_new( 1343 reinterpret_cast<const gchar*>(array_variant_type.gobj()), builder)); 1344 1345 g_variant_builder_unref(builder); 1346 1347 return result; 1348} 1349 1350template<class T> 1351T Variant< std::vector<T> >::get_child(gsize index) const 1352{ 1353 if (index >= get_n_children()) 1354 throw std::out_of_range( 1355 "Variant< std::vector<T> >::get_child(): Index out of bounds."); 1356 1357 Glib::Variant<T> variant; 1358 1359 GVariant* gvariant = 1360 g_variant_get_child_value(const_cast<GVariant*>(gobj()), index); 1361 1362 variant.init(gvariant); 1363 return variant.get(); 1364} 1365 1366template<class T> 1367std::vector<T> Variant< std::vector<T> >::get() const 1368{ 1369 std::vector<T> result; 1370 1371 for (gsize i = 0, n_children = get_n_children(); i < n_children; ++i) 1372 { 1373 Glib::Variant<T> variant; 1374 1375 GVariant* gvariant = 1376 g_variant_get_child_value(const_cast<GVariant*>(gobj()), i); 1377 1378 variant.init(gvariant); 1379 result.emplace_back(variant.get()); 1380 } 1381 1382 return result; 1383} 1384 1385template<class T> 1386VariantIter Variant< std::vector<T> >::get_iter() const 1387{ 1388 return VariantContainerBase::get_iter(variant_type()); 1389} 1390 1391/*---------------------Variant< std::map<K, V> > --------------------*/ 1392 1393// static 1394template<class K, class V> 1395const VariantType& Variant< std::map<K, V> >::variant_type() 1396{ 1397 static VariantType type = 1398 VariantType::create_array(Variant< std::pair<K, V> >::variant_type()); 1399 1400 return type; 1401} 1402 1403template<class K, class V> 1404Variant< std::map<K, V> > 1405Variant< std::map<K, V> >::create(const std::map<K, V>& data) 1406{ 1407 // Get the variant type of the elements. 1408 VariantType element_variant_type = 1409 Variant< std::pair<K, V> >::variant_type(); 1410 1411 // Get the variant type of the array. 1412 VariantType array_variant_type = Variant< std::map<K, V> >::variant_type(); 1413 1414 // Create a GVariantBuilder to build the array. 1415 GVariantBuilder* builder = g_variant_builder_new(array_variant_type.gobj()); 1416 1417 // Add the elements of the map into the builder. 1418 for(const auto& element : data) 1419 { 1420 auto dict_entry = 1421 Variant< std::pair<K, V> >::create(element); 1422 1423 g_variant_builder_add_value(builder, dict_entry.gobj()); 1424 } 1425 1426 // Create the variant using the builder. 1427 Variant< std::map<K, V> > result = Variant< std::map<K, V> >(g_variant_new( 1428 reinterpret_cast<const gchar*>(array_variant_type.gobj()), builder)); 1429 1430 g_variant_builder_unref(builder); 1431 1432 return result; 1433} 1434 1435template<class K, class V> 1436std::pair<K, V> 1437Variant< std::map<K, V> >::get_child(gsize index) const 1438{ 1439 Variant< std::pair<K, V> > dict_entry; 1440 VariantContainerBase::get_child(dict_entry, index); 1441 return dict_entry.get(); 1442} 1443 1444template<class K, class V> 1445bool Variant< std::map<K, V> >::lookup(const K& key, V& value) const 1446{ 1447 // The code in this method pretty much reflects the g_variant_lookup_value() 1448 // function except that it's more general to deal with keys that are not 1449 // just strings. 1450 VariantIter iter = get_iter(); 1451 1452 Variant< std::pair<K, V> > entry; 1453 1454 while(iter.next_value(entry)) 1455 { 1456 std::pair<K, V> element = entry.get(); 1457 1458 if(element.first == key) 1459 { 1460 value = element.second; 1461 return true; 1462 } 1463 } 1464 1465 return false; 1466} 1467 1468template<class K, class V> 1469std::map<K, V> Variant< std::map<K, V> >::get() const 1470{ 1471 std::map<K, V> result; 1472 VariantIter iter = get_iter(); 1473 Variant< std::pair<K, V> > entry; 1474 1475 while(iter.next_value(entry)) 1476 { 1477 result.insert(entry.get()); 1478 } 1479 1480 return result; 1481} 1482 1483template<class K, class V> 1484VariantIter Variant< std::map<K, V> >::get_iter() const 1485{ 1486 return VariantContainerBase::get_iter(variant_type()); 1487} 1488 1489/*---------------------Variant<std::tuple<class... Types>> --------------------*/ 1490 1491// static 1492template <class... Types> 1493const VariantType& Variant<std::tuple<Types...>>::variant_type() 1494{ 1495 std::vector<VariantType> types; 1496 auto expander = [&types](const VariantType &type) mutable -> int 1497 { 1498 types.push_back(type); 1499 return 0; 1500 }; 1501 1502 // expands the variadic template parameters 1503 using swallow = int[]; // ensures left to right order 1504 (void)swallow{(expander(Variant<Types>::variant_type()))...}; 1505 static auto type = VariantType::create_tuple(types); 1506 1507 return type; 1508} 1509 1510#ifndef DOXYGEN_SHOULD_SKIP_THIS 1511namespace detail 1512{ 1513// std::index_sequence and std::index_sequence_for are new in C++14, 1514// but this version of glibmm requires only C++11. 1515// The following code replaces std::index_sequence and std::index_sequence_for 1516// until we can require C++14 support. 1517// See https://bugzilla.gnome.org/show_bug.cgi?id=787648 1518 1519 /// Class template integer_sequence 1520 template<typename T, T... Idx> 1521 struct integer_sequence 1522 { 1523 typedef T value_type; 1524 static constexpr std::size_t size() { return sizeof...(Idx); } 1525 }; 1526 1527 // Concatenates two integer_sequences. 1528 template<typename Iseq1, typename Iseq2> struct iseq_cat; 1529 1530 template<typename T, std::size_t... Ind1, std::size_t... Ind2> 1531 struct iseq_cat<integer_sequence<T, Ind1...>, integer_sequence<T, Ind2...>> 1532 { 1533 using type = integer_sequence<T, Ind1..., (Ind2 + sizeof...(Ind1))...>; 1534 }; 1535 1536 // Builds an integer_sequence<T, 0, 1, 2, ..., Num-1>. 1537 template<typename T, std::size_t Num> 1538 struct make_intseq 1539 : iseq_cat<typename make_intseq<T, Num / 2>::type, 1540 typename make_intseq<T, Num - Num / 2>::type> 1541 { }; 1542 1543 template<typename T> 1544 struct make_intseq<T, 1> 1545 { 1546 typedef integer_sequence<T, 0> type; 1547 }; 1548 1549 template<typename T> 1550 struct make_intseq<T, 0> 1551 { 1552 typedef integer_sequence<T> type; 1553 }; 1554 1555 /// Alias template make_integer_sequence 1556 template<typename T, T Num> 1557 using make_integer_sequence = typename make_intseq<T, Num>::type; 1558 1559 /// Alias template index_sequence 1560 template<std::size_t... Idx> 1561 using index_sequence = integer_sequence<std::size_t, Idx...>; 1562 1563 /// Alias template make_index_sequence 1564 template<std::size_t Num> 1565 using make_index_sequence = make_integer_sequence<std::size_t, Num>; 1566 1567 /// Alias template index_sequence_for 1568 template<typename... Types> 1569 using index_sequence_for = make_index_sequence<sizeof...(Types)>; 1570 1571// End of code that replaces std::index_sequence and std::index_sequence_for 1572 1573template <class Tuple, std::size_t... Is> 1574void expand_tuple(std::vector<VariantBase> &variants, const Tuple & t, 1575 detail::index_sequence<Is...>) 1576{ 1577 using swallow = int[]; // ensures left to right order 1578 auto expander = [&variants](const VariantBase &variant) -> int 1579 { 1580 variants.push_back(variant); 1581 return 0; 1582 }; 1583 (void)swallow {(expander(Variant<typename std::tuple_element<Is, Tuple>::type>::create(std::get<Is>(t))))...}; 1584} 1585} // namespace detail 1586#endif // DOXYGEN_SHOULD_SKIP_THIS 1587 1588template <class... Types> 1589Variant<std::tuple<Types...>> 1590Variant<std::tuple<Types...>>::create(const std::tuple<Types...>& data) 1591{ 1592 // create a vector containing all tuple values as variants 1593 std::vector<Glib::VariantBase> variants; 1594 detail::expand_tuple(variants, data, detail::index_sequence_for<Types...>{}); 1595 1596 using var_ptr = GVariant*; 1597 std::unique_ptr<var_ptr[]> var_array(new var_ptr[sizeof... (Types)]); 1598 1599 for (std::vector<VariantBase>::size_type i = 0; i < variants.size(); i++) 1600 var_array[i] = const_cast<GVariant*>(variants[i].gobj()); 1601 1602 Variant<std::tuple<Types...>> result = Variant<std::tuple<Types...>>( 1603 g_variant_new_tuple(var_array.get(), variants.size())); 1604 1605 return result; 1606} 1607 1608template <class... Types> 1609template <class T> 1610T Variant<std::tuple<Types...>>::get_child(gsize index) const 1611{ 1612 Variant<T> entry; 1613 VariantContainerBase::get_child(entry, index); 1614 return entry.get(); 1615} 1616 1617template <class... Types> 1618template <class T> 1619Variant<T> Variant<std::tuple<Types...>>::get_child_variant(gsize index) const 1620{ 1621 Variant<T> entry; 1622 VariantContainerBase::get_child(entry, index); 1623 return entry; 1624} 1625 1626#ifndef DOXYGEN_SHOULD_SKIP_THIS 1627namespace detail 1628{ 1629// swallows any argument 1630template <class T> 1631constexpr int any_arg(T&& /* arg */) 1632{ 1633 return 0; 1634} 1635 1636template <class Tuple, std::size_t... Is> 1637void assign_tuple(std::vector<VariantBase> &variants, Tuple & t, detail::index_sequence<Is...>) 1638{ 1639 int i = 0; 1640 using swallow = int[]; // ensures left to right order 1641 (void)swallow {(any_arg(std::get<Is>(t) = VariantBase::cast_dynamic<Variant<typename std::tuple_element<Is, Tuple>::type > >(variants[i++]).get()))...}; 1642} 1643} // namespace detail 1644#endif // DOXYGEN_SHOULD_SKIP_THIS 1645 1646template <class... Types> 1647std::tuple<Types...> Variant<std::tuple<Types...>>::get() const 1648{ 1649 std::tuple<Types...> data; 1650 int i = 0; 1651 1652 std::vector<VariantBase> variants; 1653 using swallow = int[]; // ensures left to right order 1654 auto expander = [&variants, &i](const VariantBase &variant) -> int 1655 { 1656 variants.push_back(variant); 1657 return i++; 1658 }; 1659 (void)swallow{(expander(get_child_variant<Types>(i)))...}; 1660 detail::assign_tuple(variants, data, detail::index_sequence_for<Types...>{}); 1661 1662 return data; 1663} 1664 1665template< class... Types> 1666VariantIter Variant<std::tuple<Types...>>::get_iter() const 1667{ 1668 const auto type = variant_type(); 1669 return VariantContainerBase::get_iter(type); 1670} 1671 1672#ifndef DOXYGEN_SHOULD_SKIP_THIS 1673// This is needed so Glib::VariantBase can be used with 1674// Glib::Value and _WRAP_PROPERTY in Gio::Action and elsewhere. 1675template <> 1676class GLIBMM_API Value<Glib::VariantBase> : public ValueBase_Variant 1677{ 1678public: 1679 using CppType = Glib::VariantBase; 1680 1681 void set(CppType data); 1682 CppType get() const; 1683}; 1684#endif /* DOXYGEN_SHOULD_SKIP_THIS */ 1685 1686} // namespace Glib 1687