1170613Sbms// Copyright 2012 Google Inc.
2189592Sbms// All rights reserved.
3170613Sbms//
4170613Sbms// Redistribution and use in source and binary forms, with or without
5170613Sbms// modification, are permitted provided that the following conditions are
6170613Sbms// met:
7170613Sbms//
8170613Sbms// * Redistributions of source code must retain the above copyright
9170613Sbms//   notice, this list of conditions and the following disclaimer.
10170613Sbms// * Redistributions in binary form must reproduce the above copyright
11170613Sbms//   notice, this list of conditions and the following disclaimer in the
12170613Sbms//   documentation and/or other materials provided with the distribution.
13170613Sbms// * Neither the name of Google Inc. nor the names of its contributors
14170613Sbms//   may be used to endorse or promote products derived from this software
15170613Sbms//   without specific prior written permission.
16170613Sbms//
17170613Sbms// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18170613Sbms// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19170613Sbms// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20170613Sbms// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21170613Sbms// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22170613Sbms// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23170613Sbms// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24170613Sbms// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25170613Sbms// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26170613Sbms// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27170613Sbms// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28170613Sbms
29170613Sbms#include "utils/config/nodes.ipp"
30170613Sbms
31170613Sbms#include <memory>
32170613Sbms
33170613Sbms#include <lutok/state.ipp>
34170613Sbms
35170613Sbms#include "utils/config/exceptions.hpp"
36170613Sbms#include "utils/config/keys.hpp"
37170613Sbms#include "utils/format/macros.hpp"
38170613Sbms
39170613Sbmsnamespace config = utils::config;
40170613Sbms
41170613Sbms
42170613Sbms/// Destructor.
43171746Scsjpconfig::detail::base_node::~base_node(void)
44170613Sbms{
45170613Sbms}
46189592Sbms
47170613Sbms
48189592Sbms/// Constructor.
49228969Sjhb///
50189592Sbms/// \param dynamic_ Whether the node is dynamic or not.
51170613Sbmsconfig::detail::inner_node::inner_node(const bool dynamic_) :
52170613Sbms    _dynamic(dynamic_)
53170613Sbms{
54170613Sbms}
55185571Sbz
56170613Sbms
57170613Sbms/// Destructor.
58170613Sbmsconfig::detail::inner_node::~inner_node(void)
59170613Sbms{
60170613Sbms    for (children_map::const_iterator iter = _children.begin();
61170613Sbms         iter != _children.end(); ++iter)
62170613Sbms        delete (*iter).second;
63170613Sbms}
64189592Sbms
65191659Sbms
66189592Sbms/// Fills the given node with a copy of this node's data.
67189592Sbms///
68170613Sbms/// \param node The node to fill.  Should be the fresh return value of a
69170613Sbms///     deep_copy() operation.
70170613Sbmsvoid
71170613Sbmsconfig::detail::inner_node::copy_into(inner_node* node) const
72170613Sbms{
73170613Sbms    node->_dynamic = _dynamic;
74170613Sbms    for (children_map::const_iterator iter = _children.begin();
75170613Sbms         iter != _children.end(); ++iter) {
76170613Sbms        base_node* new_node = (*iter).second->deep_copy();
77170613Sbms        try {
78170613Sbms            node->_children[(*iter).first] = new_node;
79189592Sbms        } catch (...) {
80189592Sbms            delete new_node;
81170613Sbms            throw;
82170613Sbms        }
83189592Sbms    }
84189592Sbms}
85170613Sbms
86170613Sbms
87189592Sbms/// Finds a node without creating it if not found.
88189592Sbms///
89189592Sbms/// This recursive algorithm traverses the tree searching for a particular key.
90189592Sbms/// The returned node is constant, so this can only be used for querying
91189592Sbms/// purposes.  For this reason, this algorithm does not create intermediate
92189592Sbms/// nodes if they don't exist (as would be necessary to set a new node).
93189592Sbms///
94189592Sbms/// \param key The key to be queried.
95189592Sbms/// \param key_pos The current level within the key to be examined.
96170613Sbms///
97170613Sbms/// \return A reference to the located node, if successful.
98189592Sbms///
99170613Sbms/// \throw unknown_key_error If the provided key is unknown.
100170613Sbmsconst config::detail::base_node*
101170613Sbmsconfig::detail::inner_node::lookup_ro(const tree_key& key,
102170613Sbms                                      const tree_key::size_type key_pos) const
103189592Sbms{
104170613Sbms    PRE(key_pos < key.size());
105170613Sbms
106189592Sbms    const children_map::const_iterator child_iter = _children.find(
107189592Sbms        key[key_pos]);
108189592Sbms    if (child_iter == _children.end())
109189592Sbms        throw unknown_key_error(key);
110170613Sbms
111170613Sbms    if (key_pos == key.size() - 1) {
112170613Sbms        return (*child_iter).second;
113170613Sbms    } else {
114189592Sbms        PRE(key_pos < key.size() - 1);
115189592Sbms        try {
116189592Sbms            const inner_node& child = dynamic_cast< const inner_node& >(
117170613Sbms                *(*child_iter).second);
118189592Sbms            return child.lookup_ro(key, key_pos + 1);
119189592Sbms        } catch (const std::bad_cast& e) {
120189592Sbms            throw unknown_key_error(
121189592Sbms                key, "Cannot address incomplete configuration property '%s'");
122189592Sbms        }
123189592Sbms    }
124189592Sbms}
125189592Sbms
126189592Sbms
127189592Sbms/// Finds a node and creates it if not found.
128189592Sbms///
129189592Sbms/// This recursive algorithm traverses the tree searching for a particular key,
130170613Sbms/// creating any intermediate nodes if they do not already exist (for the case
131189592Sbms/// of dynamic inner nodes).  The returned node is non-constant, so this can be
132189592Sbms/// used by the algorithms that set key values.
133189592Sbms///
134189592Sbms/// \param key The key to be queried.
135189592Sbms/// \param key_pos The current level within the key to be examined.
136189592Sbms/// \param new_node A function that returns a new leaf node of the desired
137189592Sbms///     type.  This is only called if the leaf cannot be found, but it has
138189592Sbms///     already been defined.
139189592Sbms///
140189592Sbms/// \return A reference to the located node, if successful.
141189592Sbms///
142259982Sdim/// \throw unknown_key_error If the provided key is unknown.
143189592Sbms/// \throw value_error If the resulting node of the search would be an inner
144259982Sdim///     node.
145189592Sbmsconfig::leaf_node*
146189592Sbmsconfig::detail::inner_node::lookup_rw(const tree_key& key,
147189592Sbms                                      const tree_key::size_type key_pos,
148170613Sbms                                      new_node_hook new_node)
149170613Sbms{
150228969Sjhb    PRE(key_pos < key.size());
151228969Sjhb
152170613Sbms    children_map::const_iterator child_iter = _children.find(key[key_pos]);
153170613Sbms    if (child_iter == _children.end()) {
154170613Sbms        if (_dynamic) {
155189592Sbms            base_node* const child = (key_pos == key.size() - 1) ?
156189592Sbms                static_cast< base_node* >(new_node()) :
157189592Sbms                static_cast< base_node* >(new dynamic_inner_node());
158189592Sbms            _children.insert(children_map::value_type(key[key_pos], child));
159170613Sbms            child_iter = _children.find(key[key_pos]);
160170613Sbms        } else {
161189592Sbms            throw unknown_key_error(key);
162170613Sbms        }
163227309Sed    }
164227309Sed
165189357Sbms    if (key_pos == key.size() - 1) {
166189592Sbms        try {
167189592Sbms            leaf_node& child = dynamic_cast< leaf_node& >(
168189592Sbms                *(*child_iter).second);
169189592Sbms            return &child;
170189592Sbms        } catch (const std::bad_cast& unused_error) {
171189592Sbms            throw value_error(F("Invalid value for key '%s'") %
172189592Sbms                              flatten_key(key));
173189592Sbms        }
174189592Sbms    } else {
175189592Sbms        PRE(key_pos < key.size() - 1);
176189592Sbms        try {
177189592Sbms            inner_node& child = dynamic_cast< inner_node& >(
178189357Sbms                *(*child_iter).second);
179189357Sbms            return child.lookup_rw(key, key_pos + 1, new_node);
180189357Sbms        } catch (const std::bad_cast& e) {
181189357Sbms            throw unknown_key_error(
182189357Sbms                key, "Cannot address incomplete configuration property '%s'");
183227309Sed        }
184189592Sbms    }
185189592Sbms}
186189592Sbms
187228969Sjhb
188228969Sjhb/// Converts the subtree to a collection of key/value string pairs.
189228969Sjhb///
190228969Sjhb/// \param [out] properties The accumulator for the generated properties.  The
191259982Sdim///     contents of the map are only extended.
192170613Sbms/// \param key The path to the current node.
193189592Sbmsvoid
194189592Sbmsconfig::detail::inner_node::all_properties(properties_map& properties,
195189592Sbms                                           const tree_key& key) const
196189592Sbms{
197189592Sbms    for (children_map::const_iterator iter = _children.begin();
198189592Sbms         iter != _children.end(); ++iter) {
199189592Sbms        tree_key child_key = key;
200189592Sbms        child_key.push_back((*iter).first);
201189592Sbms        try {
202189592Sbms            leaf_node& child = dynamic_cast< leaf_node& >(*(*iter).second);
203189592Sbms            if (child.is_set())
204189592Sbms                properties[flatten_key(child_key)] = child.to_string();
205189592Sbms        } catch (const std::bad_cast& unused_error) {
206189592Sbms            inner_node& child = dynamic_cast< inner_node& >(*(*iter).second);
207189592Sbms            child.all_properties(properties, child_key);
208189592Sbms        }
209189592Sbms    }
210189592Sbms}
211189592Sbms
212189592Sbms
213189592Sbms/// Constructor.
214259982Sdimconfig::detail::static_inner_node::static_inner_node(void) :
215189592Sbms    inner_node(false)
216189592Sbms{
217189592Sbms}
218189592Sbms
219189592Sbms
220189592Sbms/// Copies the node.
221189592Sbms///
222189592Sbms/// \return A dynamically-allocated node.
223189592Sbmsconfig::detail::base_node*
224189592Sbmsconfig::detail::static_inner_node::deep_copy(void) const
225189592Sbms{
226189592Sbms    std::unique_ptr< inner_node > new_node(new static_inner_node());
227189592Sbms    copy_into(new_node.get());
228189592Sbms    return new_node.release();
229189592Sbms}
230170613Sbms
231170613Sbms
232170613Sbms/// Registers a key as valid and having a specific type.
233170613Sbms///
234170613Sbms/// This method does not raise errors on invalid/unknown keys or other
235170613Sbms/// tree-related issues.  The reasons is that define() is a method that does not
236170613Sbms/// depend on user input: it is intended to pre-populate the tree with a
237170613Sbms/// specific structure, and that happens once at coding time.
238170613Sbms///
239170613Sbms/// \param key The key to be registered.
240170613Sbms/// \param key_pos The current level within the key to be examined.
241170613Sbms/// \param new_node A function that returns a new leaf node of the desired
242170613Sbms///     type.
243170613Sbmsvoid
244170613Sbmsconfig::detail::static_inner_node::define(const tree_key& key,
245170613Sbms                                          const tree_key::size_type key_pos,
246170613Sbms                                          new_node_hook new_node)
247170613Sbms{
248170613Sbms    PRE(key_pos < key.size());
249170613Sbms
250170613Sbms    if (key_pos == key.size() - 1) {
251170613Sbms        PRE_MSG(_children.find(key[key_pos]) == _children.end(),
252170613Sbms                "Key already defined");
253170613Sbms        _children.insert(children_map::value_type(key[key_pos], new_node()));
254170613Sbms    } else {
255189592Sbms        PRE(key_pos < key.size() - 1);
256170613Sbms        const children_map::const_iterator child_iter = _children.find(
257170613Sbms            key[key_pos]);
258170613Sbms
259189592Sbms        if (child_iter == _children.end()) {
260189592Sbms            static_inner_node* const child_ptr = new static_inner_node();
261170613Sbms            _children.insert(children_map::value_type(key[key_pos], child_ptr));
262170613Sbms            child_ptr->define(key, key_pos + 1, new_node);
263170613Sbms        } else {
264170613Sbms            try {
265170613Sbms                static_inner_node& child = dynamic_cast< static_inner_node& >(
266170613Sbms                    *(*child_iter).second);
267170613Sbms                child.define(key, key_pos + 1, new_node);
268170613Sbms            } catch (const std::bad_cast& e) {
269170613Sbms                UNREACHABLE;
270170613Sbms            }
271170613Sbms        }
272189592Sbms    }
273170613Sbms}
274170613Sbms
275170613Sbms
276170613Sbms/// Constructor.
277170613Sbmsconfig::detail::dynamic_inner_node::dynamic_inner_node(void) :
278170613Sbms    inner_node(true)
279170613Sbms{
280170613Sbms}
281170613Sbms
282170613Sbms
283170613Sbms/// Copies the node.
284189592Sbms///
285189592Sbms/// \return A dynamically-allocated node.
286189592Sbmsconfig::detail::base_node*
287170613Sbmsconfig::detail::dynamic_inner_node::deep_copy(void) const
288189592Sbms{
289170613Sbms    std::unique_ptr< inner_node > new_node(new dynamic_inner_node());
290170613Sbms    copy_into(new_node.get());
291170613Sbms    return new_node.release();
292170613Sbms}
293189592Sbms
294170613Sbms
295170613Sbms/// Destructor.
296170613Sbmsconfig::leaf_node::~leaf_node(void)
297170613Sbms{
298170613Sbms}
299170613Sbms
300170613Sbms
301170613Sbms/// Copies the node.
302170613Sbms///
303170613Sbms/// \return A dynamically-allocated node.
304170613Sbmsconfig::detail::base_node*
305189592Sbmsconfig::bool_node::deep_copy(void) const
306170613Sbms{
307170613Sbms    std::unique_ptr< bool_node > new_node(new bool_node());
308170613Sbms    new_node->_value = _value;
309170613Sbms    return new_node.release();
310170613Sbms}
311170613Sbms
312170613Sbms
313170613Sbms/// Pushes the node's value onto the Lua stack.
314170613Sbms///
315170613Sbms/// \param state The Lua state onto which to push the value.
316189592Sbmsvoid
317170613Sbmsconfig::bool_node::push_lua(lutok::state& state) const
318189592Sbms{
319189592Sbms    state.push_boolean(value());
320189592Sbms}
321170613Sbms
322189592Sbms
323189592Sbms/// Sets the value of the node from an entry in the Lua stack.
324189592Sbms///
325170613Sbms/// \param state The Lua state from which to get the value.
326189592Sbms/// \param value_index The stack index in which the value resides.
327170613Sbms///
328189592Sbms/// \throw value_error If the value in state(value_index) cannot be
329189592Sbms///     processed by this node.
330170613Sbmsvoid
331170613Sbmsconfig::bool_node::set_lua(lutok::state& state, const int value_index)
332170613Sbms{
333170613Sbms    if (state.is_boolean(value_index))
334170613Sbms        set(state.to_boolean(value_index));
335170613Sbms    else
336170613Sbms        throw value_error("Not a boolean");
337170613Sbms}
338170613Sbms
339170613Sbms
340189592Sbms/// Copies the node.
341189592Sbms///
342189592Sbms/// \return A dynamically-allocated node.
343189592Sbmsconfig::detail::base_node*
344189592Sbmsconfig::int_node::deep_copy(void) const
345189592Sbms{
346170613Sbms    std::unique_ptr< int_node > new_node(new int_node());
347170613Sbms    new_node->_value = _value;
348170613Sbms    return new_node.release();
349189592Sbms}
350189592Sbms
351189592Sbms
352189592Sbms/// Pushes the node's value onto the Lua stack.
353170613Sbms///
354189592Sbms/// \param state The Lua state onto which to push the value.
355189592Sbmsvoid
356189592Sbmsconfig::int_node::push_lua(lutok::state& state) const
357170613Sbms{
358189592Sbms    state.push_integer(value());
359189592Sbms}
360189592Sbms
361189592Sbms
362189592Sbms/// Sets the value of the node from an entry in the Lua stack.
363189592Sbms///
364189592Sbms/// \param state The Lua state from which to get the value.
365189592Sbms/// \param value_index The stack index in which the value resides.
366189592Sbms///
367189592Sbms/// \throw value_error If the value in state(value_index) cannot be
368189592Sbms///     processed by this node.
369189592Sbmsvoid
370189592Sbmsconfig::int_node::set_lua(lutok::state& state, const int value_index)
371189592Sbms{
372189592Sbms    if (state.is_number(value_index))
373189592Sbms        set(state.to_integer(value_index));
374189592Sbms    else
375189592Sbms        throw value_error("Not an integer");
376189592Sbms}
377189592Sbms
378189592Sbms
379189592Sbms/// Copies the node.
380189592Sbms///
381189592Sbms/// \return A dynamically-allocated node.
382189592Sbmsconfig::detail::base_node*
383189592Sbmsconfig::string_node::deep_copy(void) const
384189592Sbms{
385189592Sbms    std::unique_ptr< string_node > new_node(new string_node());
386189592Sbms    new_node->_value = _value;
387189592Sbms    return new_node.release();
388189592Sbms}
389189592Sbms
390189592Sbms
391189592Sbms/// Pushes the node's value onto the Lua stack.
392189592Sbms///
393189592Sbms/// \param state The Lua state onto which to push the value.
394189592Sbmsvoid
395189592Sbmsconfig::string_node::push_lua(lutok::state& state) const
396189592Sbms{
397189592Sbms    state.push_string(value());
398189592Sbms}
399189592Sbms
400189592Sbms
401189592Sbms/// Sets the value of the node from an entry in the Lua stack.
402189592Sbms///
403189592Sbms/// \param state The Lua state from which to get the value.
404170613Sbms/// \param value_index The stack index in which the value resides.
405189592Sbms///
406170613Sbms/// \throw value_error If the value in state(value_index) cannot be
407189592Sbms///     processed by this node.
408170613Sbmsvoid
409189592Sbmsconfig::string_node::set_lua(lutok::state& state, const int value_index)
410170613Sbms{
411170613Sbms    if (state.is_string(value_index))
412170613Sbms        set(state.to_string(value_index));
413170613Sbms    else
414170613Sbms        throw value_error("Not a string");
415170613Sbms}
416170613Sbms
417170613Sbms
418189592Sbms/// Copies the node.
419189592Sbms///
420189592Sbms/// \return A dynamically-allocated node.
421170613Sbmsconfig::detail::base_node*
422189592Sbmsconfig::strings_set_node::deep_copy(void) const
423189592Sbms{
424189592Sbms    std::unique_ptr< strings_set_node > new_node(new strings_set_node());
425189592Sbms    new_node->_value = _value;
426170613Sbms    return new_node.release();
427189592Sbms}
428189592Sbms
429189592Sbms
430189592Sbms/// Converts a single word to the native type.
431189592Sbms///
432189592Sbms/// \param raw_value The value to parse.
433189592Sbms///
434189592Sbms/// \return The parsed value.
435189931Sbmsstd::string
436229621Sjhbconfig::strings_set_node::parse_one(const std::string& raw_value) const
437189931Sbms{
438189592Sbms    return raw_value;
439189592Sbms}
440189592Sbms