1// Copyright 2012 Google Inc. 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#include "utils/config/nodes.hpp" 30 31#if !defined(UTILS_CONFIG_NODES_IPP) 32#define UTILS_CONFIG_NODES_IPP 33 34#include <memory> 35#include <typeinfo> 36 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" 44 45namespace utils { 46 47 48namespace config { 49namespace detail { 50 51 52/// Type of the new_node() family of functions. 53typedef base_node* (*new_node_hook)(void); 54 55 56/// Creates a new leaf node of a given type. 57/// 58/// \tparam NodeType The type of the leaf node to create. 59/// 60/// \return A pointer to the newly-created node. 61template< class NodeType > 62base_node* 63new_node(void) 64{ 65 return new NodeType(); 66} 67 68 69/// Internal node of the tree. 70/// 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. 76class inner_node : public base_node { 77 /// Whether the node is dynamic or not. 78 bool _dynamic; 79 80protected: 81 /// Type to represent the collection of children of this node. 82 /// 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; 86 87 /// Mapping of keys to values that are descendants of this node. 88 children_map _children; 89 90 void copy_into(inner_node* new_node) const; 91 92public: 93 inner_node(const bool); 94 virtual ~inner_node(void) = 0; 95 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, 99 new_node_hook); 100 101 void all_properties(properties_map&, const tree_key&) const; 102}; 103 104 105/// Static internal node of the tree. 106/// 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. 110class static_inner_node : public config::detail::inner_node { 111public: 112 static_inner_node(void); 113 114 virtual base_node* deep_copy(void) const; 115 116 void define(const tree_key&, const tree_key::size_type, new_node_hook); 117}; 118 119 120/// Dynamic internal node of the tree. 121/// 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. 126class dynamic_inner_node : public config::detail::inner_node { 127public: 128 virtual base_node* deep_copy(void) const; 129 130 dynamic_inner_node(void); 131}; 132 133 134} // namespace detail 135} // namespace config 136 137 138/// Constructor for a node with an undefined value. 139/// 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. 143template< typename ValueType > 144config::typed_leaf_node< ValueType >::typed_leaf_node(void) : 145 _value(none) 146{ 147} 148 149 150/// Checks whether the node has been set. 151/// 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. 155/// 156/// \return True if a value has been set in the node. 157template< typename ValueType > 158bool 159config::typed_leaf_node< ValueType >::is_set(void) const 160{ 161 return static_cast< bool >(_value); 162} 163 164 165/// Gets the value stored in the node. 166/// 167/// \pre The node must have a value. 168/// 169/// \return The value in the node. 170template< typename ValueType > 171const typename config::typed_leaf_node< ValueType >::value_type& 172config::typed_leaf_node< ValueType >::value(void) const 173{ 174 PRE(is_set()); 175 return _value.get(); 176} 177 178 179/// Gets the read-write value stored in the node. 180/// 181/// \pre The node must have a value. 182/// 183/// \return The value in the node. 184template< typename ValueType > 185typename config::typed_leaf_node< ValueType >::value_type& 186config::typed_leaf_node< ValueType >::value(void) 187{ 188 PRE(is_set()); 189 return _value.get(); 190} 191 192 193/// Sets the value of the node. 194/// 195/// \param value_ The new value to set the node to. 196/// 197/// \throw value_error If the value is invalid, according to validate(). 198template< typename ValueType > 199void 200config::typed_leaf_node< ValueType >::set(const value_type& value_) 201{ 202 validate(value_); 203 _value = optional< value_type >(value_); 204} 205 206 207/// Checks a given value for validity. 208/// 209/// This is called internally by the node right before updating the recorded 210/// value. This method can be redefined by subclasses. 211/// 212/// \param unused_new_value The value to validate. 213/// 214/// \throw value_error If the value is not valid. 215template< typename ValueType > 216void 217config::typed_leaf_node< ValueType >::validate( 218 const value_type& UTILS_UNUSED_PARAM(new_value)) const 219{ 220} 221 222 223/// Sets the value of the node from a raw string representation. 224/// 225/// \param raw_value The value to set the node to. 226/// 227/// \throw value_error If the value is invalid. 228template< typename ValueType > 229void 230config::native_leaf_node< ValueType >::set_string(const std::string& raw_value) 231{ 232 try { 233 typed_leaf_node< ValueType >::set(text::to_type< ValueType >( 234 raw_value)); 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); 238 } 239} 240 241 242/// Converts the contents of the node to a string. 243/// 244/// \pre The node must have a value. 245/// 246/// \return A string representation of the value held by the node. 247template< typename ValueType > 248std::string 249config::native_leaf_node< ValueType >::to_string(void) const 250{ 251 PRE(typed_leaf_node< ValueType >::is_set()); 252 return F("%s") % typed_leaf_node< ValueType >::value(); 253} 254 255 256/// Constructor for a node with an undefined value. 257/// 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. 261template< typename ValueType > 262config::base_set_node< ValueType >::base_set_node(void) : 263 _value(none) 264{ 265} 266 267 268/// Checks whether the node has been set. 269/// 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. 273/// 274/// \return True if a value has been set in the node. 275template< typename ValueType > 276bool 277config::base_set_node< ValueType >::is_set(void) const 278{ 279 return static_cast< bool >(_value); 280} 281 282 283/// Gets the value stored in the node. 284/// 285/// \pre The node must have a value. 286/// 287/// \return The value in the node. 288template< typename ValueType > 289const typename config::base_set_node< ValueType >::value_type& 290config::base_set_node< ValueType >::value(void) const 291{ 292 PRE(is_set()); 293 return _value.get(); 294} 295 296 297/// Gets the read-write value stored in the node. 298/// 299/// \pre The node must have a value. 300/// 301/// \return The value in the node. 302template< typename ValueType > 303typename config::base_set_node< ValueType >::value_type& 304config::base_set_node< ValueType >::value(void) 305{ 306 PRE(is_set()); 307 return _value.get(); 308} 309 310 311/// Sets the value of the node. 312/// 313/// \param value_ The new value to set the node to. 314/// 315/// \throw value_error If the value is invalid, according to validate(). 316template< typename ValueType > 317void 318config::base_set_node< ValueType >::set(const value_type& value_) 319{ 320 validate(value_); 321 _value = optional< value_type >(value_); 322} 323 324 325/// Sets the value of the node from a raw string representation. 326/// 327/// \param raw_value The value to set the node to. 328/// 329/// \throw value_error If the value is invalid. 330template< typename ValueType > 331void 332config::base_set_node< ValueType >::set_string(const std::string& raw_value) 333{ 334 std::set< ValueType > new_value; 335 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)); 341 } 342 343 set(new_value); 344} 345 346 347/// Converts the contents of the node to a string. 348/// 349/// \pre The node must have a value. 350/// 351/// \return A string representation of the value held by the node. 352template< typename ValueType > 353std::string 354config::base_set_node< ValueType >::to_string(void) const 355{ 356 PRE(is_set()); 357 return text::join(_value.get(), " "); 358} 359 360 361/// Pushes the node's value onto the Lua stack. 362/// 363/// \param unused_state The Lua state onto which to push the value. 364template< typename ValueType > 365void 366config::base_set_node< ValueType >::push_lua( 367 lutok::state& UTILS_UNUSED_PARAM(state)) const 368{ 369 UNREACHABLE; 370} 371 372 373/// Sets the value of the node from an entry in the Lua stack. 374/// 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. 377/// 378/// \throw value_error If the value in state(value_index) cannot be 379/// processed by this node. 380template< typename ValueType > 381void 382config::base_set_node< ValueType >::set_lua( 383 lutok::state& UTILS_UNUSED_PARAM(state), 384 const int UTILS_UNUSED_PARAM(value_index)) 385{ 386 UNREACHABLE; 387} 388 389 390/// Checks a given value for validity. 391/// 392/// This is called internally by the node right before updating the recorded 393/// value. This method can be redefined by subclasses. 394/// 395/// \param unused_new_value The value to validate. 396/// 397/// \throw value_error If the value is not valid. 398template< typename ValueType > 399void 400config::base_set_node< ValueType >::validate( 401 const value_type& UTILS_UNUSED_PARAM(new_value)) const 402{ 403} 404 405 406} // namespace utils 407 408#endif // !defined(UTILS_CONFIG_NODES_IPP) 409