The Battle for Wesnoth  1.19.19+dev
variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2025
3  by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
19 
20 #include <map>
21 #include <vector>
22 
23 namespace wfl
24 {
25 class formula_callable;
26 class variant_iterator;
27 
28 class variant
29 {
30 public:
32 
33  variant();
34  explicit variant(int n);
35  variant(int n, DECIMAL_VARIANT_TYPE /*type*/);
36  variant(double n, DECIMAL_VARIANT_TYPE /*type*/);
37  explicit variant(const std::vector<variant>& array);
38  explicit variant(std::vector<variant>&& array);
39  explicit variant(const std::string& str);
40  explicit variant(std::string&& str);
41  explicit variant(const std::map<variant, variant>& map);
42  explicit variant(std::map<variant, variant>&& map);
43  variant(const variant& v) = default;
44  variant(variant&& v) = default;
45 
46  template<typename T>
47  explicit variant(std::shared_ptr<T> callable)
48  : value_(std::make_shared<variant_callable>(callable))
49  {
50  }
51 
52  variant& operator=(const variant& v) = default;
53  variant& operator=(variant&& v) = default;
54 
55  variant operator[](std::size_t n) const;
56  variant operator[](const variant& v) const;
57 
58  std::size_t num_elements() const;
59  bool is_empty() const;
60 
61  variant get_member(const std::string& name) const;
62 
63  /** Functions to test the type of the internal value. */
64  bool is_null() const { return type() == formula_variant::type::null; }
65  bool is_int() const { return type() == formula_variant::type::integer; }
66  bool is_decimal() const { return type() == formula_variant::type::decimal; }
67  bool is_callable() const { return type() == formula_variant::type::object; }
68  bool is_list() const { return type() == formula_variant::type::list; }
69  bool is_string() const { return type() == formula_variant::type::string; }
70  bool is_map() const { return type() == formula_variant::type::map; }
71 
72  /**
73  * Returns the variant's value as an integer.
74  * If @ref is_null() is true, returns @a fallback.
75  */
76  int as_int(int fallback = 0) const;
77 
78  /**
79  * Returns the variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
80  * If @ref is_null() is true, returns @a fallback.
81  */
82  int as_decimal(int fallback = 0) const;
83 
84  /** Returns a boolean state of the variant value. The implementation is type-dependent. */
85  bool as_bool() const;
86 
87  const std::vector<variant>& as_list() const;
88  const std::map<variant, variant>& as_map() const;
89 
90  const std::string& as_string() const;
91 
93  {
94  must_be(formula_variant::type::object);
95  return value_cast<variant_callable>()->get_callable();
96  }
97 
98  template<typename T>
99  std::shared_ptr<T> try_convert() const
100  {
101  if(!is_callable()) {
102  return nullptr;
103  }
104 
105  return std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
106  }
107 
108  template<typename T>
109  std::shared_ptr<T> convert_to() const
110  {
111  std::shared_ptr<T> res = std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
112  if(!res) {
113  throw type_error("could not convert type");
114  }
115 
116  return res;
117  }
118 
119  variant operator+(const variant&) const;
120  variant operator-(const variant&) const;
121  variant operator*(const variant&) const;
122  variant operator/(const variant&) const;
123  variant operator^(const variant&) const;
124  variant operator%(const variant&) const;
125  variant operator-() const;
126 
127  bool operator==(const variant&) const;
128  bool operator!=(const variant&) const;
129  bool operator<(const variant&) const;
130  bool operator>(const variant&) const;
131  bool operator<=(const variant&) const;
132  bool operator>=(const variant&) const;
133 
134  variant list_elements_add(const variant& v) const;
135  variant list_elements_sub(const variant& v) const;
136  variant list_elements_mul(const variant& v) const;
137  variant list_elements_div(const variant& v) const;
138  variant concatenate(const variant& v) const;
139  variant build_range(const variant& v) const;
140 
141  bool contains(const variant& other) const;
142 
143  variant get_keys() const;
144  variant get_values() const;
145 
146  variant_iterator begin() const;
147  variant_iterator end() const;
148 
149  std::string serialize_to_string() const;
150  void serialize_from_string(const std::string& str);
151 
152  std::string string_cast() const;
153 
154  std::string to_debug_string(bool verbose = false, formula_seen_stack* seen = nullptr) const;
155 
156  /** Gets string name of the current value type */
157  std::string type_string() const
158  {
160  }
161 
162  variant execute_variant(const variant& to_exec);
163 
164 private:
165  template<typename T>
166  std::shared_ptr<T> value_cast() const
167  {
168  return wfl::value_cast<T>(value_);
169  }
170 
171  void must_be(formula_variant::type t) const;
172 
173  void must_both_be(formula_variant::type t, const variant& second) const;
174 
176  {
177  return value_->get_type();
178  }
179 
180  /**
181  * Variant value.
182  * Each of the constructors initialized this with the appropriate helper class.
183  */
185 };
186 
187 /**
188  * Iterator class for the variant.
189  *
190  * Depending on the @p type_ the @p list_iterator_ and the @p map_iterator_ are
191  * a valid iterator or singular. Since most actions on singular iterators
192  * result in Undefined Behavior care should be taken when copying the
193  * @p list_iterator_ and @p map_iterator_.
194  */
196 {
197 public:
199  typedef std::bidirectional_iterator_tag iterator_category;
200  typedef variant& reference;
201  typedef variant* pointer;
202  typedef int difference_type;
203 
204  /**
205  * Constructor for a no-op iterator.
206  */
208 
209  /**
210  * Constructor for a generic iterator.
211  *
212  * @pre @p iter is not singular.
213  *
214  * @param value A pointer to a variant value representing the container.
215  * @param iter An underlying iterator for the underlying container.
216  */
217  variant_iterator(const variant_value_base* value, const utils::any& iter);
218 
219  variant operator*() const;
224  bool operator==(const variant_iterator& that) const;
225  bool operator!=(const variant_iterator& that) const;
226 private:
229  utils::any iter_;
230 };
231 
232 }
double t
Definition: astarsearch.cpp:63
Iterator class for the variant.
Definition: variant.hpp:196
bool operator!=(const variant_iterator &that) const
Definition: variant.cpp:134
const variant_value_base * container_
Definition: variant.hpp:228
variant operator*() const
Definition: variant.cpp:74
bool operator==(const variant_iterator &that) const
Definition: variant.cpp:121
variant_iterator & operator--()
Definition: variant.cpp:102
std::bidirectional_iterator_tag iterator_category
Definition: variant.hpp:199
formula_variant::type type_
Definition: variant.hpp:227
variant_iterator()
Constructor for a no-op iterator.
Definition: variant.cpp:60
variant_iterator & operator++()
Definition: variant.cpp:83
Base class for all variant types.
variant execute_variant(const variant &to_exec)
Definition: variant.cpp:691
value_base_ptr value_
Variant value.
Definition: variant.hpp:184
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:99
std::shared_ptr< T > value_cast() const
Definition: variant.hpp:166
variant operator-() const
Definition: variant.cpp:486
bool is_map() const
Definition: variant.hpp:70
bool is_list() const
Definition: variant.hpp:68
variant operator^(const variant &) const
Definition: variant.cpp:470
variant concatenate(const variant &v) const
Definition: variant.cpp:598
variant get_keys() const
Definition: variant.cpp:237
variant_iterator begin() const
Definition: variant.cpp:261
variant & operator=(const variant &v)=default
int as_int(int fallback=0) const
Returns the variant's value as an integer.
Definition: variant.cpp:300
variant operator/(const variant &) const
Definition: variant.cpp:414
variant get_values() const
Definition: variant.cpp:249
void serialize_from_string(const std::string &str)
Definition: variant.cpp:666
int as_decimal(int fallback=0) const
Returns the variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
Definition: variant.cpp:309
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:92
bool operator>=(const variant &) const
Definition: variant.cpp:530
void must_both_be(formula_variant::type t, const variant &second) const
Definition: variant.cpp:651
variant(variant &&v)=default
std::size_t num_elements() const
Definition: variant.cpp:276
variant(std::shared_ptr< T > callable)
Definition: variant.hpp:47
DECIMAL_VARIANT_TYPE
Definition: variant.hpp:31
@ DECIMAL_VARIANT
Definition: variant.hpp:31
formula_variant::type type() const
Definition: variant.hpp:175
variant(const variant &v)=default
bool is_decimal() const
Definition: variant.hpp:66
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:109
bool operator!=(const variant &) const
Definition: variant.cpp:508
variant operator+(const variant &) const
Definition: variant.cpp:345
bool is_empty() const
Definition: variant.cpp:271
bool contains(const variant &other) const
Definition: variant.cpp:631
bool operator==(const variant &) const
Definition: variant.cpp:495
bool operator>(const variant &) const
Definition: variant.cpp:540
variant operator*(const variant &) const
Definition: variant.cpp:391
variant get_member(const std::string &name) const
Definition: variant.cpp:285
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:586
std::string serialize_to_string() const
Definition: variant.cpp:661
variant list_elements_add(const variant &v) const
Definition: variant.cpp:574
const std::string & as_string() const
Definition: variant.cpp:327
std::string string_cast() const
Definition: variant.cpp:676
variant list_elements_div(const variant &v) const
Definition: variant.cpp:592
variant_iterator end() const
Definition: variant.cpp:266
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:322
bool operator<(const variant &) const
Definition: variant.cpp:513
variant & operator=(variant &&v)=default
variant operator[](std::size_t n) const
Definition: variant.cpp:189
bool is_string() const
Definition: variant.hpp:69
variant build_range(const variant &v) const
Definition: variant.cpp:624
std::string type_string() const
Gets string name of the current value type.
Definition: variant.hpp:157
bool is_callable() const
Definition: variant.hpp:67
variant operator%(const variant &) const
Definition: variant.cpp:449
const std::vector< variant > & as_list() const
Definition: variant.cpp:333
bool operator<=(const variant &) const
Definition: variant.cpp:535
void must_be(formula_variant::type t) const
Definition: variant.cpp:644
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:681
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:339
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:64
bool is_int() const
Definition: variant.hpp:65
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:580
Definition: callable.hpp:26
std::shared_ptr< variant_value_base > value_base_ptr
std::vector< const_formula_callable_ptr > formula_seen_stack
std::shared_ptr< const formula_callable > const_formula_callable_ptr
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition: enum_base.hpp:46
static map_location::direction n