Home | History | Annotate | Line # | Download | only in config
      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