Configuration.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: Configuration.cpp 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 #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 //                                                      std::cout << "'" << line << "' '" << name << "' " << end << std::endl;
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 //                                                              std::cout << "<- " << name << std::endl;
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 /*                                                              if ((!inString) &&
00147                                                                         ((line[curPos] == '[') || (line[curPos] == '<')))
00148                                                                 {
00149                                                                         curPos--;
00150                                                                         break;
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 { // Comment
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                         //result->push_back(node);
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39