1 // Copyright 2012 Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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.
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.
29 #include "utils/config/nodes.hpp"
31 #if !defined(UTILS_CONFIG_NODES_IPP)
32 #define UTILS_CONFIG_NODES_IPP
37 #include "utils/config/exceptions.hpp"
38 #include "utils/defs.hpp"
39 #include "utils/format/macros.hpp"
40 #include "utils/optional.ipp"
41 #include "utils/text/exceptions.hpp"
42 #include "utils/text/operations.ipp"
43 #include "utils/sanity.hpp"
52 /// Type of the new_node() family of functions.
53 typedef base_node* (*new_node_hook)(void);
56 /// Creates a new leaf node of a given type.
58 /// \tparam NodeType The type of the leaf node to create.
60 /// \return A pointer to the newly-created node.
61 template< class NodeType >
65 return new NodeType();
69 /// Internal node of the tree.
71 /// This abstract base class provides the mechanism to implement both static and
72 /// dynamic nodes. Ideally, the implementation would be split in subclasses and
73 /// this class would not include the knowledge of whether the node is dynamic or
74 /// not. However, because the static/dynamic difference depends on the leaf
75 /// types, we need to declare template functions and these cannot be virtual.
76 class inner_node : public base_node {
77 /// Whether the node is dynamic or not.
81 /// Type to represent the collection of children of this node.
83 /// Note that these are one-level keys. They cannot contain dots, and thus
84 /// is why we use a string rather than a tree_key.
85 typedef std::map< std::string, base_node* > children_map;
87 /// Mapping of keys to values that are descendants of this node.
88 children_map _children;
90 void copy_into(inner_node* new_node) const;
93 inner_node(const bool);
94 virtual ~inner_node(void) = 0;
96 const base_node* lookup_ro(const tree_key&,
97 const tree_key::size_type) const;
98 leaf_node* lookup_rw(const tree_key&, const tree_key::size_type,
101 void all_properties(properties_map&, const tree_key&) const;
105 /// Static internal node of the tree.
107 /// The direct children of this node must be pre-defined by calls to define().
108 /// Attempts to traverse this node and resolve a key that is not a pre-defined
109 /// children will result in an "unknown key" error.
110 class static_inner_node : public config::detail::inner_node {
112 static_inner_node(void);
114 virtual base_node* deep_copy(void) const;
116 void define(const tree_key&, const tree_key::size_type, new_node_hook);
120 /// Dynamic internal node of the tree.
122 /// The children of this node need not be pre-defined. Attempts to traverse
123 /// this node and resolve a key will result in such key being created. Any
124 /// intermediate non-existent nodes of the traversal will be created as dynamic
125 /// inner nodes as well.
126 class dynamic_inner_node : public config::detail::inner_node {
128 virtual base_node* deep_copy(void) const;
130 dynamic_inner_node(void);
134 } // namespace detail
135 } // namespace config
138 /// Constructor for a node with an undefined value.
140 /// This should only be called by the tree's define() method as a way to
141 /// register a node as known but undefined. The node will then serve as a
142 /// placeholder for future values.
143 template< typename ValueType >
144 config::typed_leaf_node< ValueType >::typed_leaf_node(void) :
150 /// Checks whether the node has been set.
152 /// Remember that a node can exist before holding a value (i.e. when the node
153 /// has been defined as "known" but not yet set by the user). This function
154 /// checks whether the node laready holds a value.
156 /// \return True if a value has been set in the node.
157 template< typename ValueType >
159 config::typed_leaf_node< ValueType >::is_set(void) const
161 return static_cast< bool >(_value);
165 /// Gets the value stored in the node.
167 /// \pre The node must have a value.
169 /// \return The value in the node.
170 template< typename ValueType >
171 const typename config::typed_leaf_node< ValueType >::value_type&
172 config::typed_leaf_node< ValueType >::value(void) const
179 /// Gets the read-write value stored in the node.
181 /// \pre The node must have a value.
183 /// \return The value in the node.
184 template< typename ValueType >
185 typename config::typed_leaf_node< ValueType >::value_type&
186 config::typed_leaf_node< ValueType >::value(void)
193 /// Sets the value of the node.
195 /// \param value_ The new value to set the node to.
197 /// \throw value_error If the value is invalid, according to validate().
198 template< typename ValueType >
200 config::typed_leaf_node< ValueType >::set(const value_type& value_)
203 _value = optional< value_type >(value_);
207 /// Checks a given value for validity.
209 /// This is called internally by the node right before updating the recorded
210 /// value. This method can be redefined by subclasses.
212 /// \param unused_new_value The value to validate.
214 /// \throw value_error If the value is not valid.
215 template< typename ValueType >
217 config::typed_leaf_node< ValueType >::validate(
218 const value_type& UTILS_UNUSED_PARAM(new_value)) const
223 /// Sets the value of the node from a raw string representation.
225 /// \param raw_value The value to set the node to.
227 /// \throw value_error If the value is invalid.
228 template< typename ValueType >
230 config::native_leaf_node< ValueType >::set_string(const std::string& raw_value)
233 typed_leaf_node< ValueType >::set(text::to_type< ValueType >(
235 } catch (const text::value_error& e) {
236 throw config::value_error(F("Failed to convert string value '%s' to "
237 "the node's type") % raw_value);
242 /// Converts the contents of the node to a string.
244 /// \pre The node must have a value.
246 /// \return A string representation of the value held by the node.
247 template< typename ValueType >
249 config::native_leaf_node< ValueType >::to_string(void) const
251 PRE(typed_leaf_node< ValueType >::is_set());
252 return F("%s") % typed_leaf_node< ValueType >::value();
256 /// Constructor for a node with an undefined value.
258 /// This should only be called by the tree's define() method as a way to
259 /// register a node as known but undefined. The node will then serve as a
260 /// placeholder for future values.
261 template< typename ValueType >
262 config::base_set_node< ValueType >::base_set_node(void) :
268 /// Checks whether the node has been set.
270 /// Remember that a node can exist before holding a value (i.e. when the node
271 /// has been defined as "known" but not yet set by the user). This function
272 /// checks whether the node laready holds a value.
274 /// \return True if a value has been set in the node.
275 template< typename ValueType >
277 config::base_set_node< ValueType >::is_set(void) const
279 return static_cast< bool >(_value);
283 /// Gets the value stored in the node.
285 /// \pre The node must have a value.
287 /// \return The value in the node.
288 template< typename ValueType >
289 const typename config::base_set_node< ValueType >::value_type&
290 config::base_set_node< ValueType >::value(void) const
297 /// Gets the read-write value stored in the node.
299 /// \pre The node must have a value.
301 /// \return The value in the node.
302 template< typename ValueType >
303 typename config::base_set_node< ValueType >::value_type&
304 config::base_set_node< ValueType >::value(void)
311 /// Sets the value of the node.
313 /// \param value_ The new value to set the node to.
315 /// \throw value_error If the value is invalid, according to validate().
316 template< typename ValueType >
318 config::base_set_node< ValueType >::set(const value_type& value_)
321 _value = optional< value_type >(value_);
325 /// Sets the value of the node from a raw string representation.
327 /// \param raw_value The value to set the node to.
329 /// \throw value_error If the value is invalid.
330 template< typename ValueType >
332 config::base_set_node< ValueType >::set_string(const std::string& raw_value)
334 std::set< ValueType > new_value;
336 const std::vector< std::string > words = text::split(raw_value, ' ');
337 for (std::vector< std::string >::const_iterator iter = words.begin();
338 iter != words.end(); ++iter) {
339 if (!(*iter).empty())
340 new_value.insert(parse_one(*iter));
347 /// Converts the contents of the node to a string.
349 /// \pre The node must have a value.
351 /// \return A string representation of the value held by the node.
352 template< typename ValueType >
354 config::base_set_node< ValueType >::to_string(void) const
357 return text::join(_value.get(), " ");
361 /// Pushes the node's value onto the Lua stack.
363 /// \param unused_state The Lua state onto which to push the value.
364 template< typename ValueType >
366 config::base_set_node< ValueType >::push_lua(
367 lutok::state& UTILS_UNUSED_PARAM(state)) const
373 /// Sets the value of the node from an entry in the Lua stack.
375 /// \param unused_state The Lua state from which to get the value.
376 /// \param unused_value_index The stack index in which the value resides.
378 /// \throw value_error If the value in state(value_index) cannot be
379 /// processed by this node.
380 template< typename ValueType >
382 config::base_set_node< ValueType >::set_lua(
383 lutok::state& UTILS_UNUSED_PARAM(state),
384 const int UTILS_UNUSED_PARAM(value_index))
390 /// Checks a given value for validity.
392 /// This is called internally by the node right before updating the recorded
393 /// value. This method can be redefined by subclasses.
395 /// \param unused_new_value The value to validate.
397 /// \throw value_error If the value is not valid.
398 template< typename ValueType >
400 config::base_set_node< ValueType >::validate(
401 const value_type& UTILS_UNUSED_PARAM(new_value)) const
408 #endif // !defined(UTILS_CONFIG_NODES_IPP)