The Battle for Wesnoth  1.17.12+dev
variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2022
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;
211  variant_iterator& operator++();
212  variant_iterator operator++(int);
213  variant_iterator& operator--();
214  variant_iterator operator--(int);
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 }
variant execute_variant(const variant &to_exec)
Definition: variant.cpp:656
std::string type_string() const
Gets string name of the current value type.
Definition: variant.hpp:148
bool is_map() const
Definition: variant.hpp:68
std::shared_ptr< variant_value_base > value_base_ptr
int as_int() const
Definition: variant.cpp:294
DECIMAL_VARIANT_TYPE
Definition: variant.hpp:31
value_base_ptr value_
Variant value.
Definition: variant.hpp:175
bool contains(const variant &other) const
Definition: variant.cpp:596
bool is_string() const
Definition: variant.hpp:67
bool is_callable() const
Definition: variant.hpp:65
variant operator-() const
Definition: variant.cpp:480
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:333
STL namespace.
static std::shared_ptr< T > value_cast(value_base_ptr ptr)
Casts a variant_value_base shared pointer to a new derived type.
variant operator%(const variant &) const
Definition: variant.cpp:443
bool is_list() const
Definition: variant.hpp:66
const std::vector< variant > & as_list() const
Definition: variant.cpp:327
bool is_decimal() const
Definition: variant.hpp:64
bool is_int() const
Definition: variant.hpp:63
const std::string & as_string() const
Definition: variant.cpp:321
bool operator<=(const variant &) const
Definition: variant.cpp:529
variant & operator=(const variant &v)=default
formula_variant::type type_
Definition: variant.hpp:218
int as_decimal() const
Returns variant&#39;s internal representation of decimal number: ie, 1.234 is represented as 1234...
Definition: variant.cpp:303
void must_be(formula_variant::type t) const
Definition: variant.cpp:609
std::shared_ptr< T > value_cast() const
Definition: variant.hpp:157
variant(std::shared_ptr< T > callable)
Definition: variant.hpp:44
void serialize_from_string(const std::string &str)
Definition: variant.cpp:631
variant list_elements_add(const variant &v) const
Definition: variant.cpp:539
bool operator!=(const variant &) const
Definition: variant.cpp:502
std::string serialize_to_string() const
Definition: variant.cpp:626
variant_iterator end() const
Definition: variant.cpp:260
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:551
variant operator/(const variant &) const
Definition: variant.cpp:408
variant build_range(const variant &v) const
Definition: variant.cpp:589
std::string string_cast() const
Definition: variant.cpp:641
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:83
variant list_elements_div(const variant &v) const
Definition: variant.cpp:557
std::bidirectional_iterator_tag iterator_category
Definition: variant.hpp:190
std::vector< const_formula_callable_ptr > formula_seen_stack
std::shared_ptr< const formula_callable > const_formula_callable_ptr
bool operator>(const variant &) const
Definition: variant.cpp:534
const variant_value_base * container_
Definition: variant.hpp:219
formula_variant::type type() const
Definition: variant.hpp:166
void must_both_be(formula_variant::type t, const variant &second) const
Definition: variant.cpp:616
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:62
variant concatenate(const variant &v) const
Definition: variant.cpp:563
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:90
variant operator+(const variant &) const
Definition: variant.cpp:339
double t
Definition: astarsearch.cpp:65
Definition: contexts.hpp:44
variant get_keys() const
Definition: variant.cpp:231
variant_iterator begin() const
Definition: variant.cpp:255
variant get_values() const
Definition: variant.cpp:243
bool operator<(const variant &) const
Definition: variant.cpp:507
Base class for all variant types.
std::size_t num_elements() const
Definition: variant.cpp:270
variant get_member(const std::string &name) const
Definition: variant.cpp:279
Iterator class for the variant.
Definition: variant.hpp:186
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:316
static map_location::DIRECTION n
bool operator>=(const variant &) const
Definition: variant.cpp:524
variant operator[](std::size_t n) const
Definition: variant.cpp:183
variant operator^(const variant &) const
Definition: variant.cpp:464
bool is_empty() const
Definition: variant.cpp:265
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:100
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:545
variant operator*(const variant &) const
Definition: variant.cpp:385
bool operator==(const variant &) const
Definition: variant.cpp:489
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:646
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition: enum_base.hpp:46