00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "Configuration.h"
00018
00019 namespace castor {
00020
00021 Configuration::Configuration() :
00022 filename(),
00023 configRoot(new ConfigNode("root"))
00024 {}
00025
00026 Configuration::Configuration(std::string filename) :
00027 filename(filename), configRoot(new ConfigNode("root"))
00028 {
00029 load(filename);
00030 }
00031
00032 Configuration::Configuration(std::string filename, const std::string content) :
00033 filename(filename), configRoot(new ConfigNode("root"))
00034 {
00035 load(filename, boost::shared_ptr<std::istream>(new std::istringstream(content)), false, false);
00036 }
00037
00038 void Configuration::load(std::string filename, boost::shared_ptr<std::istream> content, bool, bool) {
00039
00040 this->filename = filename;
00041
00042 int linePos = 0;
00043 int chrPos = 0;
00044
00045 std::string line;
00046
00047 ConfigNode *currentNode = this->configRoot.get();
00048
00049 while (content->good()) {
00050
00051 std::getline(*content, line);
00052 boost::algorithm::trim_left(line);
00053
00054 int lineLen = line.size();
00055
00056 chrPos = 1;
00057
00058 linePos++;
00059
00060 while (chrPos < lineLen - 1) {
00061
00062 if (line.size() == 0) break;
00063
00064 switch (line[0]) {
00065
00066 case '#':
00067 {
00068 std::string comment = line.substr(1, line.size() - 1);
00069
00070 boost::trim(comment);
00071 currentNode->create(ConfigNode::Comment, comment);
00072
00073 chrPos += line.size() - 1;
00074 }
00075 continue;
00076
00077 case '<':
00078 case '[':
00079 {
00080 size_t end = line.find(']');
00081
00082 if (end == std::string::npos) {
00083 end = line.find('>');
00084 }
00085
00086 if ((line.size() < 2) || (end == std::string::npos)) {
00087 std::ostringstream ss;
00088 ss << "Parse error in " << filename << ", line " << linePos << " character " << chrPos << ": malformed tag!";
00089 throw ConfigException(ss.str());
00090 }
00091
00092 if (end - 1 == 0) {
00093 std::ostringstream ss;
00094 ss << "Parse error in " << filename << ", line " << linePos << " character " << chrPos << ": malformed tag, tag name empty!";
00095 throw ConfigException(ss.str());
00096 }
00097
00098 std::string name = line.substr(1, end - 1);
00099
00100
00101 if ((name[0] == '/') || (name[0] == '!')) {
00102
00103 if (currentNode == NULL) {
00104 std::ostringstream ss;
00105 ss << "Parse error in " << filename << ", line " << linePos << " character " << chrPos << ": no opening tag found!";
00106 throw ConfigException(ss.str());
00107 }
00108
00109 if (name.compare(1, name.size() - 1, currentNode->getName()) != 0) {
00110 std::ostringstream ss;
00111 ss << "Parse error in " << filename << ", line " << linePos << " character " << chrPos << ": closing tag does not match opening tag!";
00112 throw ConfigException(ss.str());
00113 }
00114
00115 currentNode = currentNode->getParent();
00116
00117
00118
00119 } else {
00120
00121 ConfigNode *x = currentNode->create(name);
00122
00123 currentNode = x;
00124 }
00125
00126 if (end < line.size() - 1) {
00127 line = line.substr(end + 1, line.size() - end - 1);
00128 }
00129
00130 chrPos += (end + 1);
00131 }
00132 break;
00133
00134 default:
00135 chrPos++;
00136
00137 if ((line[0] != ' ') && (line[0] != '\t')) {
00138
00139 size_t curPos = 0;
00140 bool inString = false;
00141
00142 std::ostringstream ss;
00143
00144 while (curPos < line.size()) {
00145
00146
00147
00148
00149
00150
00151
00152
00153 if (line[curPos] == '"') {
00154 inString = !inString;
00155 curPos++;
00156 }
00157
00158 if (curPos < line.size()) {
00159
00160 ss << line[curPos];
00161 curPos++;
00162 }
00163 }
00164
00165 line = (curPos >= line.size() - 1 ? "" : line.substr(curPos + 1, line.size() - curPos - 1));
00166
00167 chrPos += (curPos - 1);
00168
00169 std::string element = ss.str();
00170 std::string key;
00171 std::string value;
00172
00173 size_t eq = element.find('=');
00174
00175 if (eq != std::string::npos) {
00176 key = element.substr(0, eq - 1);
00177 value = element.substr(eq + 1, element.size() - eq - 1);
00178
00179 boost::algorithm::trim(key);
00180 boost::algorithm::trim(value);
00181 }
00182
00183 boost::any a(value);
00184
00185 currentNode->create(key, a);
00186
00187 } else {
00188 line = line.substr(1, line.size() - 1);
00189 }
00190
00191 break;
00192 }
00193 }
00194 }
00195
00196
00197 if (this->configRoot.get() != currentNode) {
00198 std::ostringstream ss;
00199 ss << "Parse error in " << filename << ", line " << linePos << " character " << line.size() << ": no closing tag found!";
00200 throw ConfigException(ss.str());
00201 }
00202 }
00203
00204 void Configuration::serialize_internal(std::ostringstream *ss, ConfigNode *node) {
00205
00206 if (node == NULL) return;
00207
00208 if (node->getType() == ConfigNode::Node) {
00209
00210 *ss << std::string(4 * node->getDepth(), ' ') << "[" << node->getName() << "]" << std::endl;
00211
00212 for (std::vector<ConfigNodePtr>::iterator itr = node->getChildren()->begin();
00213 itr != node->getChildren()->end(); itr++)
00214 {
00215 serialize_internal(ss, (*itr).get());
00216 }
00217
00218 *ss << std::string(4 * node->getDepth(), ' ') << "[!" << node->getName() << "]" << std::endl;
00219
00220 } else if (node -> getType() == ConfigNode::Leaf) {
00221
00222 *ss << std::string(4 * node->getDepth(), ' ') << node->getName() << " = " << boost::any_cast<std::string>(node->getValue()) << std::endl;
00223
00224 } else {
00225
00226 *ss << std::string(4 * node->getDepth(), ' ') << "# " << node->getName() << std::endl;
00227
00228 }
00229 }
00230
00231 void Configuration::store() {
00232
00233 if (this->filename.size() > 0) {
00234 store(this->filename);
00235 }
00236 }
00237
00238 void Configuration::store(std::string filename) {
00239
00240 std::ostringstream ss;
00241 std::ofstream os(filename.c_str(), std::ios_base::out);
00242
00243 serialize_internal(&ss, this->configRoot.get());
00244
00245 os << ss.str();
00246 }
00247
00248 std::string Configuration::serialize() {
00249
00250 std::ostringstream ss;
00251 serialize_internal(&ss, this->configRoot.get());
00252
00253 return ss.str();
00254 }
00255
00256 void Configuration::collect(ConfigNode *node, std::vector<std::string> *params, size_t offset, std::vector<ConfigNode *> *result) {
00257
00258 std::vector<ConfigNodePtr> *children = node->getChildren();
00259
00260 if (offset == params->size()) {
00261 result->push_back(node);
00262 return;
00263 }
00264
00265 for (size_t i = offset; i < params->size(); i++) {
00266
00267 bool found = false;
00268
00269 for (size_t j = 0; j < children->size(); j++) {
00270
00271 if ((*children)[j]->getName().compare((*params)[i]) == 0) {
00272 collect((*children)[j].get(), params, offset + 1, result);
00273 found = true;
00274 }
00275 }
00276
00277 if (!found) return;
00278 }
00279 }
00280
00281 void Configuration::collectSections(ConfigNode *node, std::vector<std::string> *params, size_t offset, std::vector<ConfigNode *> *result) {
00282
00283 std::vector<ConfigNodePtr> *children = node->getChildren();
00284
00285 for(unsigned int i = 0; i < children->size(); i++){
00286
00287 printf("Children %d %s\n", i, (*children)[i]->getName().c_str());
00288
00289 }
00290
00291 printf("offset %u\n", (unsigned int)offset);
00292 printf("params->size %u\n", (unsigned int)params->size());
00293
00294 if (offset == params->size()) {
00295 printf("pushed %s\n", node->getName().c_str());
00296
00297 for(unsigned int i = 0; i < children->size(); i++){
00298
00299 result->push_back((*children)[i].get());
00300
00301 }
00302
00303 return;
00304 }
00305
00306 for (size_t i = offset; i < params->size(); i++) {
00307
00308 bool found = false;
00309
00310 for (size_t j = 0; j < children->size(); j++) {
00311
00312 if ((*children)[j]->getName().compare((*params)[i]) == 0) {
00313 printf("found true mit %s\n", (*children)[j]->getName().c_str());
00314 collectSections((*children)[j].get(), params, offset + 1, result);
00315 found = true;
00316 }
00317 }
00318
00319 if (!found) return;
00320 }
00321 }
00322
00323
00324
00325 std::string Configuration::pathNotFound(std::vector<std::string> *params) {
00326
00327 std::ostringstream os;
00328
00329 if ((params == NULL) || (params->size() == 0)) {
00330
00331 os << "Empty path not found in " << this->filename << "!" << std::endl;
00332
00333 } else {
00334
00335 os << "Path '" << (*params)[0];
00336
00337 for (size_t i = 1; i < params->size(); i++) {
00338 os << "." << (*params)[i];
00339 }
00340
00341 os << "' not found in " << this->filename << "!" << std::endl;
00342 }
00343
00344 return os.str();
00345 }
00346
00347 boost::shared_ptr<std::vector<std::string> > Configuration::getSections(const char *path, ...) {
00348
00349 CONSUME_PARAMS(path);
00350
00351 std::vector<ConfigNode *> nodes;
00352
00353 for(unsigned int i = 0; i < params->size(); i++){
00354 printf("Params %d %s\n", i, (*params)[i].c_str());
00355
00356 }
00357
00358 collectSections(this->configRoot.get(), params.get(), 0, &nodes);
00359
00360
00361 boost::shared_ptr<std::vector<std::string> > result(new std::vector<std::string>());
00362
00363 if (nodes.size() == 0) {
00364 throw ConfigException(pathNotFound(params.get()));
00365 }
00366
00367
00368
00369
00370 for (unsigned int i = 0; i < nodes.size(); i++) {
00371 printf("Nodes as result: %u %s\n", i, nodes[i]->getName().c_str());
00372
00373 if (nodes[i]->getType() == ConfigNode::Node) {
00374 result->push_back(nodes[i]->getName());
00375 }
00376 }
00377
00378 return result;
00379 }
00380
00381 boost::shared_ptr<std::vector<std::string> > Configuration::getNames(const char *path, ...) {
00382
00383 CONSUME_PARAMS(path);
00384
00385 std::vector<ConfigNode *> nodes;
00386
00387 collect(this->configRoot.get(), params.get(), 0, &nodes);
00388
00389 boost::shared_ptr<std::vector<std::string> > result(new std::vector<std::string>());
00390
00391 if (nodes.size() == 0) {
00392 throw ConfigException(pathNotFound(params.get()));
00393 }
00394
00395 for (size_t i = 0; i < nodes.size(); i++) {
00396 if (nodes[i]->getType() == ConfigNode::Leaf) {
00397 result->push_back(nodes[i]->getName());
00398 }
00399 }
00400
00401 return result;
00402 }
00403
00404 boost::shared_ptr<std::vector<std::string> > Configuration::tryGetSections(std::string d, const char *path, ...) {
00405
00406 CONSUME_PARAMS(path);
00407
00408 std::vector<ConfigNode *> nodes;
00409
00410 collect(this->configRoot.get(), params.get(), 0, &nodes);
00411
00412 boost::shared_ptr<std::vector<std::string> > result(new std::vector<std::string>());
00413
00414 if (nodes.size() == 0) {
00415
00416 result->push_back(d);
00417
00418 return result;
00419 }
00420
00421 for (size_t i = 0; i < nodes.size(); i++) {
00422 if (nodes[i]->getType() == ConfigNode::Node) {
00423 result->push_back(nodes[i]->getName());
00424 }
00425 }
00426
00427 return result;
00428 }
00429
00430 boost::shared_ptr<std::vector<std::string> > Configuration::tryGetNames(std::string d, const char *path, ...) {
00431
00432 CONSUME_PARAMS(path);
00433
00434 std::vector<ConfigNode *> nodes;
00435
00436 collect(this->configRoot.get(), params.get(), 0, &nodes);
00437
00438 boost::shared_ptr<std::vector<std::string> > result(new std::vector<std::string>());
00439
00440 if (nodes.size() == 0) {
00441
00442 result->push_back(d);
00443
00444 return result;
00445 }
00446
00447 for (size_t i = 0; i < nodes.size(); i++) {
00448 if (nodes[i]->getType() == ConfigNode::Leaf) {
00449 result->push_back(nodes[i]->getName());
00450 }
00451 }
00452
00453 return result;
00454 }
00455 };
00456