The Battle for Wesnoth  1.19.13+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(const std::string& str);
39  explicit variant(const std::map<variant, variant>& map);
40  variant(const variant& v) = default;
41  variant(variant&& v) = default;
42 
43  template<typename T>
44  variant(std::shared_ptr<T> callable)
45  : value_(std::make_shared<variant_callable>(callable))
46  {
47  assert(value_.get());
48  }
49 
50  variant& operator=(const variant& v) = default;
51  variant& operator=(variant&& v) = default;
52 
53  variant operator[](std::size_t n) const;
54  variant operator[](const variant& v) const;
55 
56  std::size_t num_elements() const;
57  bool is_empty() const;
58 
59  variant get_member(const std::string& name) const;
60 
61  /** Functions to test the type of the internal value. */
62  bool is_null() const { return type() == formula_variant::type::null; }
63  bool is_int() const { return type() == formula_variant::type::integer; }
64  bool is_decimal() const { return type() == formula_variant::type::decimal; }
65  bool is_callable() const { return type() == formula_variant::type::object; }
66  bool is_list() const { return type() == formula_variant::type::list; }
67  bool is_string() const { return type() == formula_variant::type::string; }
68  bool is_map() const { return type() == formula_variant::type::map; }
69 
70  /**
71  * Returns the variant's value as an integer.
72  * If @ref is_null() is true, returns @a fallback.
73  */
74  int as_int(int fallback = 0) const;
75 
76  /**
77  * Returns the variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
78  * If @ref is_null() is true, returns @a fallback.
79  */
80  int as_decimal(int fallback = 0) const;
81 
82  /** Returns a boolean state of the variant value. The implementation is type-dependent. */
83  bool as_bool() const;
84 
85  const std::vector<variant>& as_list() const;
86  const std::map<variant, variant>& as_map() const;
87 
88  const std::string& as_string() const;
89 
91  {
92  must_be(formula_variant::type::object);
93  return value_cast<variant_callable>()->get_callable();
94  }
95 
96  template<typename T>
97  std::shared_ptr<T> try_convert() const
98  {
99  if(!is_callable()) {
100  return nullptr;
101  }
102 
103  return std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
104  }
105 
106  template<typename T>
107  std::shared_ptr<T> convert_to() const
108  {
109  std::shared_ptr<T> res = std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
110  if(!res) {
111  throw type_error("could not convert type");
112  }
113 
114  return res;
115  }
116 
117  variant operator+(const variant&) const;
118  variant operator-(const variant&) const;
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;
124 
125  bool operator==(const variant&) const;
126  bool operator!=(const variant&) const;
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 
132  variant list_elements_add(const variant& v) const;
133  variant list_elements_sub(const variant& v) const;
134  variant list_elements_mul(const variant& v) const;
135  variant list_elements_div(const variant& v) const;
136  variant concatenate(const variant& v) const;
137  variant build_range(const variant& v) const;
138 
139  bool contains(const variant& other) const;
140 
141  variant get_keys() const;
142  variant get_values() const;
143 
144  variant_iterator begin() const;
145  variant_iterator end() const;
146 
147  std::string serialize_to_string() const;
148  void serialize_from_string(const std::string& str);
149 
150  std::string string_cast() const;
151 
152  std::string to_debug_string(bool verbose = false, formula_seen_stack* seen = nullptr) const;
153 
154  /** Gets string name of the current value type */
155  std::string type_string() const
156  {
158  }
159 
160  variant execute_variant(const variant& to_exec);
161 
162 private:
163  template<typename T>
164  std::shared_ptr<T> value_cast() const
165  {
166  return wfl::value_cast<T>(value_);
167  }
168 
169  void must_be(formula_variant::type t) const;
170 
171  void must_both_be(formula_variant::type t, const variant& second) const;
172 
174  {
175  return value_->get_type();
176  }
177 
178  /**
179  * Variant value.
180  * Each of the constructors initialized this with the appropriate helper class.
181  */
183 };
184 
185 /**
186  * Iterator class for the variant.
187  *
188  * Depending on the @p type_ the @p list_iterator_ and the @p map_iterator_ are
189  * a valid iterator or singular. Since most actions on singular iterators
190  * result in Undefined Behavior care should be taken when copying the
191  * @p list_iterator_ and @p map_iterator_.
192  */
194 {
195 public:
197  typedef std::bidirectional_iterator_tag iterator_category;
198  typedef variant& reference;
199  typedef variant* pointer;
200  typedef int difference_type;
201 
202  /**
203  * Constructor for a no-op iterator.
204  */
206 
207  /**
208  * Constructor for a generic iterator.
209  *
210  * @pre @p iter is not singular.
211  *
212  * @param value A pointer to a variant value representing the container.
213  * @param iter An underlying iterator for the underlying container.
214  */
215  variant_iterator(const variant_value_base* value, const utils::any& iter);
216 
217  variant operator*() const;
222  bool operator==(const variant_iterator& that) const;
223  bool operator!=(const variant_iterator& that) const;
224 private:
227  utils::any iter_;
228 };
229 
230 }
double t
Definition: astarsearch.cpp:63
Iterator class for the variant.
Definition: variant.hpp:194
bool operator!=(const variant_iterator &that) const
Definition: variant.cpp:134
const variant_value_base * container_
Definition: variant.hpp:226
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:197
formula_variant::type type_
Definition: variant.hpp:225
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:653
value_base_ptr value_
Variant value.
Definition: variant.hpp:182
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:97
std::shared_ptr< T > value_cast() const
Definition: variant.hpp:164
variant operator-() const
Definition: variant.cpp:477
bool is_map() const
Definition: variant.hpp:68
bool is_list() const
Definition: variant.hpp:66
variant operator^(const variant &) const
Definition: variant.cpp:461
variant concatenate(const variant &v) const
Definition: variant.cpp:560
variant get_keys() const
Definition: variant.cpp:228
variant_iterator begin() const
Definition: variant.cpp:252
variant & operator=(const variant &v)=default
int as_int(int fallback=0) const
Returns the variant's value as an integer.
Definition: variant.cpp:291
variant operator/(const variant &) const
Definition: variant.cpp:405
variant get_values() const
Definition: variant.cpp:240
void serialize_from_string(const std::string &str)
Definition: variant.cpp:628
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:300
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:90
bool operator>=(const variant &) const
Definition: variant.cpp:521
void must_both_be(formula_variant::type t, const variant &second) const
Definition: variant.cpp:613
variant(variant &&v)=default
std::size_t num_elements() const
Definition: variant.cpp:267
variant(std::shared_ptr< T > callable)
Definition: variant.hpp:44
DECIMAL_VARIANT_TYPE
Definition: variant.hpp:31
@ DECIMAL_VARIANT
Definition: variant.hpp:31
formula_variant::type type() const
Definition: variant.hpp:173
variant(const variant &v)=default
bool is_decimal() const
Definition: variant.hpp:64
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:107
bool operator!=(const variant &) const
Definition: variant.cpp:499
variant operator+(const variant &) const
Definition: variant.cpp:336
bool is_empty() const
Definition: variant.cpp:262
bool contains(const variant &other) const
Definition: variant.cpp:593
bool operator==(const variant &) const
Definition: variant.cpp:486
bool operator>(const variant &) const
Definition: variant.cpp:531
variant operator*(const variant &) const
Definition: variant.cpp:382
variant get_member(const std::string &name) const
Definition: variant.cpp:276
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:548
std::string serialize_to_string() const
Definition: variant.cpp:623
variant list_elements_add(const variant &v) const
Definition: variant.cpp:536
const std::string & as_string() const
Definition: variant.cpp:318
std::string string_cast() const
Definition: variant.cpp:638
variant list_elements_div(const variant &v) const
Definition: variant.cpp:554
variant_iterator end() const
Definition: variant.cpp:257
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:313
bool operator<(const variant &) const
Definition: variant.cpp:504
variant & operator=(variant &&v)=default
variant operator[](std::size_t n) const
Definition: variant.cpp:180
bool is_string() const
Definition: variant.hpp:67
variant build_range(const variant &v) const
Definition: variant.cpp:586
std::string type_string() const
Gets string name of the current value type.
Definition: variant.hpp:155
bool is_callable() const
Definition: variant.hpp:65
variant operator%(const variant &) const
Definition: variant.cpp:440
const std::vector< variant > & as_list() const
Definition: variant.cpp:324
bool operator<=(const variant &) const
Definition: variant.cpp:526
void must_be(formula_variant::type t) const
Definition: variant.cpp:606
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:643
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:330
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:62
bool is_int() const
Definition: variant.hpp:63
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:542
Definition: contexts.hpp:43
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