00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00321