The Battle for Wesnoth  1.19.5+dev
variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
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  int as_int() const;
71 
72  /** Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234 */
73  int as_decimal() const;
74 
75  /** Returns a boolean state of the variant value. The implementation is type-dependent. */
76  bool as_bool() const;
77 
78  const std::vector<variant>& as_list() const;
79  const std::map<variant, variant>& as_map() const;
80 
81  const std::string& as_string() const;
82 
84  {
85  must_be(formula_variant::type::object);
86  return value_cast<variant_callable>()->get_callable();
87  }
88 
89  template<typename T>
90  std::shared_ptr<T> try_convert() const
91  {
92  if(!is_callable()) {
93  return nullptr;
94  }
95 
96  return std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
97  }
98 
99  template<typename T>
100  std::shared_ptr<T> convert_to() const
101  {
102  std::shared_ptr<T> res = std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
103  if(!res) {
104  throw type_error("could not convert type");
105  }
106 
107  return res;
108  }
109 
110  variant operator+(const variant&) const;
111  variant operator-(const variant&) const;
112  variant operator*(const variant&) const;
113  variant operator/(const variant&) const;
114  variant operator^(const variant&) const;
115  variant operator%(const variant&) const;
116  variant operator-() const;
117 
118  bool operator==(const variant&) const;
119  bool operator!=(const variant&) const;
120  bool operator<(const variant&) const;
121  bool operator>(const variant&) const;
122  bool operator<=(const variant&) const;
123  bool operator>=(const variant&) const;
124 
125  variant list_elements_add(const variant& v) const;
126  variant list_elements_sub(const variant& v) const;
127  variant list_elements_mul(const variant& v) const;
128  variant list_elements_div(const variant& v) const;
129  variant concatenate(const variant& v) const;
130  variant build_range(const variant& v) const;
131 
132  bool contains(const variant& other) const;
133 
134  variant get_keys() const;
135  variant get_values() const;
136 
137  variant_iterator begin() const;
138  variant_iterator end() const;
139 
140  std::string serialize_to_string() const;
141  void serialize_from_string(const std::string& str);
142 
143  std::string string_cast() const;
144 
145  std::string to_debug_string(bool verbose = false, formula_seen_stack* seen = nullptr) const;
146 
147  /** Gets string name of the current value type */
148  std::string type_string() const
149  {
151  }
152 
153  variant execute_variant(const variant& to_exec);
154 
155 private:
156  template<typename T>
157  std::shared_ptr<T> value_cast() const
158  {
159  return wfl::value_cast<T>(value_);
160  }
161 
162  void must_be(formula_variant::type t) const;
163 
164  void must_both_be(formula_variant::type t, const variant& second) const;
165 
167  {
168  return value_->get_type();
169  }
170 
171  /**
172  * Variant value.
173  * Each of the constructors initialized this with the appropriate helper class.
174  */
176 };
177 
178 /**
179  * Iterator class for the variant.
180  *
181  * Depending on the @p type_ the @p list_iterator_ and the @p map_iterator_ are
182  * a valid iterator or singular. Since most actions on singular iterators
183  * result in Undefined Behavior care should be taken when copying the
184  * @p list_iterator_ and @p map_iterator_.
185  */
187 {
188 public:
190  typedef std::bidirectional_iterator_tag iterator_category;
191  typedef variant& reference;
192  typedef variant* pointer;
193  typedef int difference_type;
194 
195  /**
196  * Constructor for a no-op iterator.
197  */
199 
200  /**
201  * Constructor for a generic iterator.
202  *
203  * @pre @p iter is not singular.
204  *
205  * @param value A pointer to a variant value representing the container.
206  * @param iter An underlying iterator for the underlying container.
207  */
208  variant_iterator(const variant_value_base* value, const utils::any& iter);
209 
210  variant operator*() const;
215  bool operator==(const variant_iterator& that) const;
216  bool operator!=(const variant_iterator& that) const;
217 private:
220  utils::any iter_;
221 };
222 
223 }
double t
Definition: astarsearch.cpp:63
Iterator class for the variant.
Definition: variant.hpp:187
bool operator!=(const variant_iterator &that) const
Definition: variant.cpp:134
const variant_value_base * container_
Definition: variant.hpp:219
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:190
formula_variant::type type_
Definition: variant.hpp:218
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:175
int as_int() const
Definition: variant.cpp:291
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:90
std::shared_ptr< T > value_cast() const
Definition: variant.hpp:157
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
int as_decimal() const
Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234.
Definition: variant.cpp:300
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
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
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:83
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:166
variant(const variant &v)=default
bool is_decimal() const
Definition: variant.hpp:64
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:100
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:148
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