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 45 namespace utils { 46 47 48 namespace config { 49 namespace detail { 50 51 52 /// Type of the new_node() family of functions. 53 typedef 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. 61 template< class NodeType > 62 base_node* 63 new_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. 76 class inner_node : public base_node { 77 /// Whether the node is dynamic or not. 78 bool _dynamic; 79 80 protected: 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 92 public: 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. 110 class static_inner_node : public config::detail::inner_node { 111 public: 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. 126 class dynamic_inner_node : public config::detail::inner_node { 127 public: 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. 143 template< typename ValueType > 144 config::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. 157 template< typename ValueType > 158 bool 159 config::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. 170 template< typename ValueType > 171 const typename config::typed_leaf_node< ValueType >::value_type& 172 config::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. 184 template< typename ValueType > 185 typename config::typed_leaf_node< ValueType >::value_type& 186 config::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(). 198 template< typename ValueType > 199 void 200 config::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. 215 template< typename ValueType > 216 void 217 config::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. 228 template< typename ValueType > 229 void 230 config::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. 247 template< typename ValueType > 248 std::string 249 config::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. 261 template< typename ValueType > 262 config::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. 275 template< typename ValueType > 276 bool 277 config::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. 288 template< typename ValueType > 289 const typename config::base_set_node< ValueType >::value_type& 290 config::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. 302 template< typename ValueType > 303 typename config::base_set_node< ValueType >::value_type& 304 config::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(). 316 template< typename ValueType > 317 void 318 config::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. 330 template< typename ValueType > 331 void 332 config::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. 352 template< typename ValueType > 353 std::string 354 config::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. 364 template< typename ValueType > 365 void 366 config::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. 380 template< typename ValueType > 381 void 382 config::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. 398 template< typename ValueType > 399 void 400 config::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