From 3f3b3a15c74c59c4cd14fc539ca5e45fedadbcd4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Mon, 22 Feb 2016 17:27:06 +0100 Subject: [PATCH] conftree: astyle + merge with upmpdcli version --- src/utils/conftree.cpp | 1052 +++++++++++++++++++++------------------- src/utils/conftree.h | 539 ++++++++++---------- 2 files changed, 828 insertions(+), 763 deletions(-) diff --git a/src/utils/conftree.cpp b/src/utils/conftree.cpp index c553ad9b..db75aa65 100644 --- a/src/utils/conftree.cpp +++ b/src/utils/conftree.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 J.F.Dockes +/* Copyright (C) 2003 J.F.Dockes * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -18,22 +18,24 @@ #ifndef TEST_CONFTREE +#include "conftree.h" + #include #include #include "safesysstat.h" -#include -#include #include -#include #include +#include +#include +#include +#include -using namespace std; - -#include "conftree.h" #include "pathut.h" #include "smallut.h" +using namespace std; + #undef DEBUG #ifdef DEBUG #define LOGDEB(X) fprintf X @@ -41,7 +43,7 @@ using namespace std; #define LOGDEB(X) #endif -void ConfSimple::parseinput(istream &input) +void ConfSimple::parseinput(istream& input) { string submapkey; string cline; @@ -52,86 +54,92 @@ void ConfSimple::parseinput(istream &input) for (;;) { cline.clear(); std::getline(input, cline); - LOGDEB((stderr, "Parse:line: [%s] status %d\n", + LOGDEB((stderr, "Parse:line: [%s] status %d\n", cline.c_str(), int(status))); - if (!input.good()) { - if (input.bad()) { + if (!input.good()) { + if (input.bad()) { LOGDEB((stderr, "Parse: input.bad()\n")); - status = STATUS_ERROR; - return; - } + status = STATUS_ERROR; + return; + } LOGDEB((stderr, "Parse: eof\n")); - // Must be eof ? But maybe we have a partial line which - // must be processed. This happens if the last line before - // eof ends with a backslash, or there is no final \n + // Must be eof ? But maybe we have a partial line which + // must be processed. This happens if the last line before + // eof ends with a backslash, or there is no final \n eof = true; - } + } { string::size_type pos = cline.find_last_not_of("\n\r"); if (pos == string::npos) { cline.clear(); - } else if (pos != cline.length()-1) { - cline.erase(pos+1); + } else if (pos != cline.length() - 1) { + cline.erase(pos + 1); } } - if (appending) - line += cline; - else - line = cline; + if (appending) { + line += cline; + } else { + line = cline; + } - // Note that we trim whitespace before checking for backslash-eol - // This avoids invisible whitespace problems. - trimstring(line); - if (line.empty() || line.at(0) == '#') { - if (eof) + // Note that we trim whitespace before checking for backslash-eol + // This avoids invisible whitespace problems. + trimstring(line); + if (line.empty() || line.at(0) == '#') { + if (eof) { break; - m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); - continue; - } - if (line[line.length() - 1] == '\\') { - line.erase(line.length() - 1); - appending = true; - continue; - } - appending = false; + } + m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); + continue; + } + if (line[line.length() - 1] == '\\') { + line.erase(line.length() - 1); + appending = true; + continue; + } + appending = false; - if (line[0] == '[') { - trimstring(line, "[]"); - if (dotildexpand) - submapkey = path_tildexpand(line); - else - submapkey = line; - // No need for adding sk to order, will be done with first - // variable insert. Also means that empty section are - // expandable (won't be output when rewriting) - // Another option would be to add the subsec to m_order here - // and not do it inside i_set() if init is true - continue; - } + if (line[0] == '[') { + trimstring(line, "[]"); + if (dotildexpand) { + submapkey = path_tildexpand(line); + } else { + submapkey = line; + } + m_subkeys_unsorted.push_back(submapkey); - // Look for first equal sign - string::size_type eqpos = line.find("="); - if (eqpos == string::npos) { - m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); - continue; - } + // No need for adding sk to order, will be done with first + // variable insert. Also means that empty section are + // expandable (won't be output when rewriting) + // Another option would be to add the subsec to m_order here + // and not do it inside i_set() if init is true + continue; + } - // Compute name and value, trim white space - string nm, val; - nm = line.substr(0, eqpos); - trimstring(nm); - val = line.substr(eqpos+1, string::npos); - trimstring(val); - - if (nm.length() == 0) { - m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); - continue; - } - i_set(nm, val, submapkey, true); - if (eof) + // Look for first equal sign + string::size_type eqpos = line.find("="); + if (eqpos == string::npos) { + m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); + continue; + } + + // Compute name and value, trim white space + string nm, val; + nm = line.substr(0, eqpos); + trimstring(nm); + val = line.substr(eqpos + 1, string::npos); + trimstring(val); + + if (nm.length() == 0) { + m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); + continue; + } + i_set(nm, val, submapkey, true); + if (eof) { break; + } } } @@ -165,31 +173,31 @@ ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp) ifstream input; if (readonly) { - input.open(fname, ios::in); + input.open(fname, ios::in); } else { - ios::openmode mode = ios::in|ios::out; - // It seems that there is no separate 'create if not exists' - // open flag. Have to truncate to create, but dont want to do - // this to an existing file ! - if (!path_exists(fname)) { - mode |= ios::trunc; - } - input.open(fname, mode); - if (input.is_open()) { - status = STATUS_RW; - } else { - input.clear(); - input.open(fname, ios::in); - if (input.is_open()) { - status = STATUS_RO; - } - } + ios::openmode mode = ios::in | ios::out; + // It seems that there is no separate 'create if not exists' + // open flag. Have to truncate to create, but dont want to do + // this to an existing file ! + if (!path_exists(fname)) { + mode |= ios::trunc; + } + input.open(fname, mode); + if (input.is_open()) { + status = STATUS_RW; + } else { + input.clear(); + input.open(fname, ios::in); + if (input.is_open()) { + status = STATUS_RO; + } + } } if (!input.is_open()) { - status = STATUS_ERROR; - return; - } + status = STATUS_ERROR; + return; + } parseinput(input); i_changed(true); @@ -198,21 +206,24 @@ ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp) ConfSimple::StatusCode ConfSimple::getStatus() const { switch (status) { - case STATUS_RO: return STATUS_RO; - case STATUS_RW: return STATUS_RW; - default: return STATUS_ERROR; + case STATUS_RO: + return STATUS_RO; + case STATUS_RW: + return STATUS_RW; + default: + return STATUS_ERROR; } } bool ConfSimple::sourceChanged() const { if (!m_filename.empty()) { - struct stat st; - if (stat(m_filename.c_str(), &st) == 0) { - if (m_fmtime != st.st_mtime) { - return true; - } - } + struct stat st; + if (stat(m_filename.c_str(), &st) == 0) { + if (m_fmtime != st.st_mtime) { + return true; + } + } } return false; } @@ -220,32 +231,36 @@ bool ConfSimple::sourceChanged() const bool ConfSimple::i_changed(bool upd) { if (!m_filename.empty()) { - struct stat st; - if (stat(m_filename.c_str(), &st) == 0) { - if (m_fmtime != st.st_mtime) { - if (upd) - m_fmtime = st.st_mtime; - return true; - } - } + struct stat st; + if (stat(m_filename.c_str(), &st) == 0) { + if (m_fmtime != st.st_mtime) { + if (upd) { + m_fmtime = st.st_mtime; + } + return true; + } + } } return false; } -int ConfSimple::get(const string &nm, string &value, const string &sk) const +int ConfSimple::get(const string& nm, string& value, const string& sk) const { - if (!ok()) - return 0; + if (!ok()) { + return 0; + } // Find submap map >::const_iterator ss; - if ((ss = m_submaps.find(sk)) == m_submaps.end()) - return 0; + if ((ss = m_submaps.find(sk)) == m_submaps.end()) { + return 0; + } // Find named value map::const_iterator s; - if ((s = ss->second.find(nm)) == ss->second.end()) - return 0; + if ((s = ss->second.find(nm)) == ss->second.end()) { + return 0; + } value = s->second; return 1; } @@ -264,107 +279,109 @@ int ConfSimple::get(const string &nm, string &value, const string &sk) const // Note that the choice of break point does not affect the validity of // the file data (when read back by conftree), only its ease of // editing with a normal editor. -static ConfSimple::WalkerCode varprinter(void *f, const string &nm, - const string &value) +static ConfSimple::WalkerCode varprinter(void *f, const string& nm, + const string& value) { ostream& output = *((ostream *)f); if (nm.empty()) { - output << "\n[" << value << "]\n"; + output << "\n[" << value << "]\n"; } else { output << nm << " = "; - if (nm.length() + value.length() < 75) { - output << value; - } else { + if (nm.length() + value.length() < 75) { + output << value; + } else { string::size_type ll = 0; - for (string::size_type pos = 0; pos < value.length(); pos++) { + for (string::size_type pos = 0; pos < value.length(); pos++) { string::value_type c = value[pos]; output << c; ll++; // Break at whitespace if line too long and "a lot" of // remaining data if (ll > 50 && (value.length() - pos) > 10 && - (c == ' ' || c == '\t')) { + (c == ' ' || c == '\t')) { ll = 0; output << "\\\n"; } - } - } + } + } output << "\n"; } return ConfSimple::WALK_CONTINUE; } // Set variable and rewrite data -int ConfSimple::set(const std::string &nm, const std::string &value, - const string &sk) +int ConfSimple::set(const std::string& nm, const std::string& value, + const string& sk) { - if (status != STATUS_RW) - return 0; + if (status != STATUS_RW) { + return 0; + } LOGDEB((stderr, "ConfSimple::set [%s]:[%s] -> [%s]\n", sk.c_str(), - nm.c_str(), value.c_str())); - if (!i_set(nm, value, sk)) - return 0; + nm.c_str(), value.c_str())); + if (!i_set(nm, value, sk)) { + return 0; + } return write(); } // Internal set variable: no rw checking or file rewriting. If init is // set, we're doing initial parsing, else we are changing a parsed // tree (changes the way we update the order data) -int ConfSimple::i_set(const std::string &nm, const std::string &value, - const string &sk, bool init) +int ConfSimple::i_set(const std::string& nm, const std::string& value, + const string& sk, bool init) { LOGDEB((stderr, "ConfSimple::i_set: nm[%s] val[%s] key[%s], init %d\n", - nm.c_str(), value.c_str(), sk.c_str(), init)); + nm.c_str(), value.c_str(), sk.c_str(), init)); // Values must not have embedded newlines if (value.find_first_of("\n\r") != string::npos) { - LOGDEB((stderr, "ConfSimple::i_set: LF in value\n")); - return 0; + LOGDEB((stderr, "ConfSimple::i_set: LF in value\n")); + return 0; } bool existing = false; map >::iterator ss; // Test if submap already exists, else create it, and insert variable: if ((ss = m_submaps.find(sk)) == m_submaps.end()) { - LOGDEB((stderr, "ConfSimple::i_set: new submap\n")); - map submap; - submap[nm] = value; - m_submaps[sk] = submap; + LOGDEB((stderr, "ConfSimple::i_set: new submap\n")); + map submap; + submap[nm] = value; + m_submaps[sk] = submap; - // Maybe add sk entry to m_order data: - if (!sk.empty()) { - ConfLine nl(ConfLine::CFL_SK, sk); - // Append SK entry only if it's not already there (erase - // does not remove entries from the order data, adn it may - // be being recreated after deletion) - if (find(m_order.begin(), m_order.end(), nl) == m_order.end()) { - m_order.push_back(nl); - } - } + // Maybe add sk entry to m_order data: + if (!sk.empty()) { + ConfLine nl(ConfLine::CFL_SK, sk); + // Append SK entry only if it's not already there (erase + // does not remove entries from the order data, adn it may + // be being recreated after deletion) + if (find(m_order.begin(), m_order.end(), nl) == m_order.end()) { + m_order.push_back(nl); + } + } } else { - // Insert or update variable in existing map. - map::iterator it; - it = ss->second.find(nm); - if (it == ss->second.end()) { - ss->second.insert(pair(nm, value)); - } else { - it->second = value; - existing = true; - } + // Insert or update variable in existing map. + map::iterator it; + it = ss->second.find(nm); + if (it == ss->second.end()) { + ss->second.insert(pair(nm, value)); + } else { + it->second = value; + existing = true; + } } // If the variable already existed, no need to change the m_order data if (existing) { - LOGDEB((stderr, "ConfSimple::i_set: existing var: no order update\n")); - return 1; + LOGDEB((stderr, "ConfSimple::i_set: existing var: no order update\n")); + return 1; } // Add the new variable at the end of its submap in the order data. if (init) { - // During the initial construction, just append: - LOGDEB((stderr, "ConfSimple::i_set: init true: append\n")); - m_order.push_back(ConfLine(ConfLine::CFL_VAR, nm)); - return 1; - } + // During the initial construction, just append: + LOGDEB((stderr, "ConfSimple::i_set: init true: append\n")); + m_order.push_back(ConfLine(ConfLine::CFL_VAR, nm)); + return 1; + } // Look for the start and end of the subkey zone. Start is either // at begin() for a null subkey, or just behind the subkey @@ -372,91 +389,96 @@ int ConfSimple::i_set(const std::string &nm, const std::string &value, // list. We insert the new entry just before end. vector::iterator start, fin; if (sk.empty()) { - start = m_order.begin(); - LOGDEB((stderr,"ConfSimple::i_set: null sk, start at top of order\n")); + start = m_order.begin(); + LOGDEB((stderr, "ConfSimple::i_set: null sk, start at top of order\n")); } else { - start = find(m_order.begin(), m_order.end(), - ConfLine(ConfLine::CFL_SK, sk)); - if (start == m_order.end()) { - // This is not logically possible. The subkey must - // exist. We're doomed - std::cerr << "Logical failure during configuration variable " - "insertion" << endl; - abort(); - } + start = find(m_order.begin(), m_order.end(), + ConfLine(ConfLine::CFL_SK, sk)); + if (start == m_order.end()) { + // This is not logically possible. The subkey must + // exist. We're doomed + std::cerr << "Logical failure during configuration variable " + "insertion" << endl; + abort(); + } } fin = m_order.end(); if (start != m_order.end()) { - // The null subkey has no entry (maybe it should) - if (!sk.empty()) - start++; - for (vector::iterator it = start; it != m_order.end(); it++) { - if (it->m_kind == ConfLine::CFL_SK) { - fin = it; - break; - } - } + // The null subkey has no entry (maybe it should) + if (!sk.empty()) { + start++; + } + for (vector::iterator it = start; it != m_order.end(); it++) { + if (it->m_kind == ConfLine::CFL_SK) { + fin = it; + break; + } + } } // It may happen that the order entry already exists because erase doesnt // update m_order if (find(start, fin, ConfLine(ConfLine::CFL_VAR, nm)) == fin) { - m_order.insert(fin, ConfLine(ConfLine::CFL_VAR, nm)); + m_order.insert(fin, ConfLine(ConfLine::CFL_VAR, nm)); } return 1; } -int ConfSimple::erase(const string &nm, const string &sk) +int ConfSimple::erase(const string& nm, const string& sk) { - if (status != STATUS_RW) - return 0; + if (status != STATUS_RW) { + return 0; + } map >::iterator ss; if ((ss = m_submaps.find(sk)) == m_submaps.end()) { - return 0; + return 0; } - + ss->second.erase(nm); if (ss->second.empty()) { - m_submaps.erase(ss); + m_submaps.erase(ss); } return write(); } -int ConfSimple::eraseKey(const string &sk) +int ConfSimple::eraseKey(const string& sk) { vector nms = getNames(sk); for (vector::iterator it = nms.begin(); it != nms.end(); it++) { - erase(*it, sk); + erase(*it, sk); } return write(); } // Walk the tree, calling user function at each node -ConfSimple::WalkerCode -ConfSimple::sortwalk(WalkerCode (*walker)(void *,const string&,const string&), - void *clidata) const +ConfSimple::WalkerCode +ConfSimple::sortwalk(WalkerCode(*walker)(void *, const string&, const string&), + void *clidata) const { - if (!ok()) - return WALK_STOP; + if (!ok()) { + return WALK_STOP; + } // For all submaps: - for (map >::const_iterator sit = - m_submaps.begin(); - sit != m_submaps.end(); sit++) { + for (map >::const_iterator sit = + m_submaps.begin(); + sit != m_submaps.end(); sit++) { - // Possibly emit submap name: - if (!sit->first.empty() && walker(clidata, string(), sit->first.c_str()) - == WALK_STOP) - return WALK_STOP; + // Possibly emit submap name: + if (!sit->first.empty() && walker(clidata, string(), sit->first.c_str()) + == WALK_STOP) { + return WALK_STOP; + } - // Walk submap - const map &sm = sit->second; - for (map::const_iterator it = sm.begin();it != sm.end(); - it++) { - if (walker(clidata, it->first, it->second) == WALK_STOP) - return WALK_STOP; - } + // Walk submap + const map& sm = sit->second; + for (map::const_iterator it = sm.begin(); it != sm.end(); + it++) { + if (walker(clidata, it->first, it->second) == WALK_STOP) { + return WALK_STOP; + } + } } return WALK_CONTINUE; } @@ -465,21 +487,24 @@ ConfSimple::sortwalk(WalkerCode (*walker)(void *,const string&,const string&), // a file bool ConfSimple::write() { - if (!ok()) - return false; - if (m_holdWrites) - return true; + if (!ok()) { + return false; + } + if (m_holdWrites) { + return true; + } if (m_filename.length()) { - ofstream output(m_filename.c_str(), ios::out|ios::trunc); - if (!output.is_open()) - return 0; - return write(output); + ofstream output(m_filename.c_str(), ios::out | ios::trunc); + if (!output.is_open()) { + return 0; + } + return write(output); } else { - // No backing store, no writing. Maybe one day we'll need it with + // No backing store, no writing. Maybe one day we'll need it with // some kind of output string. This can't be the original string which // is currently readonly. - //ostringstream output(m_ostring, ios::out | ios::trunc); - return 1; + //ostringstream output(m_ostring, ios::out | ios::trunc); + return 1; } } @@ -488,74 +513,81 @@ bool ConfSimple::write() // lets ie: showall work even when holdWrites is set bool ConfSimple::write(ostream& out) const { - if (!ok()) - return false; + if (!ok()) { + return false; + } string sk; - for (vector::const_iterator it = m_order.begin(); - it != m_order.end(); it++) { - switch(it->m_kind) { - case ConfLine::CFL_COMMENT: - out << it->m_data << endl; - if (!out.good()) - return false; - break; - case ConfLine::CFL_SK: - sk = it->m_data; - LOGDEB((stderr, "ConfSimple::write: SK [%s]\n", sk.c_str())); - // Check that the submap still exists, and only output it if it - // does - if (m_submaps.find(sk) != m_submaps.end()) { - out << "[" << it->m_data << "]" << endl; - if (!out.good()) - return false; - } - break; - case ConfLine::CFL_VAR: - string nm = it->m_data; - LOGDEB((stderr, "ConfSimple::write: VAR [%s], sk [%s]\n", - nm.c_str(), sk.c_str())); - // As erase() doesnt update m_order we can find unexisting - // variables, and must not output anything for them. Have - // to use a ConfSimple::get() to check here, because - // ConfTree's could retrieve from an ancestor even if the - // local var is gone. - string value; - if (ConfSimple::get(nm, value, sk)) { - varprinter(&out, nm, value); - if (!out.good()) - return false; - break; - } - LOGDEB((stderr, "ConfSimple::write: no value: nm[%s] sk[%s]\n", - nm.c_str(), sk.c_str())); - break; - } + for (vector::const_iterator it = m_order.begin(); + it != m_order.end(); it++) { + switch (it->m_kind) { + case ConfLine::CFL_COMMENT: + out << it->m_data << endl; + if (!out.good()) { + return false; + } + break; + case ConfLine::CFL_SK: + sk = it->m_data; + LOGDEB((stderr, "ConfSimple::write: SK [%s]\n", sk.c_str())); + // Check that the submap still exists, and only output it if it + // does + if (m_submaps.find(sk) != m_submaps.end()) { + out << "[" << it->m_data << "]" << endl; + if (!out.good()) { + return false; + } + } + break; + case ConfLine::CFL_VAR: + string nm = it->m_data; + LOGDEB((stderr, "ConfSimple::write: VAR [%s], sk [%s]\n", + nm.c_str(), sk.c_str())); + // As erase() doesnt update m_order we can find unexisting + // variables, and must not output anything for them. Have + // to use a ConfSimple::get() to check here, because + // ConfTree's could retrieve from an ancestor even if the + // local var is gone. + string value; + if (ConfSimple::get(nm, value, sk)) { + varprinter(&out, nm, value); + if (!out.good()) { + return false; + } + break; + } + LOGDEB((stderr, "ConfSimple::write: no value: nm[%s] sk[%s]\n", + nm.c_str(), sk.c_str())); + break; + } } return true; } void ConfSimple::showall() const { - if (!ok()) - return; + if (!ok()) { + return; + } write(std::cout); } -vector ConfSimple::getNames(const string &sk, const char *pattern) const +vector ConfSimple::getNames(const string& sk, const char *pattern) const { vector mylist; - if (!ok()) - return mylist; + if (!ok()) { + return mylist; + } map >::const_iterator ss; if ((ss = m_submaps.find(sk)) == m_submaps.end()) { - return mylist; + return mylist; } mylist.reserve(ss->second.size()); map::const_iterator it; for (it = ss->second.begin(); it != ss->second.end(); it++) { - if (pattern && 0 != fnmatch(pattern, it->first.c_str(), 0)) + if (pattern && 0 != fnmatch(pattern, it->first.c_str(), 0)) { continue; - mylist.push_back(it->first); + } + mylist.push_back(it->first); } return mylist; } @@ -563,12 +595,13 @@ vector ConfSimple::getNames(const string &sk, const char *pattern) const vector ConfSimple::getSubKeys() const { vector mylist; - if (!ok()) - return mylist; + if (!ok()) { + return mylist; + } mylist.reserve(m_submaps.size()); map >::const_iterator ss; for (ss = m_submaps.begin(); ss != m_submaps.end(); ss++) { - mylist.push_back(ss->first); + mylist.push_back(ss->first); } return mylist; } @@ -576,11 +609,12 @@ vector ConfSimple::getSubKeys() const bool ConfSimple::hasNameAnywhere(const string& nm) const { vectorkeys = getSubKeys(); - for (vector::const_iterator it = keys.begin(); - it != keys.end(); it++) { + for (vector::const_iterator it = keys.begin(); + it != keys.end(); it++) { string val; - if (get(nm, val, *it)) + if (get(nm, val, *it)) { return true; + } } return false; } @@ -589,12 +623,13 @@ bool ConfSimple::hasNameAnywhere(const string& nm) const // ConfTree Methods: conftree interpret keys like a hierarchical file tree // ////////////////////////////////////////////////////////////////////////// -int ConfTree::get(const std::string &name, string &value, const string &sk) - const +int ConfTree::get(const std::string& name, string& value, const string& sk) +const { - if (sk.empty() || !path_isabsolute(sk) ) { - // LOGDEB((stderr, "ConfTree::get: looking in global space for sk [%s]\n", sk.c_str())); - return ConfSimple::get(name, value, sk); + if (sk.empty() || !path_isabsolute(sk)) { + // LOGDEB((stderr, "ConfTree::get: looking in global space for [%s]\n", + // sk.c_str())); + return ConfSimple::get(name, value, sk); } // Get writable copy of subkey path @@ -606,20 +641,21 @@ int ConfTree::get(const std::string &name, string &value, const string &sk) // Look in subkey and up its parents until root ('') for (;;) { - // LOGDEB((stderr,"ConfTree::get: looking for '%s' in '%s'\n", + // LOGDEB((stderr,"ConfTree::get: looking for '%s' in '%s'\n", // name.c_str(), msk.c_str())); - if (ConfSimple::get(name, value, msk)) - return 1; - string::size_type pos = msk.rfind("/"); - if (pos != string::npos) { - msk.replace(pos, string::npos, string()); - } else { + if (ConfSimple::get(name, value, msk)) { + return 1; + } + string::size_type pos = msk.rfind("/"); + if (pos != string::npos) { + msk.replace(pos, string::npos, string()); + } else { #ifdef _WIN32 - if (msk.size() == 2 && isalpha(msk[0]) && msk[1] == ':') + if (msk.size() == 2 && isalpha(msk[0]) && msk[1] == ':') { msk.clear(); - else + } else #endif - break; + break; } } return 0; @@ -647,16 +683,16 @@ static char *thisprog; bool complex_updates(const string& fn) { int fd; - if ((fd = open(fn.c_str(), O_RDWR|O_TRUNC|O_CREAT, 0666)) < 0) { - perror("open/create"); - return false; + if ((fd = open(fn.c_str(), O_RDWR | O_TRUNC | O_CREAT, 0666)) < 0) { + perror("open/create"); + return false; } close(fd); ConfTree conf(fn.c_str()); if (!conf.ok()) { - cerr << "Config init failed" << endl; - return false; + cerr << "Config init failed" << endl; + return false; } conf.set("nm-1", "val-1", ""); @@ -699,54 +735,55 @@ bool complex_updates(const string& fn) string data; file_to_string(fn, data, 0); const string ref = - "nm-1 = val-1\n" - "[/dir1]\n" - "nm-1 = val1-1\n" - "nm-2 = val1-2\n" - ; + "nm-1 = val-1\n" + "[/dir1]\n" + "nm-1 = val1-1\n" + "nm-2 = val1-2\n" + ; if (data.compare(ref)) { - cerr << "Final file:" << endl << data << endl << "Differs from ref:" << - endl << ref << endl; - return false; + cerr << "Final file:" << endl << data << endl << "Differs from ref:" << + endl << ref << endl; + return false; } else { - cout << "Updates test Ok" << endl; + cout << "Updates test Ok" << endl; } return true; } -ConfSimple::WalkerCode mywalker(void *, const string &nm, const string &value) +ConfSimple::WalkerCode mywalker(void *, const string& nm, const string& value) { - if (nm.empty()) - printf("\n[%s]\n", value.c_str()); - else - printf("'%s' -> '%s'\n", nm.c_str(), value.c_str()); + if (nm.empty()) { + printf("\n[%s]\n", value.c_str()); + } else { + printf("'%s' -> '%s'\n", nm.c_str(), value.c_str()); + } return ConfSimple::WALK_CONTINUE; } -const char *longvalue = -"Donnees012345678901234567890123456789012345678901234567890123456789AA" -"0123456789012345678901234567890123456789012345678901234567890123456789FIN" +const char *longvalue = + "Donnees012345678901234567890123456789012345678901234567890123456789AA" + "0123456789012345678901234567890123456789012345678901234567890123456789FIN" ; -void memtest(ConfSimple &c) +void memtest(ConfSimple& c) { cout << "Initial:" << endl; c.showall(); if (c.set("nom", "avec nl \n 2eme ligne", "")) { - fprintf(stderr, "set with embedded nl succeeded !\n"); - exit(1); + fprintf(stderr, "set with embedded nl succeeded !\n"); + exit(1); } if (!c.set(string("parm1"), string("1"), string("subkey1"))) { - fprintf(stderr, "Set error"); - exit(1); + fprintf(stderr, "Set error"); + exit(1); } if (!c.set("sparm", "Parametre \"string\" bla", "s2")) { - fprintf(stderr, "Set error"); - exit(1); + fprintf(stderr, "Set error"); + exit(1); } if (!c.set("long", longvalue, "")) { - fprintf(stderr, "Set error"); - exit(1); + fprintf(stderr, "Set error"); + exit(1); } cout << "Final:" << endl; @@ -756,34 +793,34 @@ void memtest(ConfSimple &c) bool readwrite(ConfNull *conf) { if (conf->ok()) { - // It's ok for the file to not exist here - string value; - - if (conf->get("mypid", value)) { - cout << "Value for mypid is [" << value << "]" << endl; - } else { - cout << "mypid not set" << endl; - } - - if (conf->get("unstring", value)) { - cout << "Value for unstring is ["<< value << "]" << endl; - } else { - cout << "unstring not set" << endl; - } + // It's ok for the file to not exist here + string value; + + if (conf->get("mypid", value)) { + cout << "Value for mypid is [" << value << "]" << endl; + } else { + cout << "mypid not set" << endl; + } + + if (conf->get("unstring", value)) { + cout << "Value for unstring is [" << value << "]" << endl; + } else { + cout << "unstring not set" << endl; + } } char spid[100]; sprintf(spid, "%d", getpid()); if (!conf->set("mypid", spid)) { - cerr << "Set mypid failed" << endl; + cerr << "Set mypid failed" << endl; } ostringstream ost; ost << "mypid" << getpid(); if (!conf->set(ost.str(), spid, "")) { - cerr << "Set mypid failed (2)" << endl; + cerr << "Set mypid failed (2)" << endl; } if (!conf->set("unstring", "Une jolie phrase pour essayer")) { - cerr << "Set unstring failed" << endl; + cerr << "Set unstring failed" << endl; } return true; } @@ -791,13 +828,13 @@ bool readwrite(ConfNull *conf) bool query(ConfNull *conf, const string& nm, const string& sub) { if (!conf->ok()) { - cerr << "Error opening or parsing file\n" << endl; - return false; + cerr << "Error opening or parsing file\n" << endl; + return false; } string value; if (!conf->get(nm, value, sub)) { - cerr << "name [" << nm << "] not found in [" << sub << "]" << endl; - return false; + cerr << "name [" << nm << "] not found in [" << sub << "]" << endl; + return false; } cout << "[" << sub << "] " << nm << " " << value << endl; return true; @@ -806,13 +843,13 @@ bool query(ConfNull *conf, const string& nm, const string& sub) bool erase(ConfNull *conf, const string& nm, const string& sub) { if (!conf->ok()) { - cerr << "Error opening or parsing file\n" << endl; - return false; + cerr << "Error opening or parsing file\n" << endl; + return false; } if (!conf->erase(nm, sub)) { - cerr << "delete name [" << nm << "] in ["<< sub << "] failed" << endl; - return false; + cerr << "delete name [" << nm << "] in [" << sub << "] failed" << endl; + return false; } return true; } @@ -820,27 +857,27 @@ bool erase(ConfNull *conf, const string& nm, const string& sub) bool eraseKey(ConfNull *conf, const string& sub) { if (!conf->ok()) { - cerr << "Error opening or parsing file\n" << endl; - return false; + cerr << "Error opening or parsing file\n" << endl; + return false; } if (!conf->eraseKey(sub)) { - cerr << "delete key [" << sub << "] failed" << endl; - return false; + cerr << "delete key [" << sub << "] failed" << endl; + return false; } return true; } -bool setvar(ConfNull *conf, const string& nm, const string& value, - const string& sub) +bool setvar(ConfNull *conf, const string& nm, const string& value, + const string& sub) { if (!conf->ok()) { - cerr << "Error opening or parsing file\n" << endl; - return false; + cerr << "Error opening or parsing file\n" << endl; + return false; } if (!conf->set(nm, value, sub)) { - cerr << "Set error\n" << endl; - return false; + cerr << "Set error\n" << endl; + return false; } return true; } @@ -855,16 +892,17 @@ static char usage [] = "-E sect : erase key (and all its names)\n" "-S : string io test. No filename in this case\n" "-V : volatile config test. No filename in this case\n" - "-U : complex update test. Will erase the named file parameter\n" + "-U : complex update test. Will erase the named file parameter\n" ; -void Usage() { +void Usage() +{ fprintf(stderr, "%s:%s\n", thisprog, usage); exit(1); } static int op_flags; #define OPT_MOINS 0x1 -#define OPT_w 0x2 +#define OPT_w 0x2 #define OPT_q 0x4 #define OPT_s 0x8 #define OPT_S 0x10 @@ -882,160 +920,196 @@ int main(int argc, char **argv) const char *value = 0; thisprog = argv[0]; - argc--; argv++; + argc--; + argv++; while (argc > 0 && **argv == '-') { - (*argv)++; - if (!(**argv)) - /* Cas du "adb - core" */ - Usage(); - while (**argv) - switch (*(*argv)++) { - case 'a': - op_flags |= OPT_a; - if (argc < 4) - Usage(); - nm = *(++argv);argc--; - value = *(++argv);argc--; - sub = *(++argv);argc--; - goto b1; - case 'd': - op_flags |= OPT_d; - if (argc < 3) - Usage(); - nm = *(++argv);argc--; - sub = *(++argv);argc--; - goto b1; - case 'E': - op_flags |= OPT_E; - if (argc < 2) - Usage(); - sub = *(++argv);argc--; - goto b1; - case 'k': op_flags |= OPT_k; break; - case 'q': - op_flags |= OPT_q; - if (argc < 3) - Usage(); - nm = *(++argv);argc--; - sub = *(++argv);argc--; - goto b1; - case 's': op_flags |= OPT_s; break; - case 'S': op_flags |= OPT_S; break; - case 'V': op_flags |= OPT_V; break; - case 'U': op_flags |= OPT_U; break; - case 'w': op_flags |= OPT_w; break; + (*argv)++; + if (!(**argv)) + /* Cas du "adb - core" */ + { + Usage(); + } + while (**argv) + switch (*(*argv)++) { + case 'a': + op_flags |= OPT_a; + if (argc < 4) { + Usage(); + } + nm = *(++argv); + argc--; + value = *(++argv); + argc--; + sub = *(++argv); + argc--; + goto b1; + case 'd': + op_flags |= OPT_d; + if (argc < 3) { + Usage(); + } + nm = *(++argv); + argc--; + sub = *(++argv); + argc--; + goto b1; + case 'E': + op_flags |= OPT_E; + if (argc < 2) { + Usage(); + } + sub = *(++argv); + argc--; + goto b1; + case 'k': + op_flags |= OPT_k; + break; + case 'q': + op_flags |= OPT_q; + if (argc < 3) { + Usage(); + } + nm = *(++argv); + argc--; + sub = *(++argv); + argc--; + goto b1; + case 's': + op_flags |= OPT_s; + break; + case 'S': + op_flags |= OPT_S; + break; + case 'V': + op_flags |= OPT_V; + break; + case 'U': + op_flags |= OPT_U; + break; + case 'w': + op_flags |= OPT_w; + break; - default: Usage(); break; - } - b1: argc--; argv++; + default: + Usage(); + break; + } +b1: + argc--; + argv++; } if ((op_flags & OPT_S)) { - // String storage test - if (argc != 0) - Usage(); - string s; - ConfSimple c(s); - memtest(c); - exit(0); - } else if ((op_flags & OPT_V)) { - // No storage test - if (argc != 0) - Usage(); - ConfSimple c; - memtest(c); - exit(0); - } + // String storage test + if (argc != 0) { + Usage(); + } + string s; + ConfSimple c(s); + memtest(c); + exit(0); + } else if ((op_flags & OPT_V)) { + // No storage test + if (argc != 0) { + Usage(); + } + ConfSimple c; + memtest(c); + exit(0); + } // Other tests use file(s) as backing store - if (argc < 1) - Usage(); + if (argc < 1) { + Usage(); + } if (op_flags & OPT_U) { - exit(!complex_updates(argv[0])); + exit(!complex_updates(argv[0])); } vector flist; while (argc--) { - flist.push_back(*argv++); + flist.push_back(*argv++); } - bool ro = !(op_flags & (OPT_w|OPT_a|OPT_d|OPT_E)); + bool ro = !(op_flags & (OPT_w | OPT_a | OPT_d | OPT_E)); ConfNull *conf = 0; switch (flist.size()) { case 0: - Usage(); - break; + Usage(); + break; case 1: - conf = new ConfTree(flist.front().c_str(), ro); - break; + conf = new ConfTree(flist.front().c_str(), ro); + break; default: - conf = new ConfStack(flist, ro); - break; + conf = new ConfStack(flist, ro); + break; } if (op_flags & OPT_w) { - exit(!readwrite(conf)); + exit(!readwrite(conf)); } else if (op_flags & OPT_q) { - exit(!query(conf, nm, sub)); + exit(!query(conf, nm, sub)); } else if (op_flags & OPT_k) { - if (!conf->ok()) { - cerr << "conf init error" << endl; - exit(1); - } - vectorlst = conf->getSubKeys(); - for (vector::const_iterator it = lst.begin(); - it != lst.end(); it++) { - cout << *it << endl; - } - exit(0); + if (!conf->ok()) { + cerr << "conf init error" << endl; + exit(1); + } + vectorlst = conf->getSubKeys(); + for (vector::const_iterator it = lst.begin(); + it != lst.end(); it++) { + cout << *it << endl; + } + exit(0); } else if (op_flags & OPT_a) { - exit(!setvar(conf, nm, value, sub)); + exit(!setvar(conf, nm, value, sub)); } else if (op_flags & OPT_d) { - exit(!erase(conf, nm, sub)); + exit(!erase(conf, nm, sub)); } else if (op_flags & OPT_E) { - exit(!eraseKey(conf, sub)); + exit(!eraseKey(conf, sub)); } else if (op_flags & OPT_s) { - if (!conf->ok()) { - cerr << "Cant open /parse conf file " << endl; - exit(1); - } - - string source; - if (!conf->get(string("strings"), source, "")) { - cerr << "Cant get param 'strings'" << endl; - exit(1); - } - cout << "source: [" << source << "]" << endl; - vector strings; - if (!stringToStrings(source, strings)) { - cerr << "parse failed" << endl; - exit(1); - } - - for (vector::iterator it = strings.begin(); - it != strings.end(); it++) { - cout << "[" << *it << "]" << endl; - } - + if (!conf->ok()) { + cerr << "Cant open /parse conf file " << endl; + exit(1); + } + + string source; + if (!conf->get(string("strings"), source, "")) { + cerr << "Cant get param 'strings'" << endl; + exit(1); + } + cout << "source: [" << source << "]" << endl; + vector strings; + if (!stringToStrings(source, strings)) { + cerr << "parse failed" << endl; + exit(1); + } + + for (vector::iterator it = strings.begin(); + it != strings.end(); it++) { + cout << "[" << *it << "]" << endl; + } + } else { - if (!conf->ok()) { - fprintf(stderr, "Open failed\n"); - exit(1); - } - printf("LIST\n"); - conf->showall(); - //printf("WALK\n");conf->sortwalk(mywalker, 0); - printf("\nNAMES in global space:\n"); - vector names = conf->getNames(""); - for (vector::iterator it = names.begin(); - it!=names.end(); it++) - cout << *it << " "; + if (!conf->ok()) { + fprintf(stderr, "Open failed\n"); + exit(1); + } + printf("LIST\n"); + conf->showall(); + //printf("WALK\n");conf->sortwalk(mywalker, 0); + printf("\nNAMES in global space:\n"); + vector names = conf->getNames(""); + for (vector::iterator it = names.begin(); + it != names.end(); it++) { + cout << *it << " "; + } cout << endl; - printf("\nNAMES in global space matching t* \n"); - names = conf->getNames("", "t*"); - for (vector::iterator it = names.begin(); - it!=names.end(); it++) - cout << *it << " "; + printf("\nNAMES in global space matching t* \n"); + names = conf->getNames("", "t*"); + for (vector::iterator it = names.begin(); + it != names.end(); it++) { + cout << *it << " "; + } cout << endl; } } diff --git a/src/utils/conftree.h b/src/utils/conftree.h index 7ea85a69..a3910ae2 100644 --- a/src/utils/conftree.h +++ b/src/utils/conftree.h @@ -23,23 +23,23 @@ * Configuration files have lines like 'name = value', and/or like '[subkey]' * * Lines like '[subkey]' in the file define subsections, with independant - * configuration namespaces. Only subsections holding at least one variable are + * configuration namespaces. Only subsections holding at least one variable are * significant (empty subsections may be deleted during an update, or not) * * Whitespace around name and value is insignificant. * * The names are case-sensitive but don't depend on it, this might change * - * Values can be queried for, or set. + * Values can be queried for, or set. * * Any line without a '=' is a comment (a line like #var = value * actually assigns a variable named '#var', which is not a big issue) * * A configuration object can be created empty or by reading from a file or * a string. - * All 'set' calls cause an immediate rewrite of the backing object if any - * (file or string) - * + * All 'set' calls cause an immediate rewrite of the backing object if any + * (file or string) + * * The ConfTree derived class interprets the subkeys as file paths and * lets subdir keys hierarchically inherit the properties from * parents. @@ -49,10 +49,10 @@ * (useful to have central/personal config files) */ -#include -#include -#include #include +#include +#include +#include // rh7.3 likes iostream better... #if defined(__GNUC__) && __GNUC__ < 3 @@ -62,15 +62,13 @@ #include #endif -#ifndef NO_NAMESPACES +#include "pathut.h" + using std::string; using std::vector; using std::map; using std::istream; using std::ostream; -#endif // NO_NAMESPACES - -#include "pathut.h" /** Internal class used for storing presentation information */ class ConfLine { @@ -78,32 +76,30 @@ public: enum Kind {CFL_COMMENT, CFL_SK, CFL_VAR}; Kind m_kind; string m_data; - ConfLine(Kind k, const string& d) - : m_kind(k), m_data(d) - { + ConfLine(Kind k, const string& d) + : m_kind(k), m_data(d) { } - bool operator==(const ConfLine& o) - { - return o.m_kind == m_kind && o.m_data == m_data; + bool operator==(const ConfLine& o) { + return o.m_kind == m_kind && o.m_data == m_data; } }; -/** +/** * Virtual base class used to define an interface mostly useful for testing */ class ConfNull { public: - enum StatusCode {STATUS_ERROR=0, STATUS_RO=1, STATUS_RW=2}; + enum StatusCode {STATUS_ERROR = 0, STATUS_RO = 1, STATUS_RW = 2}; virtual ~ConfNull() {}; - virtual int get(const string &name, string &value, - const string &sk = string()) const = 0; + virtual int get(const string& name, string& value, + const string& sk = string()) const = 0; virtual bool hasNameAnywhere(const string& nm) const = 0; - virtual int set(const string &nm, const string &val, - const string &sk = string()) = 0; + virtual int set(const string& nm, const string& val, + const string& sk = string()) = 0; virtual bool ok() const = 0; - virtual vector getNames(const string &sk, const char* = 0)const = 0; - virtual int erase(const string &, const string &) = 0; - virtual int eraseKey(const string &) = 0; + virtual vector getNames(const string& sk, const char* = 0)const = 0; + virtual int erase(const string&, const string&) = 0; + virtual int eraseKey(const string&) = 0; virtual void showall() const {}; virtual vector getSubKeys() const = 0; virtual vector getSubKeys(bool) const = 0; @@ -111,7 +107,7 @@ public: virtual bool sourceChanged() const = 0; }; -/** +/** * Manages a simple configuration file with subsections. */ class ConfSimple : public ConfNull { @@ -127,7 +123,7 @@ public: /** * Build the object by reading content from a string - * @param data points to the data to parse. + * @param data points to the data to parse. * @param readonly if true open readonly, else rw * @param tildexp try tilde (home dir) expansion for subsection names */ @@ -145,120 +141,122 @@ public: /** Origin file changed. Only makes sense if we read the data from a file */ virtual bool sourceChanged() const; - /** + /** * Decide if we actually rewrite the backing-store after modifying the * tree. */ - virtual bool holdWrites(bool on) - { - m_holdWrites = on; - if (on == false) { - return write(); - } else - return true; + virtual bool holdWrites(bool on) { + m_holdWrites = on; + if (on == false) { + return write(); + } else { + return true; + } } /** Clear, then reparse from string */ void reparse(const string& in); /** Clear all content */ - void clear() - { - m_submaps.clear(); - m_order.clear(); + void clear() { + m_submaps.clear(); + m_order.clear(); } - /** - * Get value for named parameter, from specified subsection (looks in + /** + * Get value for named parameter, from specified subsection (looks in * global space if sk is empty). * @return 0 if name not found, 1 else */ - virtual int get(const string &name, string &value, - const string &sk = string()) const; + virtual int get(const string& name, string& value, + const string& sk = string()) const; - /** + /** * Set value for named parameter in specified subsection (or global) * @return 0 for error, 1 else */ - virtual int set(const string &nm, const string &val, - const string &sk = string()); + virtual int set(const string& nm, const string& val, + const string& sk = string()); /** * Remove name and value from config */ - virtual int erase(const string &name, const string &sk); + virtual int erase(const string& name, const string& sk); /** * Erase all names under given subkey (and subkey itself) */ - virtual int eraseKey(const string &sk); + virtual int eraseKey(const string& sk); virtual StatusCode getStatus() const; - virtual bool ok() const {return getStatus() != STATUS_ERROR;} + virtual bool ok() const { + return getStatus() != STATUS_ERROR; + } - /** + /** * Walk the configuration values, calling function for each. - * The function is called with a null nm when changing subsections (the + * The function is called with a null nm when changing subsections (the * value is then the new subsection name) - * @return WALK_STOP when/if the callback returns WALK_STOP, + * @return WALK_STOP when/if the callback returns WALK_STOP, * WALK_CONTINUE else (got to end of config) */ enum WalkerCode {WALK_STOP, WALK_CONTINUE}; - virtual WalkerCode sortwalk(WalkerCode - (*wlkr)(void *cldata, const string &nm, - const string &val), - void *clidata) const; + virtual WalkerCode sortwalk(WalkerCode + (*wlkr)(void *cldata, const string& nm, + const string& val), + void *clidata) const; /** Print all values to stdout */ virtual void showall() const; /** Return all names in given submap. */ - virtual vector getNames(const string &sk, const char *pattern = 0) - const; + virtual vector getNames(const string& sk, const char *pattern = 0) + const; /** Check if name is present in any submap. This is relatively expensive * but useful for saving further processing sometimes */ virtual bool hasNameAnywhere(const string& nm) const; /** - * Return all subkeys + * Return all subkeys */ - virtual vector getSubKeys(bool) const - { - return getSubKeys(); + virtual vector getSubKeys(bool) const { + return getSubKeys(); + } + virtual vector getSubKeys_unsorted(bool = false) const { + return m_subkeys_unsorted; } virtual vector getSubKeys() const; /** Test for subkey existence */ - virtual bool hasSubKey(const string& sk) const - { - return m_submaps.find(sk) != m_submaps.end(); + virtual bool hasSubKey(const string& sk) const { + return m_submaps.find(sk) != m_submaps.end(); } - virtual string getFilename() const - {return m_filename;} + virtual string getFilename() const { + return m_filename; + } /** * Copy constructor. Expensive but less so than a full rebuild */ - ConfSimple(const ConfSimple &rhs) - : ConfNull() - { - if ((status = rhs.status) == STATUS_ERROR) - return; - m_filename = rhs.m_filename; - m_submaps = rhs.m_submaps; + ConfSimple(const ConfSimple& rhs) + : ConfNull() { + if ((status = rhs.status) == STATUS_ERROR) { + return; + } + m_filename = rhs.m_filename; + m_submaps = rhs.m_submaps; } /** * Assignement. This is expensive */ - ConfSimple& operator=(const ConfSimple &rhs) - { - if (this != &rhs && (status = rhs.status) != STATUS_ERROR) { - m_filename = rhs.m_filename; - m_submaps = rhs.m_submaps; - } - return *this; + ConfSimple& operator=(const ConfSimple& rhs) { + if (this != &rhs && (status = rhs.status) != STATUS_ERROR) { + m_filename = rhs.m_filename; + m_submaps = rhs.m_submaps; + } + return *this; } /** @@ -271,11 +269,12 @@ protected: StatusCode status; private: // Set if we're working with a file - string m_filename; + string m_filename; time_t m_fmtime; // Configuration data submaps (one per subkey, the main data has a // null subkey) map > m_submaps; + vector m_subkeys_unsorted; // Presentation data. We keep the comments, empty lines and // variable and subkey ordering information in there (for // rewriting the file while keeping hand-edited information) @@ -286,8 +285,8 @@ private: void parseinput(istream& input); bool write(); // Internal version of set: no RW checking - virtual int i_set(const string &nm, const string &val, - const string &sk, bool init = false); + virtual int i_set(const string& nm, const string& val, + const string& sk, bool init = false); bool i_changed(bool upd); }; @@ -295,7 +294,7 @@ private: * This is a configuration class which attaches tree-like signification to the * submap names. * - * If a given variable is not found in the specified section, it will be + * If a given variable is not found in the specified section, it will be * looked up the tree of section names, and in the global space. * * submap names should be '/' separated paths (ie: /sub1/sub2). No checking @@ -305,43 +304,42 @@ private: * designated by '/' but by '' (empty subkey). A '/' subkey will not * be searched at all. * - * Note: getNames() : uses ConfSimple method, this does *not* inherit + * Note: getNames() : uses ConfSimple method, this does *not* inherit * names from englobing submaps. */ class ConfTree : public ConfSimple { public: - /* The constructors just call ConfSimple's, asking for key tilde + /* The constructors just call ConfSimple's, asking for key tilde * expansion */ - ConfTree(const char *fname, int readonly = 0) - : ConfSimple(fname, readonly, true) {} - ConfTree(const string &data, int readonly = 0) - : ConfSimple(data, readonly, true) {} + ConfTree(const char *fname, int readonly = 0) + : ConfSimple(fname, readonly, true) {} + ConfTree(const string& data, int readonly = 0) + : ConfSimple(data, readonly, true) {} ConfTree(int readonly = 0) - : ConfSimple(readonly, true) {} + : ConfSimple(readonly, true) {} virtual ~ConfTree() {}; - ConfTree(const ConfTree& r) : ConfSimple(r) {}; - ConfTree& operator=(const ConfTree& r) - { - ConfSimple::operator=(r); - return *this; + ConfTree(const ConfTree& r) : ConfSimple(r) {}; + ConfTree& operator=(const ConfTree& r) { + ConfSimple::operator=(r); + return *this; } - /** - * Get value for named parameter, from specified subsection, or its + /** + * Get value for named parameter, from specified subsection, or its * parents. * @return 0 if name not found, 1 else */ - virtual int get(const string &name, string &value, const string &sk) const; + virtual int get(const string& name, string& value, const string& sk) const; }; -/** +/** * Use several config files, trying to get values from each in order. Used to * have a central config, with possible overrides from more specific * (ie personal) ones. * * Notes: it's ok for some of the files not to exist, but the last - * one must or we generate an error. We open all trees readonly, except the + * one must or we generate an error. We open all trees readonly, except the * topmost one if requested. All writes go to the topmost file. Note that * erase() won't work except for parameters only defined in the topmost * file (it erases only from there). @@ -351,178 +349,171 @@ public: /// Construct from configuration file names. The earler /// files in have priority when fetching values. Only the first /// file will be updated if ro is false and set() is used. - ConfStack(const vector &fns, bool ro = true) - { - construct(fns, ro); + ConfStack(const vector& fns, bool ro = true) { + construct(fns, ro); } /// Construct out of single file name and multiple directories - ConfStack(const string& nm, const vector& dirs, bool ro = true) - { - vector fns; - for (vector::const_iterator it = dirs.begin(); - it != dirs.end(); it++){ - fns.push_back(path_cat(*it, nm)); - } - ConfStack::construct(fns, ro); + ConfStack(const string& nm, const vector& dirs, bool ro = true) { + vector fns; + for (vector::const_iterator it = dirs.begin(); + it != dirs.end(); it++) { + fns.push_back(path_cat(*it, nm)); + } + ConfStack::construct(fns, ro); } - ConfStack(const ConfStack &rhs) - : ConfNull() - { - init_from(rhs); + ConfStack(const ConfStack& rhs) + : ConfNull() { + init_from(rhs); } - virtual ~ConfStack() - { - clear(); - m_ok = false; + virtual ~ConfStack() { + clear(); + m_ok = false; } - ConfStack& operator=(const ConfStack &rhs) - { - if (this != &rhs){ - clear(); - m_ok = rhs.m_ok; - if (m_ok) - init_from(rhs); - } - return *this; + ConfStack& operator=(const ConfStack& rhs) { + if (this != &rhs) { + clear(); + m_ok = rhs.m_ok; + if (m_ok) { + init_from(rhs); + } + } + return *this; } - virtual bool sourceChanged() const - { - typename vector::const_iterator it; - for (it = m_confs.begin();it != m_confs.end();it++) { - if ((*it)->sourceChanged()) - return true; - } - return false; + virtual bool sourceChanged() const { + typename vector::const_iterator it; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + if ((*it)->sourceChanged()) { + return true; + } + } + return false; } - virtual int get(const string &name, string &value, const string &sk, - bool shallow) const - { - typename vector::const_iterator it; - for (it = m_confs.begin();it != m_confs.end();it++) { - if ((*it)->get(name, value, sk)) - return true; - if (shallow) + virtual int get(const string& name, string& value, const string& sk, + bool shallow) const { + typename vector::const_iterator it; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + if ((*it)->get(name, value, sk)) { + return true; + } + if (shallow) { break; - } - return false; + } + } + return false; } - virtual int get(const string &name, string &value, const string &sk) const { + virtual int get(const string& name, string& value, const string& sk) const { return get(name, value, sk, false); } - virtual bool hasNameAnywhere(const string& nm) const - { - typename vector::const_iterator it; - for (it = m_confs.begin();it != m_confs.end();it++) { - if ((*it)->hasNameAnywhere(nm)) - return true; - } - return false; + virtual bool hasNameAnywhere(const string& nm) const { + typename vector::const_iterator it; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + if ((*it)->hasNameAnywhere(nm)) { + return true; + } + } + return false; } - virtual int set(const string &nm, const string &val, - const string &sk = string()) - { - if (!m_ok) - return 0; - //LOGDEB2(("ConfStack::set [%s]:[%s] -> [%s]\n", sk.c_str(), - //nm.c_str(), val.c_str())); - // Avoid adding unneeded entries: if the new value matches the - // one out from the deeper configs, erase or dont add it - // from/to the topmost file - typename vector::iterator it = m_confs.begin(); - it++; - while (it != m_confs.end()) { - string value; - if ((*it)->get(nm, value, sk)) { - // This file has value for nm/sk. If it is the same as the new - // one, no need for an entry in the topmost file. Else, stop - // looking and add the new entry - if (value == val) { - m_confs.front()->erase(nm, sk); - return true; - } else { - break; - } - } - it++; - } + virtual int set(const string& nm, const string& val, + const string& sk = string()) { + if (!m_ok) { + return 0; + } + //LOGDEB2(("ConfStack::set [%s]:[%s] -> [%s]\n", sk.c_str(), + //nm.c_str(), val.c_str())); + // Avoid adding unneeded entries: if the new value matches the + // one out from the deeper configs, erase or dont add it + // from/to the topmost file + typename vector::iterator it = m_confs.begin(); + it++; + while (it != m_confs.end()) { + string value; + if ((*it)->get(nm, value, sk)) { + // This file has value for nm/sk. If it is the same as the new + // one, no need for an entry in the topmost file. Else, stop + // looking and add the new entry + if (value == val) { + m_confs.front()->erase(nm, sk); + return true; + } else { + break; + } + } + it++; + } - return m_confs.front()->set(nm, val, sk); + return m_confs.front()->set(nm, val, sk); } - virtual int erase(const string &nm, const string &sk) - { - return m_confs.front()->erase(nm, sk); + virtual int erase(const string& nm, const string& sk) { + return m_confs.front()->erase(nm, sk); } - virtual int eraseKey(const string &sk) - { - return m_confs.front()->eraseKey(sk); + virtual int eraseKey(const string& sk) { + return m_confs.front()->eraseKey(sk); } - virtual bool holdWrites(bool on) - { - return m_confs.front()->holdWrites(on); + virtual bool holdWrites(bool on) { + return m_confs.front()->holdWrites(on); } - virtual vector getNames(const string &sk, const char *pattern = 0) - const - { - return getNames1(sk, pattern, false); + virtual vector getNames(const string& sk, const char *pattern = 0) + const { + return getNames1(sk, pattern, false); } - virtual vector getNamesShallow(const string &sk, - const char *patt = 0) const - { - return getNames1(sk, patt, true); + virtual vector getNamesShallow(const string& sk, + const char *patt = 0) const { + return getNames1(sk, patt, true); } - virtual vector getNames1(const string &sk, const char *pattern, - bool shallow) const - { - vector nms; - typename vector::const_iterator it; - bool skfound = false; - for (it = m_confs.begin(); it != m_confs.end(); it++) { - if ((*it)->hasSubKey(sk)) { - skfound = true; - vector lst = (*it)->getNames(sk, pattern); - nms.insert(nms.end(), lst.begin(), lst.end()); - } - if (shallow && skfound) - break; - } - sort(nms.begin(), nms.end()); - vector::iterator uit = unique(nms.begin(), nms.end()); - nms.resize(uit - nms.begin()); - return nms; + virtual vector getNames1(const string& sk, const char *pattern, + bool shallow) const { + vector nms; + typename vector::const_iterator it; + bool skfound = false; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + if ((*it)->hasSubKey(sk)) { + skfound = true; + vector lst = (*it)->getNames(sk, pattern); + nms.insert(nms.end(), lst.begin(), lst.end()); + } + if (shallow && skfound) { + break; + } + } + sort(nms.begin(), nms.end()); + vector::iterator uit = unique(nms.begin(), nms.end()); + nms.resize(uit - nms.begin()); + return nms; } - virtual vector getSubKeys() const - { - return getSubKeys(false); + virtual vector getSubKeys() const { + return getSubKeys(false); } - virtual vector getSubKeys(bool shallow) const - { - vector sks; - typename vector::const_iterator it; - for (it = m_confs.begin(); it != m_confs.end(); it++) { - vector lst; - lst = (*it)->getSubKeys(); - sks.insert(sks.end(), lst.begin(), lst.end()); - if (shallow) - break; - } - sort(sks.begin(), sks.end()); - vector::iterator uit = unique(sks.begin(), sks.end()); - sks.resize(uit - sks.begin()); - return sks; + virtual vector getSubKeys(bool shallow) const { + vector sks; + typename vector::const_iterator it; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + vector lst; + lst = (*it)->getSubKeys(); + sks.insert(sks.end(), lst.begin(), lst.end()); + if (shallow) { + break; + } + } + sort(sks.begin(), sks.end()); + vector::iterator uit = unique(sks.begin(), sks.end()); + sks.resize(uit - sks.begin()); + return sks; } - virtual bool ok() const {return m_ok;} + virtual bool ok() const { + return m_ok; + } private: bool m_ok; @@ -530,44 +521,44 @@ private: /// Reset to pristine void clear() { - typename vector::iterator it; - for (it = m_confs.begin();it != m_confs.end();it++) { - delete (*it); - } - m_confs.clear(); + typename vector::iterator it; + for (it = m_confs.begin(); it != m_confs.end(); it++) { + delete(*it); + } + m_confs.clear(); } /// Common code to initialize from existing object - void init_from(const ConfStack &rhs) { - if ((m_ok = rhs.m_ok)) { - typename vector::const_iterator it; - for (it = rhs.m_confs.begin();it != rhs.m_confs.end();it++) { - m_confs.push_back(new T(**it)); - } - } + void init_from(const ConfStack& rhs) { + if ((m_ok = rhs.m_ok)) { + typename vector::const_iterator it; + for (it = rhs.m_confs.begin(); it != rhs.m_confs.end(); it++) { + m_confs.push_back(new T(**it)); + } + } } /// Common construct from file names code - void construct(const vector &fns, bool ro) { - vector::const_iterator it; - bool lastok = false; - for (it = fns.begin(); it != fns.end(); it++) { - T* p = new T(it->c_str(), ro); - if (p && p->ok()) { - m_confs.push_back(p); - lastok = true; - } else { - delete p; - lastok = false; - if (!ro) { - // For rw acccess, the topmost file needs to be ok - // (ro is set to true after the first file) - break; - } - } - ro = true; - } - m_ok = lastok; + void construct(const vector& fns, bool ro) { + vector::const_iterator it; + bool lastok = false; + for (it = fns.begin(); it != fns.end(); it++) { + T* p = new T(it->c_str(), ro); + if (p && p->ok()) { + m_confs.push_back(p); + lastok = true; + } else { + delete p; + lastok = false; + if (!ro) { + // For rw acccess, the topmost file needs to be ok + // (ro is set to true after the first file) + break; + } + } + ro = true; + } + m_ok = lastok; } };