ConfigFile.cpp

Go to the documentation of this file.
00001 // ConfigFile.cpp
00002 
00003 #include "ConfigFile.hpp"
00004 
00005 using std::string;
00006 
00007 namespace youbot {
00008 
00009   ConfigFile::ConfigFile(string filename, string filepath, string delimiter,
00010           string comment, string sectionStartTag, string sectionEndTag, string sentry)
00011   : myDelimiter(delimiter), myComment(comment), mySectionStartTag(sectionStartTag), mySectionEndTag(sectionEndTag), mySentry(sentry) {
00012 
00013     if(filepath.at(filepath.length()-1) != '/'){
00014       filepath.append("/");
00015     }
00016     filepath.append(filename);
00017 
00018     //Ensure, that we are working with Config Files
00019     if (filepath.substr(filepath.length() - 4, 4) != ".cfg")
00020       filepath.append(".cfg");
00021 
00022     //Store for later use
00023     myFilepath = filepath;
00024     mySortVectorObj = new SortTreeVector();
00025 
00026     // Construct a ConfigFile, getting keys and values from given file
00027     std::ifstream in(filepath.c_str());
00028 
00029     if (!in) throw FileNotFoundException(filepath);
00030 
00031     in >> (*this);
00032   }
00033 
00034   ConfigFile::ConfigFile()
00035   : myDelimiter(string(1, '=')), myComment(string(1, '#')), mySectionStartTag(string(1, '[')), mySectionEndTag(string(1, ']')) {
00036     // Construct a ConfigFile without a file; empty
00037   }
00038 
00039   void ConfigFile::remove(const string& key) {
00040     // Remove key and its value
00041     myContents.erase(myContents.find(key));
00042     return;
00043   }
00044 
00045   void ConfigFile::remove(const string& sectionKey, const string& key) {
00046     mapciSect sp = mySectionRelatedContents.find(sectionKey);
00047     if (sp != mySectionRelatedContents.end()) {
00048       // Remove key and its value
00049       myContents = sp->second;
00050 
00051       std::cout << "Size: " << myContents.size() << endl;
00052 
00053 
00054       mapi p = myContents.find(key);
00055       if (p == myContents.end()) throw KeyNotFoundException(key);
00056       myContents.erase(p);
00057       mySectionRelatedContents[sectionKey] = myContents;
00058     }
00059     return;
00060   }
00061 
00062   void ConfigFile::save() {
00063 
00064     ofstream outFile(myFilepath.c_str());
00065 
00066     outFile << (*this);
00067 
00068   }
00069 
00070   bool ConfigFile::keyExists(const string& key) const {
00071     // Indicate whether key is found
00072     mapci p = myContents.find(key);
00073     return ( p != myContents.end());
00074   }
00075 
00076   bool ConfigFile::keyExists(const string& sectionKey, const string& key) {
00077     mapciSect sp = mySectionRelatedContents.find(sectionKey);
00078     if (sp == mySectionRelatedContents.end()) {
00079       return false;
00080     }
00081 
00082     // Indicate whether key is found
00083     mapci p = mySectionRelatedContents[sectionKey].find(key);
00084     return ( p != mySectionRelatedContents[sectionKey].end());
00085   }
00086 
00087   bool ConfigFile::sectionExists(const string& sectionKey) {
00088 
00089     mapciSect sp = mySectionRelatedContents.find(sectionKey);
00090     if (sp == mySectionRelatedContents.end()) {
00091       return false;
00092     }
00093     return true;
00094   }
00095 
00096   /* static */
00097   void ConfigFile::trim(string& s) {
00098     // Remove leading and trailing whitespace
00099     static const char whitespace[] = " \n\t\v\r\f";
00100     s.erase(0, s.find_first_not_of(whitespace));
00101     s.erase(s.find_last_not_of(whitespace) + 1U);
00102   }
00103 
00104   std::ostream & operator<<(std::ostream& os, ConfigFile& cf) {
00105 
00106     for (unsigned int i = 0; i < cf.mySortVector.size(); i++) {
00107 
00108       SortTreeVector currentTreeVector = cf.mySortVector.at(i);
00109       string currentSector = currentTreeVector.getKey();
00110 
00111       ConfigFile::mapciSect sp = cf.mySectionRelatedContents.find(currentSector.c_str());
00112       //First section has no empty line
00113       if (i > 0) {
00114         os << endl;
00115       }
00116       os << "[" << sp->first << "]" << endl;
00117 
00118       cf.myContents = sp->second;
00119 
00120       std::vector<string> contentVector = currentTreeVector.getVector();
00121       for (unsigned int j = 0; j < contentVector.size(); j++) {
00122         string currentKey = contentVector.at(j);
00123 
00124         // Save a ConfigFile to os
00125         ConfigFile::mapci p = cf.myContents.find(currentKey);
00126 
00127         if (p != cf.myContents.end()) {
00128           os << p->first << " " << cf.myDelimiter << " ";
00129           os << p->second << std::endl;
00130         }
00131       }
00132     }
00133 
00134     return os;
00135 
00136   }
00137 
00138   std::istream & operator>>(std::istream& is, ConfigFile& cf) {
00139     // Load a ConfigFile from is
00140     // Read in keys and values, keeping internal whitespace
00141     typedef string::size_type pos;
00142     const string& delim = cf.myDelimiter; // separator
00143     const string& comm = cf.myComment; // comment
00144     const string& startTag = cf.mySectionStartTag; // starttag
00145     const string& endTag = cf.mySectionEndTag; // endtag
00146     const string& sentry = cf.mySentry; // end of file sentry
00147     const pos skip = delim.length(); // length of separator
00148 
00149 
00150 
00151     string nextline = ""; // might need to read ahead to see where value ends
00152     string sectHeader = "";
00153     std::vector<string> currentVector; //holds key-value pairs for each section
00154 
00155 
00156     while (is || nextline.length() > 0) {
00157 
00158       // Read an entire line at a time
00159       string line;
00160       if (nextline.length() > 0) {
00161         line = nextline; // we read ahead; use it now
00162         nextline = "";
00163       } else {
00164         std::getline(is, line);
00165       }
00166 
00167       // Ignore comments
00168       line = line.substr(0, line.find(comm));
00169 
00170       string lncopy = line;
00171       ConfigFile::trim(lncopy);
00172       //Sectionheader found
00173       if (lncopy.substr(0, 1) == startTag && lncopy.substr(lncopy.length() - 1, 1) == endTag) {
00174 
00175         sectHeader = lncopy.substr(1, lncopy.length() - 2);
00176         ConfigFile::trim(sectHeader);
00177         //New instance for each section
00178         string currentKey = cf.mySortVectorObj->getKey();
00179 
00180         if (!cf.mySortVectorObj || sectHeader != currentKey) {
00181 
00182           if (currentVector.size() > 0) {
00183             cf.mySortVectorObj->setVector(currentVector);
00184             cf.mySortVector.push_back(*cf.mySortVectorObj);
00185 
00186           }
00187           cf.mySortVectorObj = new SortTreeVector;
00188           //Create a new vector for KeyValue-Pairs
00189           currentVector = cf.mySortVectorObj->getVector();
00190           cf.mySortVectorObj->setKey(sectHeader);
00191         }
00192 
00193         cf.mySectionRelatedContents[sectHeader] = cf.myContents;
00194         continue;
00195       }
00196 
00197       // Check for end of file sentry
00198       if (sentry != "" && line.find(sentry) != string::npos) return is;
00199 
00200       // Parse the line if it contains a delimiter
00201       pos delimPos = line.find(delim);
00202       if (delimPos < string::npos) {
00203         // Extract the key
00204         string key = line.substr(0, delimPos);
00205         line.replace(0, delimPos + skip, "");
00206 
00207         // See if value continues on the next line
00208         // Stop at blank line, next line with a key, end of stream,
00209         // or end of file sentry
00210         bool terminate = false;
00211         while (!terminate && is) {
00212           std::getline(is, nextline);
00213           terminate = true;
00214 
00215           string nlcopy = nextline;
00216           ConfigFile::trim(nlcopy);
00217           if (nlcopy == "") continue;
00218 
00219           nextline = nextline.substr(0, nextline.find(comm));
00220           if (nextline.find(delim) != string::npos)
00221             continue;
00222           if (sentry != "" && nextline.find(sentry) != string::npos)
00223             continue;
00224 
00225           nlcopy = nextline;
00226           ConfigFile::trim(nlcopy);
00227           if (nlcopy != "") line += "\n";
00228           line += nextline;
00229           terminate = false;
00230         }
00231 
00232         // Store key and value
00233         ConfigFile::trim(key);
00234         ConfigFile::trim(line);
00235 
00236         currentVector.push_back(key);
00237 
00238         cf.mySectionRelatedContents[sectHeader][key] = line; // overwrites if key is repeated
00239       }
00240     }
00241 
00242     //finally get the last things done
00243     if (currentVector.size() > 0) {
00244       cf.mySortVectorObj->setVector(currentVector);
00245       cf.mySortVector.push_back(*cf.mySortVectorObj);
00246     }
00247 
00248 
00249     return is;
00250   }
00251 
00252 } // namespace youbot
Generated by  doxygen 1.6.3