xref: /minix3/external/bsd/kyua-cli/dist/utils/config/nodes.cpp (revision 11be35a165022172ed3cea20f2b5df0307540b0e)
1*11be35a1SLionel Sambuc // Copyright 2012 Google Inc.
2*11be35a1SLionel Sambuc // All rights reserved.
3*11be35a1SLionel Sambuc //
4*11be35a1SLionel Sambuc // Redistribution and use in source and binary forms, with or without
5*11be35a1SLionel Sambuc // modification, are permitted provided that the following conditions are
6*11be35a1SLionel Sambuc // met:
7*11be35a1SLionel Sambuc //
8*11be35a1SLionel Sambuc // * Redistributions of source code must retain the above copyright
9*11be35a1SLionel Sambuc //   notice, this list of conditions and the following disclaimer.
10*11be35a1SLionel Sambuc // * Redistributions in binary form must reproduce the above copyright
11*11be35a1SLionel Sambuc //   notice, this list of conditions and the following disclaimer in the
12*11be35a1SLionel Sambuc //   documentation and/or other materials provided with the distribution.
13*11be35a1SLionel Sambuc // * Neither the name of Google Inc. nor the names of its contributors
14*11be35a1SLionel Sambuc //   may be used to endorse or promote products derived from this software
15*11be35a1SLionel Sambuc //   without specific prior written permission.
16*11be35a1SLionel Sambuc //
17*11be35a1SLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*11be35a1SLionel Sambuc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*11be35a1SLionel Sambuc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*11be35a1SLionel Sambuc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*11be35a1SLionel Sambuc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*11be35a1SLionel Sambuc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*11be35a1SLionel Sambuc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*11be35a1SLionel Sambuc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*11be35a1SLionel Sambuc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*11be35a1SLionel Sambuc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*11be35a1SLionel Sambuc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc 
29*11be35a1SLionel Sambuc #include "utils/config/nodes.ipp"
30*11be35a1SLionel Sambuc 
31*11be35a1SLionel Sambuc #include <memory>
32*11be35a1SLionel Sambuc 
33*11be35a1SLionel Sambuc #include <lutok/state.ipp>
34*11be35a1SLionel Sambuc 
35*11be35a1SLionel Sambuc #include "utils/config/exceptions.hpp"
36*11be35a1SLionel Sambuc #include "utils/config/keys.hpp"
37*11be35a1SLionel Sambuc #include "utils/format/macros.hpp"
38*11be35a1SLionel Sambuc 
39*11be35a1SLionel Sambuc namespace config = utils::config;
40*11be35a1SLionel Sambuc 
41*11be35a1SLionel Sambuc 
42*11be35a1SLionel Sambuc /// Destructor.
~base_node(void)43*11be35a1SLionel Sambuc config::detail::base_node::~base_node(void)
44*11be35a1SLionel Sambuc {
45*11be35a1SLionel Sambuc }
46*11be35a1SLionel Sambuc 
47*11be35a1SLionel Sambuc 
48*11be35a1SLionel Sambuc /// Constructor.
49*11be35a1SLionel Sambuc ///
50*11be35a1SLionel Sambuc /// \param dynamic_ Whether the node is dynamic or not.
inner_node(const bool dynamic_)51*11be35a1SLionel Sambuc config::detail::inner_node::inner_node(const bool dynamic_) :
52*11be35a1SLionel Sambuc     _dynamic(dynamic_)
53*11be35a1SLionel Sambuc {
54*11be35a1SLionel Sambuc }
55*11be35a1SLionel Sambuc 
56*11be35a1SLionel Sambuc 
57*11be35a1SLionel Sambuc /// Destructor.
~inner_node(void)58*11be35a1SLionel Sambuc config::detail::inner_node::~inner_node(void)
59*11be35a1SLionel Sambuc {
60*11be35a1SLionel Sambuc     for (children_map::const_iterator iter = _children.begin();
61*11be35a1SLionel Sambuc          iter != _children.end(); ++iter)
62*11be35a1SLionel Sambuc         delete (*iter).second;
63*11be35a1SLionel Sambuc }
64*11be35a1SLionel Sambuc 
65*11be35a1SLionel Sambuc 
66*11be35a1SLionel Sambuc /// Fills the given node with a copy of this node's data.
67*11be35a1SLionel Sambuc ///
68*11be35a1SLionel Sambuc /// \param node The node to fill.  Should be the fresh return value of a
69*11be35a1SLionel Sambuc ///     deep_copy() operation.
70*11be35a1SLionel Sambuc void
copy_into(inner_node * node) const71*11be35a1SLionel Sambuc config::detail::inner_node::copy_into(inner_node* node) const
72*11be35a1SLionel Sambuc {
73*11be35a1SLionel Sambuc     node->_dynamic = _dynamic;
74*11be35a1SLionel Sambuc     for (children_map::const_iterator iter = _children.begin();
75*11be35a1SLionel Sambuc          iter != _children.end(); ++iter) {
76*11be35a1SLionel Sambuc         base_node* new_node = (*iter).second->deep_copy();
77*11be35a1SLionel Sambuc         try {
78*11be35a1SLionel Sambuc             node->_children[(*iter).first] = new_node;
79*11be35a1SLionel Sambuc         } catch (...) {
80*11be35a1SLionel Sambuc             delete new_node;
81*11be35a1SLionel Sambuc             throw;
82*11be35a1SLionel Sambuc         }
83*11be35a1SLionel Sambuc     }
84*11be35a1SLionel Sambuc }
85*11be35a1SLionel Sambuc 
86*11be35a1SLionel Sambuc 
87*11be35a1SLionel Sambuc /// Finds a node without creating it if not found.
88*11be35a1SLionel Sambuc ///
89*11be35a1SLionel Sambuc /// This recursive algorithm traverses the tree searching for a particular key.
90*11be35a1SLionel Sambuc /// The returned node is constant, so this can only be used for querying
91*11be35a1SLionel Sambuc /// purposes.  For this reason, this algorithm does not create intermediate
92*11be35a1SLionel Sambuc /// nodes if they don't exist (as would be necessary to set a new node).
93*11be35a1SLionel Sambuc ///
94*11be35a1SLionel Sambuc /// \param key The key to be queried.
95*11be35a1SLionel Sambuc /// \param key_pos The current level within the key to be examined.
96*11be35a1SLionel Sambuc ///
97*11be35a1SLionel Sambuc /// \return A reference to the located node, if successful.
98*11be35a1SLionel Sambuc ///
99*11be35a1SLionel Sambuc /// \throw unknown_key_error If the provided key is unknown.
100*11be35a1SLionel Sambuc const config::detail::base_node*
lookup_ro(const tree_key & key,const tree_key::size_type key_pos) const101*11be35a1SLionel Sambuc config::detail::inner_node::lookup_ro(const tree_key& key,
102*11be35a1SLionel Sambuc                                       const tree_key::size_type key_pos) const
103*11be35a1SLionel Sambuc {
104*11be35a1SLionel Sambuc     PRE(key_pos < key.size());
105*11be35a1SLionel Sambuc 
106*11be35a1SLionel Sambuc     const children_map::const_iterator child_iter = _children.find(
107*11be35a1SLionel Sambuc         key[key_pos]);
108*11be35a1SLionel Sambuc     if (child_iter == _children.end())
109*11be35a1SLionel Sambuc         throw unknown_key_error(key);
110*11be35a1SLionel Sambuc 
111*11be35a1SLionel Sambuc     if (key_pos == key.size() - 1) {
112*11be35a1SLionel Sambuc         return (*child_iter).second;
113*11be35a1SLionel Sambuc     } else {
114*11be35a1SLionel Sambuc         PRE(key_pos < key.size() - 1);
115*11be35a1SLionel Sambuc         try {
116*11be35a1SLionel Sambuc             const inner_node& child = dynamic_cast< const inner_node& >(
117*11be35a1SLionel Sambuc                 *(*child_iter).second);
118*11be35a1SLionel Sambuc             return child.lookup_ro(key, key_pos + 1);
119*11be35a1SLionel Sambuc         } catch (const std::bad_cast& e) {
120*11be35a1SLionel Sambuc             throw unknown_key_error(
121*11be35a1SLionel Sambuc                 key, "Cannot address incomplete configuration property '%s'");
122*11be35a1SLionel Sambuc         }
123*11be35a1SLionel Sambuc     }
124*11be35a1SLionel Sambuc }
125*11be35a1SLionel Sambuc 
126*11be35a1SLionel Sambuc 
127*11be35a1SLionel Sambuc /// Finds a node and creates it if not found.
128*11be35a1SLionel Sambuc ///
129*11be35a1SLionel Sambuc /// This recursive algorithm traverses the tree searching for a particular key,
130*11be35a1SLionel Sambuc /// creating any intermediate nodes if they do not already exist (for the case
131*11be35a1SLionel Sambuc /// of dynamic inner nodes).  The returned node is non-constant, so this can be
132*11be35a1SLionel Sambuc /// used by the algorithms that set key values.
133*11be35a1SLionel Sambuc ///
134*11be35a1SLionel Sambuc /// \param key The key to be queried.
135*11be35a1SLionel Sambuc /// \param key_pos The current level within the key to be examined.
136*11be35a1SLionel Sambuc /// \param new_node A function that returns a new leaf node of the desired
137*11be35a1SLionel Sambuc ///     type.  This is only called if the leaf cannot be found, but it has
138*11be35a1SLionel Sambuc ///     already been defined.
139*11be35a1SLionel Sambuc ///
140*11be35a1SLionel Sambuc /// \return A reference to the located node, if successful.
141*11be35a1SLionel Sambuc ///
142*11be35a1SLionel Sambuc /// \throw unknown_key_error If the provided key is unknown.
143*11be35a1SLionel Sambuc /// \throw value_error If the resulting node of the search would be an inner
144*11be35a1SLionel Sambuc ///     node.
145*11be35a1SLionel Sambuc config::leaf_node*
lookup_rw(const tree_key & key,const tree_key::size_type key_pos,new_node_hook new_node)146*11be35a1SLionel Sambuc config::detail::inner_node::lookup_rw(const tree_key& key,
147*11be35a1SLionel Sambuc                                       const tree_key::size_type key_pos,
148*11be35a1SLionel Sambuc                                       new_node_hook new_node)
149*11be35a1SLionel Sambuc {
150*11be35a1SLionel Sambuc     PRE(key_pos < key.size());
151*11be35a1SLionel Sambuc 
152*11be35a1SLionel Sambuc     children_map::const_iterator child_iter = _children.find(key[key_pos]);
153*11be35a1SLionel Sambuc     if (child_iter == _children.end()) {
154*11be35a1SLionel Sambuc         if (_dynamic) {
155*11be35a1SLionel Sambuc             base_node* const child = (key_pos == key.size() - 1) ?
156*11be35a1SLionel Sambuc                 static_cast< base_node* >(new_node()) :
157*11be35a1SLionel Sambuc                 static_cast< base_node* >(new dynamic_inner_node());
158*11be35a1SLionel Sambuc             _children.insert(children_map::value_type(key[key_pos], child));
159*11be35a1SLionel Sambuc             child_iter = _children.find(key[key_pos]);
160*11be35a1SLionel Sambuc         } else {
161*11be35a1SLionel Sambuc             throw unknown_key_error(key);
162*11be35a1SLionel Sambuc         }
163*11be35a1SLionel Sambuc     }
164*11be35a1SLionel Sambuc 
165*11be35a1SLionel Sambuc     if (key_pos == key.size() - 1) {
166*11be35a1SLionel Sambuc         try {
167*11be35a1SLionel Sambuc             leaf_node& child = dynamic_cast< leaf_node& >(
168*11be35a1SLionel Sambuc                 *(*child_iter).second);
169*11be35a1SLionel Sambuc             return &child;
170*11be35a1SLionel Sambuc         } catch (const std::bad_cast& unused_error) {
171*11be35a1SLionel Sambuc             throw value_error(F("Invalid value for key '%s'") %
172*11be35a1SLionel Sambuc                               flatten_key(key));
173*11be35a1SLionel Sambuc         }
174*11be35a1SLionel Sambuc     } else {
175*11be35a1SLionel Sambuc         PRE(key_pos < key.size() - 1);
176*11be35a1SLionel Sambuc         try {
177*11be35a1SLionel Sambuc             inner_node& child = dynamic_cast< inner_node& >(
178*11be35a1SLionel Sambuc                 *(*child_iter).second);
179*11be35a1SLionel Sambuc             return child.lookup_rw(key, key_pos + 1, new_node);
180*11be35a1SLionel Sambuc         } catch (const std::bad_cast& e) {
181*11be35a1SLionel Sambuc             throw unknown_key_error(
182*11be35a1SLionel Sambuc                 key, "Cannot address incomplete configuration property '%s'");
183*11be35a1SLionel Sambuc         }
184*11be35a1SLionel Sambuc     }
185*11be35a1SLionel Sambuc }
186*11be35a1SLionel Sambuc 
187*11be35a1SLionel Sambuc 
188*11be35a1SLionel Sambuc /// Converts the subtree to a collection of key/value string pairs.
189*11be35a1SLionel Sambuc ///
190*11be35a1SLionel Sambuc /// \param [out] properties The accumulator for the generated properties.  The
191*11be35a1SLionel Sambuc ///     contents of the map are only extended.
192*11be35a1SLionel Sambuc /// \param key The path to the current node.
193*11be35a1SLionel Sambuc void
all_properties(properties_map & properties,const tree_key & key) const194*11be35a1SLionel Sambuc config::detail::inner_node::all_properties(properties_map& properties,
195*11be35a1SLionel Sambuc                                            const tree_key& key) const
196*11be35a1SLionel Sambuc {
197*11be35a1SLionel Sambuc     for (children_map::const_iterator iter = _children.begin();
198*11be35a1SLionel Sambuc          iter != _children.end(); ++iter) {
199*11be35a1SLionel Sambuc         tree_key child_key = key;
200*11be35a1SLionel Sambuc         child_key.push_back((*iter).first);
201*11be35a1SLionel Sambuc         try {
202*11be35a1SLionel Sambuc             leaf_node& child = dynamic_cast< leaf_node& >(*(*iter).second);
203*11be35a1SLionel Sambuc             if (child.is_set())
204*11be35a1SLionel Sambuc                 properties[flatten_key(child_key)] = child.to_string();
205*11be35a1SLionel Sambuc         } catch (const std::bad_cast& unused_error) {
206*11be35a1SLionel Sambuc             inner_node& child = dynamic_cast< inner_node& >(*(*iter).second);
207*11be35a1SLionel Sambuc             child.all_properties(properties, child_key);
208*11be35a1SLionel Sambuc         }
209*11be35a1SLionel Sambuc     }
210*11be35a1SLionel Sambuc }
211*11be35a1SLionel Sambuc 
212*11be35a1SLionel Sambuc 
213*11be35a1SLionel Sambuc /// Constructor.
static_inner_node(void)214*11be35a1SLionel Sambuc config::detail::static_inner_node::static_inner_node(void) :
215*11be35a1SLionel Sambuc     inner_node(false)
216*11be35a1SLionel Sambuc {
217*11be35a1SLionel Sambuc }
218*11be35a1SLionel Sambuc 
219*11be35a1SLionel Sambuc 
220*11be35a1SLionel Sambuc /// Copies the node.
221*11be35a1SLionel Sambuc ///
222*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
223*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const224*11be35a1SLionel Sambuc config::detail::static_inner_node::deep_copy(void) const
225*11be35a1SLionel Sambuc {
226*11be35a1SLionel Sambuc     std::auto_ptr< inner_node > new_node(new static_inner_node());
227*11be35a1SLionel Sambuc     copy_into(new_node.get());
228*11be35a1SLionel Sambuc     return new_node.release();
229*11be35a1SLionel Sambuc }
230*11be35a1SLionel Sambuc 
231*11be35a1SLionel Sambuc 
232*11be35a1SLionel Sambuc /// Registers a key as valid and having a specific type.
233*11be35a1SLionel Sambuc ///
234*11be35a1SLionel Sambuc /// This method does not raise errors on invalid/unknown keys or other
235*11be35a1SLionel Sambuc /// tree-related issues.  The reasons is that define() is a method that does not
236*11be35a1SLionel Sambuc /// depend on user input: it is intended to pre-populate the tree with a
237*11be35a1SLionel Sambuc /// specific structure, and that happens once at coding time.
238*11be35a1SLionel Sambuc ///
239*11be35a1SLionel Sambuc /// \param key The key to be registered.
240*11be35a1SLionel Sambuc /// \param key_pos The current level within the key to be examined.
241*11be35a1SLionel Sambuc /// \param new_node A function that returns a new leaf node of the desired
242*11be35a1SLionel Sambuc ///     type.
243*11be35a1SLionel Sambuc void
define(const tree_key & key,const tree_key::size_type key_pos,new_node_hook new_node)244*11be35a1SLionel Sambuc config::detail::static_inner_node::define(const tree_key& key,
245*11be35a1SLionel Sambuc                                           const tree_key::size_type key_pos,
246*11be35a1SLionel Sambuc                                           new_node_hook new_node)
247*11be35a1SLionel Sambuc {
248*11be35a1SLionel Sambuc     PRE(key_pos < key.size());
249*11be35a1SLionel Sambuc 
250*11be35a1SLionel Sambuc     if (key_pos == key.size() - 1) {
251*11be35a1SLionel Sambuc         PRE_MSG(_children.find(key[key_pos]) == _children.end(),
252*11be35a1SLionel Sambuc                 "Key already defined");
253*11be35a1SLionel Sambuc         _children.insert(children_map::value_type(key[key_pos], new_node()));
254*11be35a1SLionel Sambuc     } else {
255*11be35a1SLionel Sambuc         PRE(key_pos < key.size() - 1);
256*11be35a1SLionel Sambuc         const children_map::const_iterator child_iter = _children.find(
257*11be35a1SLionel Sambuc             key[key_pos]);
258*11be35a1SLionel Sambuc 
259*11be35a1SLionel Sambuc         if (child_iter == _children.end()) {
260*11be35a1SLionel Sambuc             static_inner_node* const child_ptr = new static_inner_node();
261*11be35a1SLionel Sambuc             _children.insert(children_map::value_type(key[key_pos], child_ptr));
262*11be35a1SLionel Sambuc             child_ptr->define(key, key_pos + 1, new_node);
263*11be35a1SLionel Sambuc         } else {
264*11be35a1SLionel Sambuc             try {
265*11be35a1SLionel Sambuc                 static_inner_node& child = dynamic_cast< static_inner_node& >(
266*11be35a1SLionel Sambuc                     *(*child_iter).second);
267*11be35a1SLionel Sambuc                 child.define(key, key_pos + 1, new_node);
268*11be35a1SLionel Sambuc             } catch (const std::bad_cast& e) {
269*11be35a1SLionel Sambuc                 UNREACHABLE;
270*11be35a1SLionel Sambuc             }
271*11be35a1SLionel Sambuc         }
272*11be35a1SLionel Sambuc     }
273*11be35a1SLionel Sambuc }
274*11be35a1SLionel Sambuc 
275*11be35a1SLionel Sambuc 
276*11be35a1SLionel Sambuc /// Constructor.
dynamic_inner_node(void)277*11be35a1SLionel Sambuc config::detail::dynamic_inner_node::dynamic_inner_node(void) :
278*11be35a1SLionel Sambuc     inner_node(true)
279*11be35a1SLionel Sambuc {
280*11be35a1SLionel Sambuc }
281*11be35a1SLionel Sambuc 
282*11be35a1SLionel Sambuc 
283*11be35a1SLionel Sambuc /// Copies the node.
284*11be35a1SLionel Sambuc ///
285*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
286*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const287*11be35a1SLionel Sambuc config::detail::dynamic_inner_node::deep_copy(void) const
288*11be35a1SLionel Sambuc {
289*11be35a1SLionel Sambuc     std::auto_ptr< inner_node > new_node(new dynamic_inner_node());
290*11be35a1SLionel Sambuc     copy_into(new_node.get());
291*11be35a1SLionel Sambuc     return new_node.release();
292*11be35a1SLionel Sambuc }
293*11be35a1SLionel Sambuc 
294*11be35a1SLionel Sambuc 
295*11be35a1SLionel Sambuc /// Destructor.
~leaf_node(void)296*11be35a1SLionel Sambuc config::leaf_node::~leaf_node(void)
297*11be35a1SLionel Sambuc {
298*11be35a1SLionel Sambuc }
299*11be35a1SLionel Sambuc 
300*11be35a1SLionel Sambuc 
301*11be35a1SLionel Sambuc /// Copies the node.
302*11be35a1SLionel Sambuc ///
303*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
304*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const305*11be35a1SLionel Sambuc config::bool_node::deep_copy(void) const
306*11be35a1SLionel Sambuc {
307*11be35a1SLionel Sambuc     std::auto_ptr< bool_node > new_node(new bool_node());
308*11be35a1SLionel Sambuc     new_node->_value = _value;
309*11be35a1SLionel Sambuc     return new_node.release();
310*11be35a1SLionel Sambuc }
311*11be35a1SLionel Sambuc 
312*11be35a1SLionel Sambuc 
313*11be35a1SLionel Sambuc /// Pushes the node's value onto the Lua stack.
314*11be35a1SLionel Sambuc ///
315*11be35a1SLionel Sambuc /// \param state The Lua state onto which to push the value.
316*11be35a1SLionel Sambuc void
push_lua(lutok::state & state) const317*11be35a1SLionel Sambuc config::bool_node::push_lua(lutok::state& state) const
318*11be35a1SLionel Sambuc {
319*11be35a1SLionel Sambuc     state.push_boolean(value());
320*11be35a1SLionel Sambuc }
321*11be35a1SLionel Sambuc 
322*11be35a1SLionel Sambuc 
323*11be35a1SLionel Sambuc /// Sets the value of the node from an entry in the Lua stack.
324*11be35a1SLionel Sambuc ///
325*11be35a1SLionel Sambuc /// \param state The Lua state from which to get the value.
326*11be35a1SLionel Sambuc /// \param value_index The stack index in which the value resides.
327*11be35a1SLionel Sambuc ///
328*11be35a1SLionel Sambuc /// \throw value_error If the value in state(value_index) cannot be
329*11be35a1SLionel Sambuc ///     processed by this node.
330*11be35a1SLionel Sambuc void
set_lua(lutok::state & state,const int value_index)331*11be35a1SLionel Sambuc config::bool_node::set_lua(lutok::state& state, const int value_index)
332*11be35a1SLionel Sambuc {
333*11be35a1SLionel Sambuc     if (state.is_boolean(value_index))
334*11be35a1SLionel Sambuc         set(state.to_boolean(value_index));
335*11be35a1SLionel Sambuc     else
336*11be35a1SLionel Sambuc         throw value_error("Not a boolean");
337*11be35a1SLionel Sambuc }
338*11be35a1SLionel Sambuc 
339*11be35a1SLionel Sambuc 
340*11be35a1SLionel Sambuc /// Copies the node.
341*11be35a1SLionel Sambuc ///
342*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
343*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const344*11be35a1SLionel Sambuc config::int_node::deep_copy(void) const
345*11be35a1SLionel Sambuc {
346*11be35a1SLionel Sambuc     std::auto_ptr< int_node > new_node(new int_node());
347*11be35a1SLionel Sambuc     new_node->_value = _value;
348*11be35a1SLionel Sambuc     return new_node.release();
349*11be35a1SLionel Sambuc }
350*11be35a1SLionel Sambuc 
351*11be35a1SLionel Sambuc 
352*11be35a1SLionel Sambuc /// Pushes the node's value onto the Lua stack.
353*11be35a1SLionel Sambuc ///
354*11be35a1SLionel Sambuc /// \param state The Lua state onto which to push the value.
355*11be35a1SLionel Sambuc void
push_lua(lutok::state & state) const356*11be35a1SLionel Sambuc config::int_node::push_lua(lutok::state& state) const
357*11be35a1SLionel Sambuc {
358*11be35a1SLionel Sambuc     state.push_integer(value());
359*11be35a1SLionel Sambuc }
360*11be35a1SLionel Sambuc 
361*11be35a1SLionel Sambuc 
362*11be35a1SLionel Sambuc /// Sets the value of the node from an entry in the Lua stack.
363*11be35a1SLionel Sambuc ///
364*11be35a1SLionel Sambuc /// \param state The Lua state from which to get the value.
365*11be35a1SLionel Sambuc /// \param value_index The stack index in which the value resides.
366*11be35a1SLionel Sambuc ///
367*11be35a1SLionel Sambuc /// \throw value_error If the value in state(value_index) cannot be
368*11be35a1SLionel Sambuc ///     processed by this node.
369*11be35a1SLionel Sambuc void
set_lua(lutok::state & state,const int value_index)370*11be35a1SLionel Sambuc config::int_node::set_lua(lutok::state& state, const int value_index)
371*11be35a1SLionel Sambuc {
372*11be35a1SLionel Sambuc     if (state.is_number(value_index))
373*11be35a1SLionel Sambuc         set(state.to_integer(value_index));
374*11be35a1SLionel Sambuc     else
375*11be35a1SLionel Sambuc         throw value_error("Not an integer");
376*11be35a1SLionel Sambuc }
377*11be35a1SLionel Sambuc 
378*11be35a1SLionel Sambuc 
379*11be35a1SLionel Sambuc /// Copies the node.
380*11be35a1SLionel Sambuc ///
381*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
382*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const383*11be35a1SLionel Sambuc config::string_node::deep_copy(void) const
384*11be35a1SLionel Sambuc {
385*11be35a1SLionel Sambuc     std::auto_ptr< string_node > new_node(new string_node());
386*11be35a1SLionel Sambuc     new_node->_value = _value;
387*11be35a1SLionel Sambuc     return new_node.release();
388*11be35a1SLionel Sambuc }
389*11be35a1SLionel Sambuc 
390*11be35a1SLionel Sambuc 
391*11be35a1SLionel Sambuc /// Pushes the node's value onto the Lua stack.
392*11be35a1SLionel Sambuc ///
393*11be35a1SLionel Sambuc /// \param state The Lua state onto which to push the value.
394*11be35a1SLionel Sambuc void
push_lua(lutok::state & state) const395*11be35a1SLionel Sambuc config::string_node::push_lua(lutok::state& state) const
396*11be35a1SLionel Sambuc {
397*11be35a1SLionel Sambuc     state.push_string(value());
398*11be35a1SLionel Sambuc }
399*11be35a1SLionel Sambuc 
400*11be35a1SLionel Sambuc 
401*11be35a1SLionel Sambuc /// Sets the value of the node from an entry in the Lua stack.
402*11be35a1SLionel Sambuc ///
403*11be35a1SLionel Sambuc /// \param state The Lua state from which to get the value.
404*11be35a1SLionel Sambuc /// \param value_index The stack index in which the value resides.
405*11be35a1SLionel Sambuc ///
406*11be35a1SLionel Sambuc /// \throw value_error If the value in state(value_index) cannot be
407*11be35a1SLionel Sambuc ///     processed by this node.
408*11be35a1SLionel Sambuc void
set_lua(lutok::state & state,const int value_index)409*11be35a1SLionel Sambuc config::string_node::set_lua(lutok::state& state, const int value_index)
410*11be35a1SLionel Sambuc {
411*11be35a1SLionel Sambuc     if (state.is_string(value_index))
412*11be35a1SLionel Sambuc         set(state.to_string(value_index));
413*11be35a1SLionel Sambuc     else
414*11be35a1SLionel Sambuc         throw value_error("Not a string");
415*11be35a1SLionel Sambuc }
416*11be35a1SLionel Sambuc 
417*11be35a1SLionel Sambuc 
418*11be35a1SLionel Sambuc /// Copies the node.
419*11be35a1SLionel Sambuc ///
420*11be35a1SLionel Sambuc /// \return A dynamically-allocated node.
421*11be35a1SLionel Sambuc config::detail::base_node*
deep_copy(void) const422*11be35a1SLionel Sambuc config::strings_set_node::deep_copy(void) const
423*11be35a1SLionel Sambuc {
424*11be35a1SLionel Sambuc     std::auto_ptr< strings_set_node > new_node(new strings_set_node());
425*11be35a1SLionel Sambuc     new_node->_value = _value;
426*11be35a1SLionel Sambuc     return new_node.release();
427*11be35a1SLionel Sambuc }
428*11be35a1SLionel Sambuc 
429*11be35a1SLionel Sambuc 
430*11be35a1SLionel Sambuc /// Converts a single word to the native type.
431*11be35a1SLionel Sambuc ///
432*11be35a1SLionel Sambuc /// \param raw_value The value to parse.
433*11be35a1SLionel Sambuc ///
434*11be35a1SLionel Sambuc /// \return The parsed value.
435*11be35a1SLionel Sambuc std::string
parse_one(const std::string & raw_value) const436*11be35a1SLionel Sambuc config::strings_set_node::parse_one(const std::string& raw_value) const
437*11be35a1SLionel Sambuc {
438*11be35a1SLionel Sambuc     return raw_value;
439*11be35a1SLionel Sambuc }
440