Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/kyua/utils/config/nodes.hpp
48081 views
1
// Copyright 2012 The Kyua Authors.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above copyright
11
// notice, this list of conditions and the following disclaimer in the
12
// documentation and/or other materials provided with the distribution.
13
// * Neither the name of Google Inc. nor the names of its contributors
14
// may be used to endorse or promote products derived from this software
15
// without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
/// \file utils/config/nodes.hpp
30
/// Representation of tree nodes.
31
32
#if !defined(UTILS_CONFIG_NODES_HPP)
33
#define UTILS_CONFIG_NODES_HPP
34
35
#include "utils/config/nodes_fwd.hpp"
36
37
#include <set>
38
#include <string>
39
40
#include <lutok/state.hpp>
41
42
#include "utils/config/keys_fwd.hpp"
43
#include "utils/config/nodes_fwd.hpp"
44
#include "utils/noncopyable.hpp"
45
#include "utils/optional.hpp"
46
47
namespace utils {
48
namespace config {
49
50
51
namespace detail {
52
53
54
/// Base representation of a node.
55
///
56
/// This abstract class provides the base type for every node in the tree. Due
57
/// to the dynamic nature of our trees (each leaf being able to hold arbitrary
58
/// data types), this base type is a necessity.
59
class base_node : noncopyable {
60
public:
61
virtual ~base_node(void) = 0;
62
63
/// Copies the node.
64
///
65
/// \return A dynamically-allocated node.
66
virtual base_node* deep_copy(void) const = 0;
67
68
/// Combines this node with another one.
69
///
70
/// \param key Key to this node.
71
/// \param other The node to combine with.
72
///
73
/// \return A new node representing the combination.
74
///
75
/// \throw bad_combination_error If the two nodes cannot be combined.
76
virtual base_node* combine(const tree_key& key, const base_node* other)
77
const = 0;
78
};
79
80
81
} // namespace detail
82
83
84
/// Abstract leaf node without any specified type.
85
///
86
/// This base abstract type is necessary to have a common pointer type to which
87
/// to cast any leaf. We later provide templated derivates of this class, and
88
/// those cannot act in this manner.
89
///
90
/// It is important to understand that a leaf can exist without actually holding
91
/// a value. Our trees are "strictly keyed": keys must have been pre-defined
92
/// before a value can be set on them. This is to ensure that the end user is
93
/// using valid key names and not making mistakes due to typos, for example. To
94
/// represent this condition, we define an "empty" key in the tree to denote
95
/// that the key is valid, yet it has not been set by the user. Only when an
96
/// explicit set is performed on the key, it gets a value.
97
class leaf_node : public detail::base_node {
98
public:
99
virtual ~leaf_node(void);
100
101
virtual bool is_set(void) const = 0;
102
103
base_node* combine(const detail::tree_key&, const base_node*) const;
104
105
virtual void push_lua(lutok::state&) const = 0;
106
virtual void set_lua(lutok::state&, const int) = 0;
107
108
virtual void set_string(const std::string&) = 0;
109
virtual std::string to_string(void) const = 0;
110
};
111
112
113
/// Base leaf node for a single arbitrary type.
114
///
115
/// This templated leaf node holds a single object of any type. The conversion
116
/// to/from string representations is undefined, as that depends on the
117
/// particular type being processed. You should reimplement this class for any
118
/// type that needs additional processing/validation during conversion.
119
template< typename ValueType >
120
class typed_leaf_node : public leaf_node {
121
public:
122
/// The type of the value held by this node.
123
typedef ValueType value_type;
124
125
/// Constructs a new leaf node that contains no value.
126
typed_leaf_node(void);
127
128
/// Checks whether the node has been set by the user.
129
bool is_set(void) const;
130
131
/// Gets the value stored in the node.
132
const value_type& value(void) const;
133
134
/// Gets the read-write value stored in the node.
135
value_type& value(void);
136
137
/// Sets the value of the node.
138
void set(const value_type&);
139
140
protected:
141
/// The value held by this node.
142
optional< value_type > _value;
143
144
private:
145
virtual void validate(const value_type&) const;
146
};
147
148
149
/// Leaf node holding a native type.
150
///
151
/// This templated leaf node holds a native type. The conversion to/from string
152
/// representations of the value happens by means of iostreams.
153
template< typename ValueType >
154
class native_leaf_node : public typed_leaf_node< ValueType > {
155
public:
156
void set_string(const std::string&);
157
std::string to_string(void) const;
158
};
159
160
161
/// A leaf node that holds a boolean value.
162
class bool_node : public native_leaf_node< bool > {
163
public:
164
virtual base_node* deep_copy(void) const;
165
166
void push_lua(lutok::state&) const;
167
void set_lua(lutok::state&, const int);
168
};
169
170
171
/// A leaf node that holds an integer value.
172
class int_node : public native_leaf_node< int > {
173
public:
174
virtual base_node* deep_copy(void) const;
175
176
void push_lua(lutok::state&) const;
177
void set_lua(lutok::state&, const int);
178
};
179
180
181
/// A leaf node that holds a positive non-zero integer value.
182
class positive_int_node : public int_node {
183
virtual void validate(const value_type&) const;
184
};
185
186
187
/// A leaf node that holds a string value.
188
class string_node : public native_leaf_node< std::string > {
189
public:
190
virtual base_node* deep_copy(void) const;
191
192
void push_lua(lutok::state&) const;
193
void set_lua(lutok::state&, const int);
194
};
195
196
197
/// Base leaf node for a set of native types.
198
///
199
/// This is a base abstract class because there is no generic way to parse a
200
/// single word in the textual representation of the set to the native value.
201
template< typename ValueType >
202
class base_set_node : public leaf_node {
203
public:
204
/// The type of the value held by this node.
205
typedef std::set< ValueType > value_type;
206
207
base_set_node(void);
208
209
/// Checks whether the node has been set by the user.
210
///
211
/// \return True if a value has been set in the node.
212
bool is_set(void) const;
213
214
/// Gets the value stored in the node.
215
///
216
/// \pre The node must have a value.
217
///
218
/// \return The value in the node.
219
const value_type& value(void) const;
220
221
/// Gets the read-write value stored in the node.
222
///
223
/// \pre The node must have a value.
224
///
225
/// \return The value in the node.
226
value_type& value(void);
227
228
/// Sets the value of the node.
229
void set(const value_type&);
230
231
/// Sets the value of the node from a raw string representation.
232
void set_string(const std::string&);
233
234
/// Converts the contents of the node to a string.
235
std::string to_string(void) const;
236
237
/// Pushes the node's value onto the Lua stack.
238
void push_lua(lutok::state&) const;
239
240
/// Sets the value of the node from an entry in the Lua stack.
241
void set_lua(lutok::state&, const int);
242
243
protected:
244
/// The value held by this node.
245
optional< value_type > _value;
246
247
private:
248
/// Converts a single word to the native type.
249
///
250
/// \return The parsed value.
251
///
252
/// \throw value_error If the value is invalid.
253
virtual ValueType parse_one(const std::string&) const = 0;
254
255
virtual void validate(const value_type&) const;
256
};
257
258
259
/// A leaf node that holds a set of strings.
260
class strings_set_node : public base_set_node< std::string > {
261
public:
262
virtual base_node* deep_copy(void) const;
263
264
private:
265
std::string parse_one(const std::string&) const;
266
};
267
268
269
} // namespace config
270
} // namespace utils
271
272
#endif // !defined(UTILS_CONFIG_NODES_HPP)
273
274