The Battle for Wesnoth  1.19.0-dev
variable.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2005 - 2024
3  by Philippe Plantier <ayin@anathas.org>
4  Copyright (C) 2003 by David White <dave@whitevine.net>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #pragma once
18 
19 #include "config.hpp"
20 #include "map/location.hpp"
21 #include "variable_info.hpp"
22 
23 #include <utility>
24 
25 class unit_map;
26 
28  const config& cfg_;
29 public:
30  config_variable_set(const config& cfg) : cfg_(cfg) {}
31  virtual config::attribute_value get_variable_const(const std::string &id) const;
32  virtual variable_access_const get_variable_access_read(const std::string& varname) const;
33 };
34 
35 /**
36  * A variable-expanding proxy for the config class. This class roughly behaves
37  * as a constant config object, but automatically expands variables.
38  *
39  * When dealing with a vconfig, keep in mind its lifetime. By default, vconfigs
40  * do not maintain a copy their data; if you need a vconfig to stick around,
41  * either construct it with manage_memory=true or call make_safe(). This will
42  * cause the vconfig to make a copy of the underlying config object.
43  */
44 class vconfig
45 {
46 private:
47 
48  vconfig();
49  vconfig(const config & cfg, const std::shared_ptr<const config> & cache);
50  vconfig(const config& cfg, const std::shared_ptr<const config> & cache, const variable_set& variables);
51 public:
52  /**
53  * Constructor from a config.
54  * Equivalent to vconfig(cfg, false).
55  * Do not use if the vconfig will persist after @a cfg is destroyed!
56  */
57  explicit vconfig(const config &cfg);
58  explicit vconfig(config &&cfg);
59  // Construct a vconfig referencing a non-default set of variables.
60  // Note that the vconfig does NOT take ownership of these variables,
61  // so you need to make sure that their scope encloses the vconfig's scope!
62  vconfig(const config& cfg, const variable_set& variables);
63  vconfig(const config &cfg, bool manage_memory, const variable_set* variables = nullptr);
64  ~vconfig();
65 
66  static vconfig empty_vconfig(); // Valid to dereference. Contains nothing
67  static vconfig unconstructed_vconfig(); // Must not be dereferenced
68 
69  /** A vconfig evaluates to true iff it can be dereferenced. */
70  explicit operator bool() const { return !null(); }
71 
72  bool null() const { assert(cfg_); return cfg_ == &default_empty_config; }
73  /** instruct the vconfig to make a private copy of its underlying data. */
74  const vconfig& make_safe() const;
75  const config& get_config() const { return *cfg_; }
76  config get_parsed_config() const;
77 
78  typedef std::vector<vconfig> child_list;
79  child_list get_children(const std::string& key) const;
80  std::size_t count_children(const std::string& key) const;
81  vconfig child(const std::string& key) const;
82  bool has_child(const std::string& key) const;
83 
84  /**
85  * Note: vconfig::operator[] returns const, and this should not be changed
86  * because vconfig is often used as a drop-in replacement for config, and
87  * this const will properly warn you if you try to assign vcfg["key"]=val;
88  *
89  * Note: The following construction is unsafe:
90  * const std::string& temp = vcfg["foo"];
91  * This binds temp to a member of a temporary t_string. The lifetime of the
92  * temporary is not extended by this reference binding and the temporary's
93  * lifetime ends which causes UB. Instead use:
94  * const std::string temp = vcfg["foo"];
95  */
96  const config::attribute_value operator[](const std::string &key) const
97  { return expand(key); }
98  config::attribute_value expand(const std::string&) const; /** < Synonym for operator[] */
99  bool has_attribute(const std::string& key) const { return cfg_->has_attribute(key); }
100  bool empty() const { return (null() || cfg_->empty()); }
101 
103  {
104  struct pointer_proxy;
105 
107  typedef std::bidirectional_iterator_tag iterator_category;
108  typedef int difference_type;
109  typedef const pointer_proxy pointer;
112  explicit attribute_iterator(const Itor &i, const variable_set& vars): i_(i), variables_(&vars) {}
113 
114  attribute_iterator &operator++() { ++i_; return *this; }
116 
117  attribute_iterator &operator--() { --i_; return *this; }
119 
120  reference operator*() const;
121  pointer operator->() const;
122 
123  bool operator==(const attribute_iterator &i) const { return i_ == i.i_; }
124  bool operator!=(const attribute_iterator &i) const { return i_ != i.i_; }
125 
126  private:
129  };
130 
131  boost::iterator_range<attribute_iterator> attribute_range() {
133  return boost::make_iterator_range(attribute_iterator(range.begin(), *variables_), attribute_iterator(range.end(), *variables_));
134  }
135 
137  {
138  struct pointer_proxy;
139 
140  typedef const std::pair<std::string, vconfig> value_type;
141  typedef std::bidirectional_iterator_tag iterator_category;
142  typedef int difference_type;
143  typedef const pointer_proxy pointer;
144  typedef const value_type reference;
146  explicit all_children_iterator(const Itor &i, const variable_set& vars);
147  all_children_iterator(const Itor &i, const variable_set& vars, const std::shared_ptr<const config> & cache);
148 
153 
154  reference operator*() const;
155  pointer operator->() const;
156 
157  std::string get_key() const;
158  vconfig get_child() const;
160 
161  bool operator==(const all_children_iterator &i) const;
162  bool operator!=(const all_children_iterator &i) const
163  { return !operator==(i); }
164 
165  private:
167  /*
168  if wa have game variables
169  [a] b = 1 [/a]
170  [a] b = 4 [/a]
171  [a] b = 6 [/a]
172  we want to expand [insert_tag] variable = a name = "u" [/insert_tag] to
173  [u] b = 1 [/u]
174  [u] b = 4 [/u]
175  [u] b = 6 [/u]
176  in this case inner_index_ points to the index in 'a' we are currently processing.
177  */
179  std::shared_ptr<const config> cache_;
181  };
182 
183  struct recursion_error : public config::error {
184  recursion_error(const std::string& msg) : error(msg) {}
185  };
186 
187  /** In-order iteration over all children. */
188  all_children_iterator ordered_begin() const;
189  all_children_iterator ordered_end() const;
190  boost::iterator_range<all_children_iterator> all_ordered() const {
191  return boost::make_iterator_range(ordered_begin(), ordered_end());
192  }
193 
194 private:
195  /** Returns true if *this has made a copy of its config. */
196  bool memory_managed() const { return static_cast<bool>(cache_); }
197 
198  /**
199  * Keeps a copy of our config alive when we manage our own memory.
200  * If this is not null, then cfg_ points to *cache_ or a child of *cache_.
201  */
202  mutable std::shared_ptr<const config> cache_;
203  /** Used to access our config (original or copy, as appropriate). */
204  mutable const config* cfg_;
207 };
208 
210 {
213  value_type *operator->() const { return &p; }
214 };
215 
217 {
220  value_type *operator->() const { return &p; }
221 };
222 
223 
225 {
226 public:
227  scoped_wml_variable(const std::string& var_name);
228  virtual ~scoped_wml_variable();
229  const std::string& name() const { return var_name_; }
230  virtual void activate() = 0;
231  config &store(const config &var_value = config());
232  bool activated() const { return activated_; }
233 private:
235  const std::string var_name_;
237 };
238 
240 {
241 public:
242  scoped_weapon_info(const std::string& var_name, optional_const_config data)
243  : scoped_wml_variable(var_name), data_(data) {}
244  void activate();
245 private:
247 };
248 
250 {
251 public:
252  scoped_xy_unit(const std::string& var_name, map_location loc, const unit_map& umap)
253  : scoped_wml_variable(var_name), loc_(loc), umap_(umap) {}
254  void activate();
255 private:
257  const unit_map& umap_;
258 };
259 
261 {
262 public:
263  scoped_recall_unit(const std::string& var_name, const std::string& player,
264  unsigned int recall_index) : scoped_wml_variable(var_name), player_(player),
265  recall_index_(recall_index) {}
266  void activate();
267 private:
268  const std::string player_;
269  unsigned int recall_index_;
270 };
Variant for storing WML attributes.
config_variable_set(const config &cfg)
Definition: variable.hpp:30
virtual config::attribute_value get_variable_const(const std::string &id) const
Definition: variable.cpp:65
const config & cfg_
Definition: variable.hpp:28
virtual variable_access_const get_variable_access_read(const std::string &varname) const
Definition: variable.cpp:75
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
const_attr_itors attribute_range() const
Definition: config.cpp:763
bool has_attribute(config_key_type key) const
Definition: config.cpp:155
boost::iterator_range< const_attribute_iterator > const_attr_itors
Definition: config.hpp:359
attribute_map::value_type attribute
Definition: config.hpp:299
bool empty() const
Definition: config.cpp:852
unsigned int recall_index_
Definition: variable.hpp:269
const std::string player_
Definition: variable.hpp:268
scoped_recall_unit(const std::string &var_name, const std::string &player, unsigned int recall_index)
Definition: variable.hpp:263
scoped_weapon_info(const std::string &var_name, optional_const_config data)
Definition: variable.hpp:242
optional_const_config data_
Definition: variable.hpp:246
scoped_wml_variable(const std::string &var_name)
Definition: variable.cpp:490
virtual void activate()=0
config & store(const config &var_value=config())
Definition: variable.cpp:499
bool activated() const
Definition: variable.hpp:232
virtual ~scoped_wml_variable()
Definition: variable.cpp:520
const std::string var_name_
Definition: variable.hpp:235
const std::string & name() const
Definition: variable.hpp:229
const map_location loc_
Definition: variable.hpp:256
void activate()
Definition: variable.cpp:545
const unit_map & umap_
Definition: variable.hpp:257
scoped_xy_unit(const std::string &var_name, map_location loc, const unit_map &umap)
Definition: variable.hpp:252
Container associating units to locations.
Definition: map.hpp:98
Information on a WML variable.
A variable-expanding proxy for the config class.
Definition: variable.hpp:45
~vconfig()
Default destructor, but defined here for possibly faster compiles (templates sometimes can be rough o...
Definition: variable.cpp:137
bool memory_managed() const
Returns true if *this has made a copy of its config.
Definition: variable.hpp:196
all_children_iterator ordered_begin() const
In-order iteration over all children.
Definition: variable.cpp:480
bool has_attribute(const std::string &key) const
< Synonym for operator[]
Definition: variable.hpp:99
std::vector< vconfig > child_list
Definition: variable.hpp:78
static vconfig unconstructed_vconfig()
This is just a wrapper for the default constructor; it exists for historical reasons and to make it c...
Definition: variable.cpp:152
static vconfig empty_vconfig()
Definition: variable.cpp:141
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
Definition: variable.cpp:288
config::attribute_value expand(const std::string &) const
Definition: variable.cpp:352
const config & get_config() const
Definition: variable.hpp:75
config get_parsed_config() const
Definition: variable.cpp:176
all_children_iterator ordered_end() const
Definition: variable.cpp:485
const vconfig & make_safe() const
instruct the vconfig to make a private copy of its underlying data.
Definition: variable.cpp:163
std::shared_ptr< const config > cache_
Keeps a copy of our config alive when we manage our own memory.
Definition: variable.hpp:202
boost::iterator_range< all_children_iterator > all_ordered() const
Definition: variable.hpp:190
vconfig()
Definition: variable.cpp:89
static const config default_empty_config
Definition: variable.hpp:206
const config * cfg_
Used to access our config (original or copy, as appropriate).
Definition: variable.hpp:204
std::size_t count_children(const std::string &key) const
Definition: variable.cpp:256
child_list get_children(const std::string &key) const
Definition: variable.cpp:226
boost::iterator_range< attribute_iterator > attribute_range()
Definition: variable.hpp:131
const variable_set * variables_
Definition: variable.hpp:205
const config::attribute_value operator[](const std::string &key) const
Note: vconfig::operator[] returns const, and this should not be changed because vconfig is often used...
Definition: variable.hpp:96
bool empty() const
Definition: variable.hpp:100
bool has_child(const std::string &key) const
Returns whether or not *this has a child whose key is key.
Definition: variable.cpp:315
std::size_t i
Definition: function.cpp:968
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string_view data
Definition: picture.cpp:194
Encapsulates the map of the game.
Definition: location.hpp:38
std::shared_ptr< const config > cache_
Definition: variable.hpp:179
all_children_iterator(const Itor &i, const variable_set &vars)
Definition: variable.cpp:374
const value_type reference
Definition: variable.hpp:144
bool operator!=(const all_children_iterator &i) const
Definition: variable.hpp:162
all_children_iterator & operator++()
Definition: variable.cpp:384
const std::pair< std::string, vconfig > value_type
Definition: variable.hpp:138
reference operator*() const
Definition: variable.cpp:435
bool operator==(const all_children_iterator &i) const
Definition: variable.cpp:475
config::const_all_children_iterator Itor
Definition: variable.hpp:145
const variable_set * variables_
Definition: variable.hpp:180
const pointer_proxy pointer
Definition: variable.hpp:143
std::string get_key() const
Definition: variable.cpp:447
std::bidirectional_iterator_tag iterator_category
Definition: variable.hpp:141
all_children_iterator & operator--()
Definition: variable.cpp:416
config::const_attribute_iterator Itor
Definition: variable.hpp:111
pointer operator->() const
Definition: variable.cpp:366
reference operator*() const
Definition: variable.cpp:359
bool operator==(const attribute_iterator &i) const
Definition: variable.hpp:123
const pointer_proxy pointer
Definition: variable.hpp:109
const config::attribute reference
Definition: variable.hpp:110
attribute_iterator operator++(int)
Definition: variable.hpp:115
attribute_iterator operator--(int)
Definition: variable.hpp:118
const variable_set * variables_
Definition: variable.hpp:128
attribute_iterator & operator++()
Definition: variable.hpp:114
attribute_iterator & operator--()
Definition: variable.hpp:117
bool operator!=(const attribute_iterator &i) const
Definition: variable.hpp:124
const config::attribute value_type
Definition: variable.hpp:104
attribute_iterator(const Itor &i, const variable_set &vars)
Definition: variable.hpp:112
std::bidirectional_iterator_tag iterator_category
Definition: variable.hpp:107
recursion_error(const std::string &msg)
Definition: variable.hpp:184