$search
00001 /* 00002 * $Id: Configuration.h 275 2008-03-12 14:43:31Z phbaer $ 00003 * 00004 * Copyright 2008 Carpe Noctem, Distributed Systems Group, 00005 * University of Kassel. All right reserved. 00006 * 00007 * The code is licensed under the Carpe Noctem Userfriendly BSD-Based 00008 * License (CNUBBL). Redistribution and use in source and binary forms, 00009 * with or without modification, are permitted provided that the 00010 * conditions of the CNUBBL are met. 00011 * 00012 * You should have received a copy of the CNUBBL along with this 00013 * software. The license is also available on our website: 00014 * http://carpenoctem.das-lab.net/license.txt 00015 */ 00016 00017 #ifndef CASTOR_CONFIGURATION_H 00018 #define CASTOR_CONFIGURATION_H 1 00019 00020 #include <vector> 00021 #include <string> 00022 #include <iostream> 00023 #include <fstream> 00024 #include <cstdarg> 00025 #include <sstream> 00026 #include <string> 00027 #include <cstdarg> 00028 00029 #include <boost/algorithm/string.hpp> 00030 #include <boost/lexical_cast.hpp> 00031 #include <boost/shared_ptr.hpp> 00032 #include <boost/any.hpp> 00033 00034 #include "ConfigException.h" 00035 00036 #define CONSUME_PARAMS(path) \ 00037 boost::shared_ptr<std::vector<std::string> > params(new std::vector<std::string>());\ 00038 if (path != NULL) {\ 00039 va_list ap;\ 00040 va_start(ap, path);\ 00041 const char *temp = path;\ 00042 do { \ 00043 std::vector<std::string> result; \ 00044 boost::split(result, temp, boost::is_any_of(".")); \ 00045 for (size_t i = 0; i < result.size(); i++) { \ 00046 params->push_back(result[i]); \ 00047 } \ 00048 } while ((temp = va_arg(ap, const char *)) != NULL); \ 00049 va_end(ap); \ 00050 } 00051 00052 namespace castor { 00053 00054 class ConfigNode; 00055 00056 typedef boost::shared_ptr<ConfigNode> ConfigNodePtr; 00057 00058 class ConfigNode { 00059 00060 public: 00061 00062 typedef enum { 00063 Node = 0, 00064 Leaf = 1, 00065 Comment = 2, 00066 } Type; 00067 00068 protected: 00069 00070 std::string name; 00071 boost::any value; 00072 ConfigNode *parent; 00073 std::vector<ConfigNodePtr> children; 00074 int depth; 00075 Type type; 00076 00077 public: 00078 00079 ConfigNode(std::string name) : 00080 name(name), value(), parent(NULL), children(), depth(0), type(Node) 00081 { 00082 } 00083 00084 ConfigNode(Type type, std::string name) : 00085 name(name), value(), parent(NULL), children(), depth(0), type(type) 00086 { 00087 } 00088 00089 ConfigNode(std::string name, boost::any &value) : 00090 name(name), value(value), parent(NULL), children(), depth(0), type(Leaf) 00091 { 00092 } 00093 00094 ConfigNode(const ConfigNode &other) : 00095 name(other.name), value(other.value), parent(other.parent), 00096 children(other.children), depth(other.depth), type(other.type) 00097 { 00098 } 00099 00100 ~ConfigNode() { 00101 // std::cout << "deleting " << this->name << std::endl; 00102 } 00103 00104 ConfigNode *create(std::string name) { 00105 this->children.push_back(ConfigNodePtr(new ConfigNode(name))); 00106 this->children.back()->setParent(this); 00107 return this->children.back().get(); 00108 } 00109 00110 ConfigNode *create(Type type, std::string name) { 00111 this->children.push_back(ConfigNodePtr(new ConfigNode(type, name))); 00112 this->children.back()->setParent(this); 00113 return this->children.back().get(); 00114 } 00115 00116 ConfigNode *create(std::string name, boost::any &value) { 00117 this->children.push_back(ConfigNodePtr(new ConfigNode(name, value))); 00118 this->children.back()->setParent(this); 00119 return this->children.back().get(); 00120 } 00121 00122 std::vector<ConfigNodePtr> *getChildren() { 00123 return &this->children; 00124 } 00125 00126 ConfigNode *getParent() { 00127 return this->parent; 00128 } 00129 00130 void setParent(ConfigNode *parent) { 00131 this->parent = parent; 00132 this->depth = parent->depth + 1; 00133 } 00134 00135 const boost::any &getValue() const { 00136 return this->value; 00137 } 00138 00139 void setValue(boost::any &value) { 00140 this->value = value; 00141 } 00142 00143 const std::string &getName() const { 00144 return this->name; 00145 } 00146 00147 int getDepth() const { 00148 return this->depth; 00149 } 00150 00151 Type getType() const { 00152 return this->type; 00153 } 00154 00155 ConfigNode &operator=(const ConfigNode &other) { 00156 00157 this->name = other.name; 00158 this->value = other.value; 00159 this->parent = other.parent; 00160 this->children = other.children; 00161 this->depth = other.depth; 00162 this->type = other.type; 00163 00164 return *this; 00165 } 00166 }; 00167 00168 class Configuration { 00169 00170 protected: 00171 00172 std::string filename; 00173 00174 ConfigNodePtr configRoot; 00175 00176 void serialize_internal(std::ostringstream *ss, ConfigNode *node); 00177 00178 template<typename Target> 00179 Target convert(std::string value) { 00180 00181 if (typeid(Target) == typeid(bool)) { 00182 00183 boost::algorithm::to_lower(value); 00184 00185 if (("false" == value) || ("no" == value) || ("0" == value)) { 00186 return boost::lexical_cast<Target>(false); 00187 } 00188 00189 return boost::lexical_cast<Target>(true); 00190 } 00191 00192 printf("Value %s\n", value.c_str()); 00193 00194 return boost::lexical_cast<Target>(value); 00195 } 00196 00197 void collect(ConfigNode *node, std::vector<std::string> *params, size_t offset, std::vector<ConfigNode *> *result); 00198 void collectSections(ConfigNode *node, std::vector<std::string> *params, size_t offset, std::vector<ConfigNode *> *result); 00199 std::string pathNotFound(std::vector<std::string> *params); 00200 00201 public: 00202 Configuration(); 00203 Configuration(std::string filename); 00204 Configuration(std::string filename, const std::string content); 00205 00206 inline void load(std::string filename) { load(filename, boost::shared_ptr<std::ifstream>(new std::ifstream(filename.c_str(), std::ifstream::in)), false, false); } 00207 00208 void load(std::string filename, boost::shared_ptr<std::istream> content, bool create, bool replace); 00209 00210 void store(); 00211 void store(std::string filename); 00212 00213 std::string serialize(); 00214 00215 template<typename T> 00216 T get(const char *path, ...) { 00217 00218 CONSUME_PARAMS(path); 00219 00220 std::vector<ConfigNode *> nodes; 00221 00222 collect(this->configRoot.get(), params.get(), 0, &nodes); 00223 00224 if (nodes.size() == 0) { 00225 throw ConfigException(pathNotFound(params.get())); 00226 } 00227 00228 return convert<T>(boost::any_cast<std::string>(nodes[0]->getValue())); 00229 } 00230 00231 template<typename T> 00232 boost::shared_ptr<std::vector<T> > getAll(const char *path, ...) { 00233 00234 CONSUME_PARAMS(path); 00235 00236 std::vector<ConfigNode *> nodes; 00237 00238 collect(this->configRoot.get(), params.get(), 0, &nodes); 00239 00240 if (nodes.size() == 0) { 00241 throw ConfigException(pathNotFound(params.get())); 00242 } 00243 00244 boost::shared_ptr<std::vector<T> > result(new std::vector<T>()); 00245 00246 for (int i = 0; i < nodes.size(); i++) { 00247 result->push_back(convert<T>(boost::any_cast<std::string>(nodes[i]->getValue()))); 00248 } 00249 00250 return result; 00251 00252 } 00253 00254 template<typename T> 00255 T tryGet(T d, const char *path, ...) { 00256 00257 CONSUME_PARAMS(path); 00258 00259 std::vector<ConfigNode *> nodes; 00260 00261 collect(this->configRoot.get(), params.get(), 0, &nodes); 00262 00263 if (nodes.size() == 0) { 00264 return d; 00265 } 00266 00267 return convert<T>(boost::any_cast<std::string>(nodes[0]->getValue())); 00268 } 00269 00270 template<typename T> 00271 boost::shared_ptr<std::vector<T> > tryGetAll(T d, const char *path, ...) { 00272 00273 CONSUME_PARAMS(path); 00274 00275 std::vector<ConfigNode *> nodes; 00276 00277 collect(this->configRoot.get(), params.get(), 0, &nodes); 00278 00279 boost::shared_ptr<std::vector<T> > result(new std::vector<T>()); 00280 00281 if (nodes.size() == 0) { 00282 00283 result->push_back(d); 00284 00285 return result; 00286 } 00287 00288 for (int i = 0; i < nodes.size(); i++) { 00289 result->push_back(convert<T>(boost::any_cast<std::string>(nodes[i]->getValue()))); 00290 } 00291 00292 return result; 00293 } 00294 00295 template<typename T> 00296 void set(T value, const char *path, ...) { 00297 00298 CONSUME_PARAMS(path); 00299 00300 std::vector<ConfigNode *> nodes; 00301 00302 collect(this->configRoot.get(), params.get(), 0, &nodes); 00303 00304 for (int i = 0; i < nodes.size(); i++) { 00305 if (nodes[i]->getType() == ConfigNode::Leaf) { 00306 nodes[i]->setValue(value); 00307 } 00308 } 00309 } 00310 00311 boost::shared_ptr<std::vector<std::string> > getSections(const char *path, ...); 00312 boost::shared_ptr<std::vector<std::string> > getNames(const char *path, ...); 00313 00314 boost::shared_ptr<std::vector<std::string> > tryGetSections(std::string d, const char *path, ...); 00315 boost::shared_ptr<std::vector<std::string> > tryGetNames(std::string d, const char *path, ...); 00316 }; 00317 00318 }; 00319 00320 #endif /* CASTOR_CONFIGURATION_H */ 00321