/* * Copyright (c) 2002, Stefan Farfeleder * $Id: conffile.cc,v 1.2 2002/09/10 16:43:18 stefan Exp $ */ #include #include #include #include #include #include #include #include #include "conffile.h" #include "exception.h" using std::map; using std::string; using namespace JFK; /* * 'ce' points to an array of 'n' variable that are allowed variables in * 'filename'. */ conffile::conffile(const variable* ce, size_t n, const char* filename) : fn(filename) { char* p; /* replace leading ~ with $HOME if the latter is set */ if (std::strncmp(filename, "~/", 2) == 0 && (p = std::getenv("HOME")) != NULL) { fn.replace(0, 1, p); } /* load variables list into the map */ for (size_t i = 0; i < n; i++) { if (ce[i].def_val != NULL) m[ce[i].name].value = ce[i].def_val; m[ce[i].name].ce = &ce[i]; } } /* * Strip white space at the front and the back. */ static string remove_ws(const string& s) { string::size_type front; string::size_type back; for (front = 0; isspace((unsigned char)s[front]); front++) ; for (back = s.size(); back > 0 && isspace((unsigned char)s[back - 1]); back--) ; return s.substr(front, back - front); } /* * Read the file (name given to constructor) and store the values into the * map. */ void conffile::read() { std::ifstream file(fn.c_str()); /* Do not complain about a missing config file. However getvar() of a * variable without a default value will fail. */ if (!file.is_open()) return; string line; for (int linenr = 1; std::getline(file, line); linenr++) { string name; string value; /* skip emtpy and comment lines */ if (line.size() == 0 || line[0] == '#') continue; string::size_type asmt_pos = line.find('='); /* '=' found */ if (asmt_pos != line.npos) { name = remove_ws(line.substr(0, asmt_pos)); value = remove_ws(line.substr(asmt_pos + 1)); } /* no '=' found or emtpy strings */ if (name.size() == 0 || value.size() == 0) { std::ostringstream msg; msg << fn << ':' << linenr << ": syntax error"; throw exception(msg.str()); } setvar(name, value); } } void conffile::write() { /* TODO */ } /* * Return the value of the variable 'name'. Variables not included in the * variable list are considered as an error. */ const string conffile::getvar(const string& name) const { varmap::const_iterator i = m.find(name); if (i == m.end()) throw exception("variable '" + name + "' unknown"); if (i->second.value == "" && i->second.ce->def_val == NULL) throw exception("variable '" + name + "' must be set in " + fn); return i->second.value; } /* * Set the value of the variable 'name' to 'val' (after the checking its * validity). Variables not included in the variable list are considered * as an error. */ void conffile::setvar(const string& name, const string& val) { varmap::iterator i = m.find(name); if (i == m.end()) throw exception("variable '" + name + "' unknown"); const variable& c = *i->second.ce; if (c.value_checker != NULL) { if (!c.value_checker(val)) throw exception('\'' + val + "\' unacceptable value for '" + name + '\''); } i->second.value = val; }