The Battle for Wesnoth  1.17.0-dev
variant.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
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() == VARIANT_TYPE::TYPE_NULL; }
63  bool is_int() const { return type() == VARIANT_TYPE::TYPE_INT; }
64  bool is_decimal() const { return type() == VARIANT_TYPE::TYPE_DECIMAL; }
65  bool is_callable() const { return type() == VARIANT_TYPE::TYPE_CALLABLE; }
66  bool is_list() const { return type() == VARIANT_TYPE::TYPE_LIST; }
67  bool is_string() const { return type() == VARIANT_TYPE::TYPE_STRING; }
68  bool is_map() const { return type() == VARIANT_TYPE::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(VARIANT_TYPE::TYPE_CALLABLE);
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  {
150  return type().to_string();
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(VARIANT_TYPE t) const;
163 
164  void must_both_be(VARIANT_TYPE t, const variant& second) const;
165 
166  VARIANT_TYPE type() const
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 boost::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:
218  VARIANT_TYPE type_;
220  boost::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
void must_both_be(VARIANT_TYPE t, const variant &second) const
Definition: variant.cpp:617
bool is_map() const
Definition: variant.hpp:68
std::shared_ptr< variant_value_base > value_base_ptr
int as_int() const
Definition: variant.cpp:295
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:597
bool is_string() const
Definition: variant.hpp:67
bool is_callable() const
Definition: variant.hpp:65
variant operator-() const
Definition: variant.cpp:481
const std::map< variant, variant > & as_map() const
Definition: variant.cpp:334
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:444
bool is_list() const
Definition: variant.hpp:66
const std::vector< variant > & as_list() const
Definition: variant.cpp:328
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:322
bool operator<=(const variant &) const
Definition: variant.cpp:530
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:304
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:632
variant list_elements_add(const variant &v) const
Definition: variant.cpp:540
VARIANT_TYPE type_
Definition: variant.hpp:218
bool operator!=(const variant &) const
Definition: variant.cpp:503
std::string serialize_to_string() const
Definition: variant.cpp:627
variant_iterator end() const
Definition: variant.cpp:261
void must_be(VARIANT_TYPE t) const
Definition: variant.cpp:610
variant list_elements_mul(const variant &v) const
Definition: variant.cpp:552
variant operator/(const variant &) const
Definition: variant.cpp:409
variant build_range(const variant &v) const
Definition: variant.cpp:590
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:558
VARIANT_TYPE type() const
Definition: variant.hpp:166
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:535
const variant_value_base * container_
Definition: variant.hpp:219
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:564
std::shared_ptr< T > try_convert() const
Definition: variant.hpp:90
variant operator+(const variant &) const
Definition: variant.cpp:340
double t
Definition: astarsearch.cpp:65
Definition: contexts.hpp:44
variant get_keys() const
Definition: variant.cpp:232
variant_iterator begin() const
Definition: variant.cpp:256
variant get_values() const
Definition: variant.cpp:244
bool operator<(const variant &) const
Definition: variant.cpp:508
Base class for all variant types.
std::size_t num_elements() const
Definition: variant.cpp:271
variant get_member(const std::string &name) const
Definition: variant.cpp:280
Iterator class for the variant.
Definition: variant.hpp:186
bool as_bool() const
Returns a boolean state of the variant value.
Definition: variant.cpp:317
static map_location::DIRECTION n
bool operator>=(const variant &) const
Definition: variant.cpp:525
variant operator[](std::size_t n) const
Definition: variant.cpp:184
variant operator^(const variant &) const
Definition: variant.cpp:465
bool is_empty() const
Definition: variant.cpp:266
std::shared_ptr< T > convert_to() const
Definition: variant.hpp:100
variant list_elements_sub(const variant &v) const
Definition: variant.cpp:546
variant operator*(const variant &) const
Definition: variant.cpp:386
bool operator==(const variant &) const
Definition: variant.cpp:490
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:646