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