The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
formula.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://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 #ifndef GUI_WIDGETS_FORMULA_HPP_INCLUDED
16 #define GUI_WIDGETS_FORMULA_HPP_INCLUDED
17 
18 #include "formula/callable.hpp"
19 #include "formula/function.hpp"
20 #include "formula/formula.hpp"
21 #include "gui/core/log.hpp"
22 #include "gui/widgets/helper.hpp"
24 #include "util.hpp"
25 #include "tstring.hpp"
26 
27 #include <cassert>
28 
29 namespace gui2
30 {
31 
32 /**
33  * Template class can hold a value or a formula to calculate the value.
34  *
35  * A string is a formula when it starts with a right paren, no other validation
36  * is done by this function, leading whitespace is significant.
37  *
38  * Upon getting the value of the formula a variable map is send. The variables
39  * in the map can be used in the formula. The 'owners' of the class need to
40  * document the variables available.
41  *
42  * @tparam T The type of the formula. This type needs to
43  * be constructable form a string, either by a
44  * lexical_cast or a template specialization in
45  * this header.
46  */
47 template <class T>
48 class tformula
49 {
50 public:
51  /**
52  * Constructor.
53  *
54  * @param str The string used to initialize the class, this
55  * can either be a formula or a string which can
56  * be converted to the type T.
57  * @param value The default value for the object.
58  */
59  explicit tformula<T>(const std::string& str, const T value = T());
60 
61  /**
62  * Returns the value, can only be used if the data is no formula.
63  *
64  * Another option would be to cache the output of the formula in value_
65  * and always allow this function. But for now decided that the caller
66  * needs to do the caching. It might be changed later.
67  */
68  T operator()() const
69  {
70  assert(!has_formula());
71  return value_;
72  }
73 
74  /**
75  * Returns the value, can always be used.
76  *
77  * @param variables The variables, which can be used during the
78  * evaluation of the formula.
79  * @param functions The variables, which can be called during the
80  * evaluation of the formula. (Note is is also
81  * possible to add extra functions to the table,
82  * when the variable is not @c nullptr.
83  *
84  * @returns The stored result or the result of the
85  * evaluation of the formula.
86  */
88  game_logic::function_symbol_table* functions = nullptr) const;
89 
90  /** Determine whether the class contains a formula. */
91  bool has_formula() const
92  {
93  return !formula_.empty();
94  }
95 
96 private:
97  /**
98  * Converts the string to the template type.
99  *
100  * This function is used by the constructor to convert the string to the
101  * wanted value, if not a formula.
102  *
103  * @param str The str send to the constructor.
104  */
105  void convert(const std::string& str);
106 
107  /**
108  * Executes the formula.
109  *
110  * This function does the calculation and can only be called if the object
111  * contains a formula.
112  *
113  * @param variables The state variables which might be used in
114  * the formula. For example a screen_width can
115  * be set so the formula can return the half
116  * width of the screen.
117  * @param functions The variables, which can be called during the
118  * evaluation of the formula. (Note is is also
119  * possible to add extra functions to the table,
120  * when the variable is not @c nullptr.
121  *
122  * @returns The calculated value.
123  */
124  T execute(const game_logic::map_formula_callable& variables,
125  game_logic::function_symbol_table* functions) const;
126 
127  /**
128  * Contains the formula for the variable.
129  *
130  * If the string is empty, there's no formula.
131  */
133 
134  /** If there's no formula it contains the value. */
136 };
137 
138 template <class T>
140  : formula_(), value_(value)
141 {
142  if(str.empty()) {
143  return;
144  }
145 
146  if(str[0] == '(') {
147  formula_ = str;
148  } else {
149  convert(str);
150  }
151 }
152 
153 template <class T>
154 inline T tformula<T>::
156  game_logic::function_symbol_table* functions) const
157 {
158  if(has_formula()) {
159  const T& result = execute(variables, functions);
160  LOG_GUI_D << "Formula: execute '" << formula_ << "' result '" << result
161  << "'.\n";
162  return result;
163  } else {
164  return value_;
165  }
166 }
167 
168 template <>
169 inline bool
171  game_logic::function_symbol_table* functions) const
172 {
173  return game_logic::formula(formula_, functions)
174  .evaluate(variables)
175  .as_bool();
176 }
177 
178 template <>
179 inline int
181  game_logic::function_symbol_table* functions) const
182 {
183  return game_logic::formula(formula_, functions)
184  .evaluate(variables)
185  .as_int();
186 }
187 
188 template <>
189 inline unsigned
191  game_logic::function_symbol_table* functions) const
192 {
193  return game_logic::formula(formula_, functions)
194  .evaluate(variables)
195  .as_int();
196 }
197 
198 template <>
200  const game_logic::map_formula_callable& variables,
201  game_logic::function_symbol_table* functions) const
202 {
203  return game_logic::formula(formula_, functions)
204  .evaluate(variables)
205  .as_string();
206 }
207 
208 template <>
209 inline t_string
211  game_logic::function_symbol_table* functions) const
212 {
213  return game_logic::formula(formula_, functions)
214  .evaluate(variables)
215  .as_string();
216 }
217 
218 template <>
219 inline PangoAlignment tformula<PangoAlignment>::execute(
220  const game_logic::map_formula_callable& variables,
221  game_logic::function_symbol_table* functions) const
222 {
223  return decode_text_alignment(game_logic::formula(formula_, functions)
224  .evaluate(variables)
225  .as_string());
226 }
227 
228 template <class T>
229 inline T
231  ,
232  game_logic::function_symbol_table* /*functions*/) const
233 {
234  // Every type needs its own execute function avoid instantiation of the
235  // default execute.
236  static_assert(sizeof(T) == 0, "tformula: Missing execute specialization");
237  return T();
238 }
239 
240 template <>
241 inline void tformula<bool>::convert(const std::string& str)
242 {
243  value_ = utils::string_bool(str);
244 }
245 
246 template <>
248 {
249  value_ = str;
250 }
251 
252 template <>
254 {
255  value_ = str;
256 }
257 
258 template <>
260 {
261  value_ = decode_text_alignment(str);
262 }
263 
264 template <class T>
265 inline void tformula<T>::convert(const std::string& str)
266 {
267  value_ = lexical_cast_default<T>(str);
268 }
269 
270 } // namespace gui2
271 
272 #endif
Define the common log macros for the gui toolkit.
T value_
If there's no formula it contains the value.
Definition: formula.hpp:135
#define LOG_GUI_D
Definition: log.hpp:30
bool as_bool() const
Definition: variant.cpp:580
PangoAlignment decode_text_alignment(const std::string &alignment)
Converts a text alignment string to a text alignment.
Definition: helper.cpp:92
Template class can hold a value or a formula to calculate the value.
Definition: formula.hpp:48
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
tformula(const std::string &str, const T value=T())
Constructor.
Definition: formula.hpp:139
GLuint64EXT * result
Definition: glew.h:10727
int as_int() const
Definition: variant.cpp:558
GLsizei const GLfloat * value
Definition: glew.h:1817
T execute(const game_logic::map_formula_callable &variables, game_logic::function_symbol_table *functions) const
Executes the formula.
Definition: formula.hpp:230
Templates and utility-routines for strings and numbers.
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
const std::string & as_string() const
Definition: variant.cpp:603
bool string_bool(const std::string &str, bool def)
Convert no, false, off, 0, 0.0 to false, empty to def, and others to true.
T operator()() const
Returns the value, can only be used if the data is no formula.
Definition: formula.hpp:68
void convert(const std::string &str)
Converts the string to the template type.
Definition: formula.hpp:265
bool has_formula() const
Determine whether the class contains a formula.
Definition: formula.hpp:91
GLsizei const GLcharARB ** string
Definition: glew.h:4503
std::string formula_
Contains the formula for the variable.
Definition: formula.hpp:132