Overview   API Reference  

config_node.hpp

00001 #if !defined(__CONFIG_NODE_HPP__)
00002 #define __CONFIG_NODE_HPP__
00003 
00004 //
00005 // standard includes
00006 //
00007 #include <string>
00008 #include <vector>
00009 
00010 //
00011 // local includes
00012 //
00013 #include "core/util/noncopyable.hpp"
00014 #include "core/util/c++0x.hpp"
00015 #include "core/system/log.hpp"
00016 
00017 //
00018 // forward declarations
00019 //
00020 namespace detail
00021 {
00022     template <typename NodeTypeT>
00023     struct node_traits
00024     {};
00025 }
00026 
00030 struct config_node : private noncopyable
00031 {
00032     //
00033     // mandatory attributes
00034     //
00035     std::string id;
00036 
00037     //
00038     // node types
00039     //
00040     enum type
00041     {
00042         BOOL, NUMBER, INTERVAL, STRING, LIST, SECTION
00043     } type;
00044 
00045     //
00046     // value attributes
00047     //
00048     union
00049     {
00050         bool boolean;
00051         unsigned long number;
00052         struct
00053         {
00054             unsigned long low, high;
00055         };
00056     };
00057 
00058     std::string string;
00059 
00060   protected:
00061     //
00062     // hierarchy attributes
00063     //
00064     config_node *next, *children;
00065 
00066   public:
00067     //
00068     // constructors & destructor
00069     //
00070     inline config_node(const std::string &id, bool boolean)
00071         : id(id), type(BOOL), boolean(boolean), next(nullptr), children(nullptr)
00072     {}
00073 
00074     inline config_node(const std::string &id, unsigned long number)
00075         : id(id), type(NUMBER), number(number), next(nullptr), children(nullptr)
00076     {}
00077 
00078     inline config_node(const std::string &id, unsigned long low, unsigned long high)
00079         : id(id), type(INTERVAL), low(low), high(high), next(nullptr), children(nullptr)
00080     {}
00081 
00082     inline config_node(const std::string &id, const char *string)
00083         : id(id), type(STRING), string(string), next(nullptr), children(nullptr)
00084     {}
00085 
00086     inline config_node(const std::string &id, config_node *children)
00087         : id(id), type(LIST), next(nullptr), children(children)
00088     {}
00089 
00090     inline config_node(const std::string &id, enum type type, config_node *next, config_node *children)
00091         : id(id), type(type), next(next), children(children)
00092     {}
00093 
00094     inline ~config_node(void)
00095     {
00096         delete next;
00097         delete children;
00098     }
00099 
00100     //
00101     // query functions
00102     //
00103     inline bool is(enum type type) const
00104     {
00105         return this->type == type;
00106     }
00107 
00108     inline bool is_bool(void) const
00109     {
00110         return is(BOOL);
00111     }
00112 
00113     inline bool is_number(void) const
00114     {
00115         return is(NUMBER);
00116     }
00117 
00118     inline bool is_interval(void) const
00119     {
00120         return is(INTERVAL);
00121     }
00122 
00123     inline bool is_string(void) const
00124     {
00125         return is(STRING);
00126     }
00127 
00128     inline bool is_list(void) const
00129     {
00130         return is(LIST);
00131     }
00132 
00133     inline bool is_section(void) const
00134     {
00135         return is(SECTION);
00136     }
00137 
00138     inline bool is_attribute(void) const
00139     {
00140         return !is_section();
00141     }
00142 
00143     inline bool is_or_warn(enum type type) const
00144     {
00145         if (is(type)) return true;
00146         warn_wrong_type(type);
00147         return false;
00148     }
00149 
00150     //
00151     // ID functions
00152     //
00153     void set_ID(const std::string &id, bool recursive=false);
00154 
00155     //
00156     // siblings handling
00157     //
00158     inline int num_siblings(void) const
00159     {
00160         return num_nodes(next);
00161     }
00162 
00163     inline bool has_sibling(const std::string &id="") const
00164     {
00165         return get_node(next, id) != nullptr;
00166     }
00167 
00168     inline const config_node *get_sibling(const std::string &id="") const
00169     {
00170         return get_node(next, id);
00171     }
00172 
00173     inline void append_sibling(config_node *node)
00174     {
00175         // appends the node at the end of the silblings list, so do not free it anymore
00176         return append_node(next, node);
00177     }
00178 
00179     inline const config_node *remove_sibling(const std::string &id="")
00180     {
00181         // removes the first sibling named id from the list, which doesn't get_node freed
00182         //     automatically anymore (transfers ownership to caller)
00183         return remove_node(next, id);
00184     }
00185 
00186     //
00187     // children handling
00188     //
00189     inline int num_children(void) const
00190     {
00191         return num_nodes(children);
00192     }
00193 
00194     inline bool has_child(const std::string &id="") const
00195     {
00196         return get_node(children, id) != nullptr;
00197     }
00198 
00199     inline const config_node *get_child(const std::string &id="") const
00200     {
00201         return get_node(children, id);
00202     }
00203 
00204     inline void append_child(config_node *node)
00205     {
00206         // appends the node at the end of the children list, so do not free it anymore
00207         return append_node(children, node);
00208     }
00209 
00210     inline config_node *remove_child(const std::string &id="")
00211     {
00212         // removes the first child named id from the list, which doesn't get freed
00213         //     automatically anymore (transfers ownership to caller)
00214         return remove_node(children, id);
00215     }
00216 
00217     //
00218     // data functions for all node types
00219     //
00220     inline void warn_wrong_type(void) const
00221     {
00222         log::warn("wrong type for option: %s, ignored\n", id.c_str());
00223     }
00224 
00225     inline void warn_wrong_type(enum type type) const
00226     {
00227         log::warn("wrong type for option: %s, expected: %s\n", id.c_str(), type2string(type));
00228     }
00229 
00230     inline void warn_wrong_value(void) const
00231     {
00232         log::warn("wrong value '%s' for option: %s, ignored\n", get_value().c_str(), id.c_str());
00233     }
00234 
00235     void warn_non_empty_section(const char *message=nullptr) const;
00236     std::string get_value(void) const;
00237 
00238     template <typename NodeTypeT>
00239     inline NodeTypeT get_value(const NodeTypeT default_value=NodeTypeT()) const
00240     {
00241         return is_or_warn(detail::node_traits<NodeTypeT>::type) ?
00242                    detail::node_traits<NodeTypeT>::value(*this) : default_value;
00243     }
00244 
00245     //
00246     // data functions for section/list nodes:
00247     //     operate on all child nodes with the specified (list child nodes inherit their id)
00248     //
00249     template <typename NodeTypeT>
00250     NodeTypeT get_option(const std::string &id, NodeTypeT default_value=NodeTypeT());
00251 
00252     template <typename NodeTypeT>
00253     int get_list_option(std::vector<NodeTypeT> &result, const std::string &id);
00254 
00255     //
00256     // debug stuff
00257     //
00258     static inline const char *type2string(enum type type)
00259     {
00260         return (type == BOOL) ? "bool" :
00261                    (type == NUMBER) ? "number" :
00262                        (type == INTERVAL) ? "interval" :
00263                            (type == STRING) ? "string" :
00264                                (type == LIST) ? "list" :
00265                                    (type == SECTION) ? "section" : "unknown";
00266     }
00267 
00268     inline const char *type2string(void) const
00269     {
00270         return type2string(type);
00271     }
00272 
00273     void print(int indent=0, int indent_inc=2, bool siblings=false) const;
00274 
00275   protected:
00276     //
00277     // hierarchy management functions: these functions do the real work
00278     //
00279     static inline int num_nodes(const config_node *chain)
00280     {
00281         for (int n=0; ; chain=chain->next, n++)
00282             if (!chain) return n;
00283     }
00284 
00285     static inline const config_node *get_node(const config_node *chain, const std::string &id="")
00286     {
00287         for (const config_node *p=chain; ; p=p->next)
00288             if (!p || (id == "") || (p->id == id)) return p;
00289     }
00290 
00291     static void append_node(config_node *&chain, config_node *node);
00292     static config_node *remove_node(config_node *&chain, const std::string &id="");
00293 };
00294 
00295 //
00296 // node_traits implementation (cannot specialize member function templates :()
00297 //
00298 namespace detail
00299 {
00300     using ::config_node;
00301 
00302     template <>
00303     struct node_traits<bool>
00304     {
00305         static const enum config_node::type type=config_node::BOOL;
00306 
00307         static inline bool value(const config_node &node)
00308         {
00309             return node.boolean;
00310         }
00311     };
00312 
00313     template <>
00314     struct node_traits<unsigned long>
00315     {
00316         static const enum config_node::type type=config_node::NUMBER;
00317 
00318         static inline unsigned long value(const config_node &node)
00319         {
00320             return node.number;
00321         }
00322     };
00323 
00324     template <>
00325     struct node_traits<std::string>
00326     {
00327         static const enum config_node::type type=config_node::STRING;
00328 
00329         static inline std::string value(const config_node &node)
00330         {
00331             return node.string;
00332         }
00333     };
00334 }
00335 
00336 #endif
00337 
00338 // ***** end of source ***** //
00339 

L4vmm Reference Manual, written by Mario Schwalbe  © 2006-2008