1*b0d29bc4SBrooks Davis // Copyright 2012 The Kyua Authors. 2*b0d29bc4SBrooks Davis // All rights reserved. 3*b0d29bc4SBrooks Davis // 4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without 5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are 6*b0d29bc4SBrooks Davis // met: 7*b0d29bc4SBrooks Davis // 8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright 9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer. 10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright 11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the 12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution. 13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors 14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software 15*b0d29bc4SBrooks Davis // without specific prior written permission. 16*b0d29bc4SBrooks Davis // 17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b0d29bc4SBrooks Davis 29*b0d29bc4SBrooks Davis /// \file utils/config/nodes.hpp 30*b0d29bc4SBrooks Davis /// Representation of tree nodes. 31*b0d29bc4SBrooks Davis 32*b0d29bc4SBrooks Davis #if !defined(UTILS_CONFIG_NODES_HPP) 33*b0d29bc4SBrooks Davis #define UTILS_CONFIG_NODES_HPP 34*b0d29bc4SBrooks Davis 35*b0d29bc4SBrooks Davis #include "utils/config/nodes_fwd.hpp" 36*b0d29bc4SBrooks Davis 37*b0d29bc4SBrooks Davis #include <set> 38*b0d29bc4SBrooks Davis #include <string> 39*b0d29bc4SBrooks Davis 40*b0d29bc4SBrooks Davis #include <lutok/state.hpp> 41*b0d29bc4SBrooks Davis 42*b0d29bc4SBrooks Davis #include "utils/config/keys_fwd.hpp" 43*b0d29bc4SBrooks Davis #include "utils/config/nodes_fwd.hpp" 44*b0d29bc4SBrooks Davis #include "utils/noncopyable.hpp" 45*b0d29bc4SBrooks Davis #include "utils/optional.hpp" 46*b0d29bc4SBrooks Davis 47*b0d29bc4SBrooks Davis namespace utils { 48*b0d29bc4SBrooks Davis namespace config { 49*b0d29bc4SBrooks Davis 50*b0d29bc4SBrooks Davis 51*b0d29bc4SBrooks Davis namespace detail { 52*b0d29bc4SBrooks Davis 53*b0d29bc4SBrooks Davis 54*b0d29bc4SBrooks Davis /// Base representation of a node. 55*b0d29bc4SBrooks Davis /// 56*b0d29bc4SBrooks Davis /// This abstract class provides the base type for every node in the tree. Due 57*b0d29bc4SBrooks Davis /// to the dynamic nature of our trees (each leaf being able to hold arbitrary 58*b0d29bc4SBrooks Davis /// data types), this base type is a necessity. 59*b0d29bc4SBrooks Davis class base_node : noncopyable { 60*b0d29bc4SBrooks Davis public: 61*b0d29bc4SBrooks Davis virtual ~base_node(void) = 0; 62*b0d29bc4SBrooks Davis 63*b0d29bc4SBrooks Davis /// Copies the node. 64*b0d29bc4SBrooks Davis /// 65*b0d29bc4SBrooks Davis /// \return A dynamically-allocated node. 66*b0d29bc4SBrooks Davis virtual base_node* deep_copy(void) const = 0; 67*b0d29bc4SBrooks Davis 68*b0d29bc4SBrooks Davis /// Combines this node with another one. 69*b0d29bc4SBrooks Davis /// 70*b0d29bc4SBrooks Davis /// \param key Key to this node. 71*b0d29bc4SBrooks Davis /// \param other The node to combine with. 72*b0d29bc4SBrooks Davis /// 73*b0d29bc4SBrooks Davis /// \return A new node representing the combination. 74*b0d29bc4SBrooks Davis /// 75*b0d29bc4SBrooks Davis /// \throw bad_combination_error If the two nodes cannot be combined. 76*b0d29bc4SBrooks Davis virtual base_node* combine(const tree_key& key, const base_node* other) 77*b0d29bc4SBrooks Davis const = 0; 78*b0d29bc4SBrooks Davis }; 79*b0d29bc4SBrooks Davis 80*b0d29bc4SBrooks Davis 81*b0d29bc4SBrooks Davis } // namespace detail 82*b0d29bc4SBrooks Davis 83*b0d29bc4SBrooks Davis 84*b0d29bc4SBrooks Davis /// Abstract leaf node without any specified type. 85*b0d29bc4SBrooks Davis /// 86*b0d29bc4SBrooks Davis /// This base abstract type is necessary to have a common pointer type to which 87*b0d29bc4SBrooks Davis /// to cast any leaf. We later provide templated derivates of this class, and 88*b0d29bc4SBrooks Davis /// those cannot act in this manner. 89*b0d29bc4SBrooks Davis /// 90*b0d29bc4SBrooks Davis /// It is important to understand that a leaf can exist without actually holding 91*b0d29bc4SBrooks Davis /// a value. Our trees are "strictly keyed": keys must have been pre-defined 92*b0d29bc4SBrooks Davis /// before a value can be set on them. This is to ensure that the end user is 93*b0d29bc4SBrooks Davis /// using valid key names and not making mistakes due to typos, for example. To 94*b0d29bc4SBrooks Davis /// represent this condition, we define an "empty" key in the tree to denote 95*b0d29bc4SBrooks Davis /// that the key is valid, yet it has not been set by the user. Only when an 96*b0d29bc4SBrooks Davis /// explicit set is performed on the key, it gets a value. 97*b0d29bc4SBrooks Davis class leaf_node : public detail::base_node { 98*b0d29bc4SBrooks Davis public: 99*b0d29bc4SBrooks Davis virtual ~leaf_node(void); 100*b0d29bc4SBrooks Davis 101*b0d29bc4SBrooks Davis virtual bool is_set(void) const = 0; 102*b0d29bc4SBrooks Davis 103*b0d29bc4SBrooks Davis base_node* combine(const detail::tree_key&, const base_node*) const; 104*b0d29bc4SBrooks Davis 105*b0d29bc4SBrooks Davis virtual void push_lua(lutok::state&) const = 0; 106*b0d29bc4SBrooks Davis virtual void set_lua(lutok::state&, const int) = 0; 107*b0d29bc4SBrooks Davis 108*b0d29bc4SBrooks Davis virtual void set_string(const std::string&) = 0; 109*b0d29bc4SBrooks Davis virtual std::string to_string(void) const = 0; 110*b0d29bc4SBrooks Davis }; 111*b0d29bc4SBrooks Davis 112*b0d29bc4SBrooks Davis 113*b0d29bc4SBrooks Davis /// Base leaf node for a single arbitrary type. 114*b0d29bc4SBrooks Davis /// 115*b0d29bc4SBrooks Davis /// This templated leaf node holds a single object of any type. The conversion 116*b0d29bc4SBrooks Davis /// to/from string representations is undefined, as that depends on the 117*b0d29bc4SBrooks Davis /// particular type being processed. You should reimplement this class for any 118*b0d29bc4SBrooks Davis /// type that needs additional processing/validation during conversion. 119*b0d29bc4SBrooks Davis template< typename ValueType > 120*b0d29bc4SBrooks Davis class typed_leaf_node : public leaf_node { 121*b0d29bc4SBrooks Davis public: 122*b0d29bc4SBrooks Davis /// The type of the value held by this node. 123*b0d29bc4SBrooks Davis typedef ValueType value_type; 124*b0d29bc4SBrooks Davis 125*b0d29bc4SBrooks Davis /// Constructs a new leaf node that contains no value. 126*b0d29bc4SBrooks Davis typed_leaf_node(void); 127*b0d29bc4SBrooks Davis 128*b0d29bc4SBrooks Davis /// Checks whether the node has been set by the user. 129*b0d29bc4SBrooks Davis bool is_set(void) const; 130*b0d29bc4SBrooks Davis 131*b0d29bc4SBrooks Davis /// Gets the value stored in the node. 132*b0d29bc4SBrooks Davis const value_type& value(void) const; 133*b0d29bc4SBrooks Davis 134*b0d29bc4SBrooks Davis /// Gets the read-write value stored in the node. 135*b0d29bc4SBrooks Davis value_type& value(void); 136*b0d29bc4SBrooks Davis 137*b0d29bc4SBrooks Davis /// Sets the value of the node. 138*b0d29bc4SBrooks Davis void set(const value_type&); 139*b0d29bc4SBrooks Davis 140*b0d29bc4SBrooks Davis protected: 141*b0d29bc4SBrooks Davis /// The value held by this node. 142*b0d29bc4SBrooks Davis optional< value_type > _value; 143*b0d29bc4SBrooks Davis 144*b0d29bc4SBrooks Davis private: 145*b0d29bc4SBrooks Davis virtual void validate(const value_type&) const; 146*b0d29bc4SBrooks Davis }; 147*b0d29bc4SBrooks Davis 148*b0d29bc4SBrooks Davis 149*b0d29bc4SBrooks Davis /// Leaf node holding a native type. 150*b0d29bc4SBrooks Davis /// 151*b0d29bc4SBrooks Davis /// This templated leaf node holds a native type. The conversion to/from string 152*b0d29bc4SBrooks Davis /// representations of the value happens by means of iostreams. 153*b0d29bc4SBrooks Davis template< typename ValueType > 154*b0d29bc4SBrooks Davis class native_leaf_node : public typed_leaf_node< ValueType > { 155*b0d29bc4SBrooks Davis public: 156*b0d29bc4SBrooks Davis void set_string(const std::string&); 157*b0d29bc4SBrooks Davis std::string to_string(void) const; 158*b0d29bc4SBrooks Davis }; 159*b0d29bc4SBrooks Davis 160*b0d29bc4SBrooks Davis 161*b0d29bc4SBrooks Davis /// A leaf node that holds a boolean value. 162*b0d29bc4SBrooks Davis class bool_node : public native_leaf_node< bool > { 163*b0d29bc4SBrooks Davis public: 164*b0d29bc4SBrooks Davis virtual base_node* deep_copy(void) const; 165*b0d29bc4SBrooks Davis 166*b0d29bc4SBrooks Davis void push_lua(lutok::state&) const; 167*b0d29bc4SBrooks Davis void set_lua(lutok::state&, const int); 168*b0d29bc4SBrooks Davis }; 169*b0d29bc4SBrooks Davis 170*b0d29bc4SBrooks Davis 171*b0d29bc4SBrooks Davis /// A leaf node that holds an integer value. 172*b0d29bc4SBrooks Davis class int_node : public native_leaf_node< int > { 173*b0d29bc4SBrooks Davis public: 174*b0d29bc4SBrooks Davis virtual base_node* deep_copy(void) const; 175*b0d29bc4SBrooks Davis 176*b0d29bc4SBrooks Davis void push_lua(lutok::state&) const; 177*b0d29bc4SBrooks Davis void set_lua(lutok::state&, const int); 178*b0d29bc4SBrooks Davis }; 179*b0d29bc4SBrooks Davis 180*b0d29bc4SBrooks Davis 181*b0d29bc4SBrooks Davis /// A leaf node that holds a positive non-zero integer value. 182*b0d29bc4SBrooks Davis class positive_int_node : public int_node { 183*b0d29bc4SBrooks Davis virtual void validate(const value_type&) const; 184*b0d29bc4SBrooks Davis }; 185*b0d29bc4SBrooks Davis 186*b0d29bc4SBrooks Davis 187*b0d29bc4SBrooks Davis /// A leaf node that holds a string value. 188*b0d29bc4SBrooks Davis class string_node : public native_leaf_node< std::string > { 189*b0d29bc4SBrooks Davis public: 190*b0d29bc4SBrooks Davis virtual base_node* deep_copy(void) const; 191*b0d29bc4SBrooks Davis 192*b0d29bc4SBrooks Davis void push_lua(lutok::state&) const; 193*b0d29bc4SBrooks Davis void set_lua(lutok::state&, const int); 194*b0d29bc4SBrooks Davis }; 195*b0d29bc4SBrooks Davis 196*b0d29bc4SBrooks Davis 197*b0d29bc4SBrooks Davis /// Base leaf node for a set of native types. 198*b0d29bc4SBrooks Davis /// 199*b0d29bc4SBrooks Davis /// This is a base abstract class because there is no generic way to parse a 200*b0d29bc4SBrooks Davis /// single word in the textual representation of the set to the native value. 201*b0d29bc4SBrooks Davis template< typename ValueType > 202*b0d29bc4SBrooks Davis class base_set_node : public leaf_node { 203*b0d29bc4SBrooks Davis public: 204*b0d29bc4SBrooks Davis /// The type of the value held by this node. 205*b0d29bc4SBrooks Davis typedef std::set< ValueType > value_type; 206*b0d29bc4SBrooks Davis 207*b0d29bc4SBrooks Davis base_set_node(void); 208*b0d29bc4SBrooks Davis 209*b0d29bc4SBrooks Davis /// Checks whether the node has been set by the user. 210*b0d29bc4SBrooks Davis /// 211*b0d29bc4SBrooks Davis /// \return True if a value has been set in the node. 212*b0d29bc4SBrooks Davis bool is_set(void) const; 213*b0d29bc4SBrooks Davis 214*b0d29bc4SBrooks Davis /// Gets the value stored in the node. 215*b0d29bc4SBrooks Davis /// 216*b0d29bc4SBrooks Davis /// \pre The node must have a value. 217*b0d29bc4SBrooks Davis /// 218*b0d29bc4SBrooks Davis /// \return The value in the node. 219*b0d29bc4SBrooks Davis const value_type& value(void) const; 220*b0d29bc4SBrooks Davis 221*b0d29bc4SBrooks Davis /// Gets the read-write value stored in the node. 222*b0d29bc4SBrooks Davis /// 223*b0d29bc4SBrooks Davis /// \pre The node must have a value. 224*b0d29bc4SBrooks Davis /// 225*b0d29bc4SBrooks Davis /// \return The value in the node. 226*b0d29bc4SBrooks Davis value_type& value(void); 227*b0d29bc4SBrooks Davis 228*b0d29bc4SBrooks Davis /// Sets the value of the node. 229*b0d29bc4SBrooks Davis void set(const value_type&); 230*b0d29bc4SBrooks Davis 231*b0d29bc4SBrooks Davis /// Sets the value of the node from a raw string representation. 232*b0d29bc4SBrooks Davis void set_string(const std::string&); 233*b0d29bc4SBrooks Davis 234*b0d29bc4SBrooks Davis /// Converts the contents of the node to a string. 235*b0d29bc4SBrooks Davis std::string to_string(void) const; 236*b0d29bc4SBrooks Davis 237*b0d29bc4SBrooks Davis /// Pushes the node's value onto the Lua stack. 238*b0d29bc4SBrooks Davis void push_lua(lutok::state&) const; 239*b0d29bc4SBrooks Davis 240*b0d29bc4SBrooks Davis /// Sets the value of the node from an entry in the Lua stack. 241*b0d29bc4SBrooks Davis void set_lua(lutok::state&, const int); 242*b0d29bc4SBrooks Davis 243*b0d29bc4SBrooks Davis protected: 244*b0d29bc4SBrooks Davis /// The value held by this node. 245*b0d29bc4SBrooks Davis optional< value_type > _value; 246*b0d29bc4SBrooks Davis 247*b0d29bc4SBrooks Davis private: 248*b0d29bc4SBrooks Davis /// Converts a single word to the native type. 249*b0d29bc4SBrooks Davis /// 250*b0d29bc4SBrooks Davis /// \return The parsed value. 251*b0d29bc4SBrooks Davis /// 252*b0d29bc4SBrooks Davis /// \throw value_error If the value is invalid. 253*b0d29bc4SBrooks Davis virtual ValueType parse_one(const std::string&) const = 0; 254*b0d29bc4SBrooks Davis 255*b0d29bc4SBrooks Davis virtual void validate(const value_type&) const; 256*b0d29bc4SBrooks Davis }; 257*b0d29bc4SBrooks Davis 258*b0d29bc4SBrooks Davis 259*b0d29bc4SBrooks Davis /// A leaf node that holds a set of strings. 260*b0d29bc4SBrooks Davis class strings_set_node : public base_set_node< std::string > { 261*b0d29bc4SBrooks Davis public: 262*b0d29bc4SBrooks Davis virtual base_node* deep_copy(void) const; 263*b0d29bc4SBrooks Davis 264*b0d29bc4SBrooks Davis private: 265*b0d29bc4SBrooks Davis std::string parse_one(const std::string&) const; 266*b0d29bc4SBrooks Davis }; 267*b0d29bc4SBrooks Davis 268*b0d29bc4SBrooks Davis 269*b0d29bc4SBrooks Davis } // namespace config 270*b0d29bc4SBrooks Davis } // namespace utils 271*b0d29bc4SBrooks Davis 272*b0d29bc4SBrooks Davis #endif // !defined(UTILS_CONFIG_NODES_HPP) 273