The Battle for Wesnoth  1.15.2+dev
variable_info_detail.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 by David White <dave@whitevine.net>
3  Copyright (C) 2005 - 2018 by Philippe Plantier <ayin@anathas.org>
4 
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 "utils/const_clone.hpp"
21 
22 #include <string>
23 #include <type_traits>
24 
26 {
27 /**
28  * The variable_info policy classes.
29  *
30  * Each of these classes describes a different behavior for reading data from a variable
31  * and should implement two functions:
32  *
33  * - get_child_at Describes the desired behavior when reading variable info.
34  * - error_message Error message regarding policy behavior.
35  */
36 
37 /** Takes a const reference and is guaranteed to not change the config. */
39 {
40 public:
41  static const config& get_child_at(const config& cfg, const std::string& key, int index)
42  {
43  assert(index >= 0);
44  // cfg.child_or_empty does not support index parameter
45  if(const config& child = cfg.child(key, index)) {
46  return child;
47  }
48 
49  static const config empty_const_cfg;
50  return empty_const_cfg;
51  }
52 
53  static std::string error_message(const std::string& name)
54  {
55  return "Cannot resolve variable '" + name + "' for reading.";
56  }
57 };
58 
59 /** Creates a child table when resolving name if it doesn't exist yet. */
61 {
62 public:
63  static config& get_child_at(config& cfg, const std::string& key, int index)
64  {
65  assert(index >= 0);
66  // the 'create_if_not_existent' logic.
67  while(static_cast<int>(cfg.child_count(key)) <= index) {
68  cfg.add_child(key);
69  }
70 
71  return cfg.child(key, index);
72  }
73 
74  static std::string error_message(const std::string& name)
75  {
76  return "Cannot resolve variable '" + name + "' for writing.";
77  }
78 };
79 
80 /**
81  * Will throw an exception when trying to access a nonexistent table.
82  * Note that the other types can throw too if name is invlid, such as '..[[[a'.
83  */
85 {
86 public:
87  static config& get_child_at(config& cfg, const std::string& key, int index)
88  {
89  assert(index >= 0);
90  if(config& child = cfg.child(key, index)) {
91  return child;
92  }
93 
95  }
96 
97  static std::string error_message(const std::string& name)
98  {
99  return "Cannot resolve variable '" + name + "' for writing without creating new children.";
100  }
101 };
102 
103 // ==================================================================
104 // Other implementation details.
105 // ==================================================================
106 
107 template<typename T, typename V>
108 struct maybe_const : public utils::const_clone<T, V>
109 {
110  // Meta type aliases provided by const_clone
111 };
112 
113 template<>
114 struct maybe_const<config::child_itors, const vi_policy_const>
115 {
117 };
118 
120  state_start = 0, /**< Represents the initial variable state before processing. */
121  state_named, /**< The result of .someval. This can either mean an attribute value or a child range. */
122  state_indexed, /**< The result of .someval[index]. This is never an attribute value and is always a single config. */
123  state_temporary, /**< The result of .length. This value can never be written, it can only be read. */
124 };
125 
126 template<typename V>
128 {
130 
132  : child_(&vars)
133  , key_()
134  , index_(0)
135  , temp_val_()
136  , type_(state_start)
137  {
138  child_ = &vars;
139  }
140 
141  // The meaning of the following 3 depends on 'type_', but the current config is usually
142  // child_->child_at(key_, index_).
144  std::string key_;
145  int index_;
146 
147  // If we have a temporary value like .length we store the result here.
149 
150  // See @ref variable_info_state_type
152 };
153 } // end namespace variable_info_implementation
154 
155 /** Helper template alias for maybe_const, defined at global scope for convenience. */
156 template<typename T, typename V>
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:420
typename variable_info_implementation::maybe_const< T, V >::type maybe_const_t
Helper template alias for maybe_const, defined at global scope for convenience.
static std::string error_message(const std::string &name)
Variant for storing WML attributes.
static std::string error_message(const std::string &name)
Helper struct to clone the constness of one type to another.
Definition: const_clone.hpp:36
unsigned child_count(config_key_type key) const
Definition: config.cpp:390
typename maybe_const< config, V >::type child_t
Represents the initial variable state before processing.
Creates a child table when resolving name if it doesn&#39;t exist yet.
Definitions for the interface to Wesnoth Markup Language (WML).
static config & get_child_at(config &cfg, const std::string &key, int index)
Will throw an exception when trying to access a nonexistent table.
boost::iterator_range< const_child_iterator > const_child_itors
Definition: config.hpp:210
std::conditional_t< is_source_const, const T, T > type
The destination type, possibly const qualified.
Definition: const_clone.hpp:47
static config & get_child_at(config &cfg, const std::string &key, int index)
static std::string error_message(const std::string &name)
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
static const config & get_child_at(const config &cfg, const std::string &key, int index)
config & add_child(config_key_type key)
Definition: config.cpp:476
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68