The Battle for Wesnoth  1.15.2+dev
variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
18 
19 #include <map>
20 #include <vector>
21 
22 namespace wfl
23 {
24 class formula_callable;
25 class variant_iterator;
26 
27 class variant
28 {
29 public:
31 
32  variant();
33  explicit variant(int n);
34  variant(int n, DECIMAL_VARIANT_TYPE /*type*/);
35  variant(double n, DECIMAL_VARIANT_TYPE /*type*/);
36  explicit variant(const std::vector<variant>& array);
37  explicit variant(const std::string& str);
38  explicit variant(const std::map<variant, variant>& map);
39  variant(const variant& v) = default;
40  variant(variant&& v) = default;
41 
42  template<typename T>
43  variant(std::shared_ptr<T> callable)
44  : value_(std::make_shared<variant_callable>(callable))
45  {
46  assert(value_.get());
47  }
48 
49  variant& operator=(const variant& v) = default;
50  variant& operator=(variant&& v) = default;
51 
52  variant operator[](std::size_t n) const;
53  variant operator[](const variant& v) const;
54 
55  std::size_t num_elements() const;
56  bool is_empty() const;
57 
58  variant get_member(const std::string& name) const;
59 
60  /** Functions to test the type of the internal value. */
61  bool is_null() const { return type() == VARIANT_TYPE::TYPE_NULL; }
62  bool is_int() const { return type() == VARIANT_TYPE::TYPE_INT; }
63  bool is_decimal() const { return type() == VARIANT_TYPE::TYPE_DECIMAL; }
64  bool is_callable() const { return type() == VARIANT_TYPE::TYPE_CALLABLE; }
65  bool is_list() const { return type() == VARIANT_TYPE::TYPE_LIST; }
66  bool is_string() const { return type() == VARIANT_TYPE::TYPE_STRING; }
67  bool is_map() const { return type() == VARIANT_TYPE::TYPE_MAP; }
68 
69  int as_int() const;
70 
71  /** Returns variant's internal representation of decimal number: ie, 1.234 is represented as 1234 */
72  int as_decimal() const;
73 
74  /** Returns a boolean state of the variant value. The implementation is type-dependent. */
75  bool as_bool() const;
76 
77  const std::vector<variant>& as_list() const;
78  const std::map<variant, variant>& as_map() const;
79 
80  const std::string& as_string() const;
81 
83  {
84  must_be(VARIANT_TYPE::TYPE_CALLABLE);
85  return value_cast<variant_callable>()->get_callable();
86  }
87 
88  template<typename T>
89  std::shared_ptr<T> try_convert() const
90  {
91  if(!is_callable()) {
92  return nullptr;
93  }
94 
95  return std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
96  }
97 
98  template<typename T>
99  std::shared_ptr<T> convert_to() const
100  {
101  std::shared_ptr<T> res = std::dynamic_pointer_cast<T>(std::const_pointer_cast<formula_callable>(as_callable()));
102  if(!res) {
103  throw type_error("could not convert type");
104  }
105 
106  return res;
107  }
108 
109  variant operator+(const variant&) const;
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;
116 
117  bool operator==(const variant&) const;
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 
124  variant list_elements_add(const variant& v) const;
125  variant list_elements_sub(const variant& v) const;
126  variant list_elements_mul(const variant& v) const;
127  variant list_elements_div(const variant& v) const;
128  variant concatenate(const variant& v) const;
129  variant build_range(const variant& v) const;
130 
131  bool contains(const variant& other) const;
132 
133  variant get_keys() const;
134  variant get_values() const;
135 
136  variant_iterator begin() const;
137  variant_iterator end() const;
138 
139  std::string serialize_to_string() const;
140  void serialize_from_string(const std::string& str);
141 
142  std::string string_cast() const;
143 
144  std::string to_debug_string(bool verbose = false, formula_seen_stack* seen = nullptr) const;
145 
146  /** Gets string name of the current value type */
147  std::string type_string() const
148  {
149  return type().to_string();
150  }
151 
152  variant execute_variant(const variant& to_exec);
153 
154 private:
155  template<typename T>
156  std::shared_ptr<T> value_cast() const
157  {
158  return wfl::value_cast<T>(value_);
159  }
160 
161  void must_be(VARIANT_TYPE t) const;
162 
163  void must_both_be(VARIANT_TYPE t, const variant& second) const;
164 
165  VARIANT_TYPE type() const
166  {
167  return value_->get_type();
168  }
169 
170  /**
171  * Variant value.
172  * Each of the constructors initialized this with the appropriate helper class.
173  */
175 };
176 
177 /**
178  * Iterator class for the variant.
179  *
180  * Depending on the @p type_ the @p list_iterator_ and the @p map_iterator_ are
181  * a valid iterator or singular. Since most actions on singular iterators
182  * result in Undefined Behavior care should be taken when copying the
183  * @p list_iterator_ and @p map_iterator_.
184  */
186 {
187 public:
189  typedef std::bidirectional_iterator_tag iterator_category;
190  typedef variant& reference;
191  typedef variant* pointer;
192  typedef int difference_type;
193 
194  /**
195  * Constructor for a no-op iterator.
196  */
198 
199  /**
200  * Constructor for a generic iterator.
201  *
202  * @pre @p iter is not singular.
203  *
204  * @param value A pointer to a variant value representing the container.
205  * @param iter An underlying iterator for the underlying container.
206  */
207  variant_iterator(const variant_value_base* value, const boost::any& iter);
208 
209  variant operator*() const;
210  variant_iterator& operator++();
211  variant_iterator operator++(int);
212  variant_iterator& operator--();
213  variant_iterator operator--(int);
214  bool operator==(const variant_iterator& that) const;
215  bool operator!=(const variant_iterator& that) const;
216 private:
217  VARIANT_TYPE type_;
219  boost::any iter_;
220 };
221 
222 }
variant execute_variant(const variant &to_exec)
Definition: variant.cpp:653
std::string type_string() const
Gets string name of the current value type.
Definition: variant.hpp:147
void must_both_be(VARIANT_TYPE t, const variant &second) const
Definition: variant.cpp:614
bool is_map() const
Definition: variant.hpp:67
std::shared_ptr< variant_value_base > value_base_ptr
int as_int() const
Definition: variant.cpp:292
DECIMAL_VARIANT_TYPE
Definition: variant.hpp:30
value_base_ptr value_
Variant value.
Definition: variant.hpp:174
bool contains(const variant &other) const
Definition: variant.cpp:594
bool is_string() const
Definition: variant.hpp:66
bool is_callable() const
Definition: variant.hpp:64
variant operator-() const
Definition: variant.cpp:478
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:331
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:441
bool is_list() const
Definition: variant.hpp:65
const std::vector< variant > & as_list() const
Definition: variant.cpp:325
bool is_decimal() const
Definition: variant.hpp:63
bool is_int() const
Definition: variant.hpp:62
const std::string & as_string() const
Definition: variant.cpp:319
bool operator<=(const variant &) const
Definition: variant.cpp:527
variant & operator=(const variant &v)=default
int as_decimal() const
Returns variant&#39;s internal representation of decimal number: ie, 1.234 is represented as 1234...
Definition: variant.cpp:301
std::shared_ptr< T > value_cast() const
Definition: variant.hpp:156
variant(std::shared_ptr< T > callable)
Definition: variant.hpp:43
void serialize_from_string(const std::string &str)
Definition: variant.cpp:629
variant list_elements_add(const variant &v) const
Definition: variant.cpp:537
VARIANT_TYPE type_
Definition: variant.hpp:217
bool operator!=(const variant &) const
Definition: variant.cpp:500
std::string serialize_to_string() const
Definition: variant.cpp:624
variant_iterator end() const
Definition: variant.cpp:260
void must_be(VARIANT_TYPE t) const
Definition: variant.cpp:607
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:549
variant operator/(const variant &) const
Definition: variant.cpp:406
variant build_range(const variant &v) const
Definition: variant.cpp:587
std::string string_cast() const
Definition: variant.cpp:638
const_formula_callable_ptr as_callable() const
Definition: variant.hpp:82
variant list_elements_div(const variant &v) const
Definition: variant.cpp:555
VARIANT_TYPE type() const
Definition: variant.hpp:165
std::bidirectional_iterator_tag iterator_category
Definition: variant.hpp:189
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:532
const variant_value_base * container_
Definition: variant.hpp:218
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:61
variant concatenate(const variant &v) const
Definition: variant.cpp:561
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:89
variant operator+(const variant &) const
Definition: variant.cpp:337
double t
Definition: astarsearch.cpp:64
Definition: contexts.hpp:42
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:505
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:185
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:314
static map_location::DIRECTION n
bool operator>=(const variant &) const
Definition: variant.cpp:522
variant operator[](std::size_t n) const
Definition: variant.cpp:183
variant operator^(const variant &) const
Definition: variant.cpp:462
bool is_empty() const
Definition: variant.cpp:265
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:99
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:543
variant operator*(const variant &) const
Definition: variant.cpp:383
bool operator==(const variant &) const
Definition: variant.cpp:487
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:643