// ndppd - NDP Proxy Daemon // Copyright (C) 2011 Daniel Adolfsson // // 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 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include #include #include #include #include #include #include #include #include "ndppd.h" NDPPD_NS_BEGIN conf::conf() : _is_block(false) { } conf::operator int() const { return as_int(); } conf::operator const std::string&() const { return as_str(); } conf::operator bool() const { return as_bool(); } bool conf::as_bool() const { if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes")) return true; else return false; } const std::string& conf::as_str() const { return _value; } int conf::as_int() const { return atoi(_value.c_str()); } bool conf::empty() const { return _value == ""; } ptr conf::load(const std::string& path) { try { std::ifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); ifs.open(path.c_str(), std::ios::in); ifs.exceptions(std::ifstream::badbit); std::string buf((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); const char* c_buf = buf.c_str(); ptr cf(new conf); if (cf->parse_block(&c_buf)) { cf->dump(LOG_DEBUG); return cf; } logger::error() << "Could not parse configuration file"; } catch (std::ifstream::failure e) { logger::error() << "Failed to load configuration file '" << path << "'"; } return ptr(); } bool conf::is_block() const { return _is_block; } const char* conf::skip(const char* str, bool all) { if (!all) { while (*str && (*str != '\n') && isspace(*str)) str++; return str; } while (*str) { while (*str && isspace(*str)) str++; if (!*str) break; if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) { while (*str && (*str != '\n')) str++; continue; } if ((*str == '/') && (*(str + 1) == '*')) { while (*str) { if ((*str == '*') && (*(str + 1) == '/')) { str += 2; break; } str++; } continue; } break; } return str; } bool conf::parse_block(const char** str) { const char* p = *str; _is_block = true; while (*p) { std::stringstream ss; p = skip(p, true); if ((*p == '}') || !*p) { *str = p; return true; } while (*p && isalpha(*p)) { ss << *p++; } p = skip(p); if (*p == '=') { p++; } ptr cf(new conf); if (cf->parse(&p)) { _map.insert(std::pair >(ss.str(), cf)); } } *str = p; return true; } bool conf::parse(const char** str) { const char* p = *str; std::stringstream ss; p = skip(p, false); if (!*p) { return false; } else if ((*p == '\'') || (*p == '"')) { for (char e = *p++; *p && (*p != e); p++) ss <<* p; } else if (isalnum(*p)) { while (*p && (isalnum(*p) || strchr(":/.",* p))) ss <<* p++; } else { _value = ""; *str = p; return true; } _value = ss.str(); p = skip(p, false); if (*p == '{') { p++; if (!parse_block(&p)) return false; if (*p != '}') return false; p++; } *str = p; return true; } void conf::dump(int pri) const { logger l(pri); dump(l, 0); } void conf::dump(logger& l, int level) const { int i; std::string pfx; for (int i = 0; i < level; i++) { pfx += " "; } if (_value != "") { l << _value << " "; } if (_is_block) { l << "{" << logger::endl; std::multimap >::const_iterator it; for (it = _map.begin(); it != _map.end(); it++) { l << pfx << " " << it->first << " "; it->second->dump(l, level + 1); } l << pfx << "}" << logger::endl; } l << logger::endl; } ptr conf::operator()(const std::string& name, int index) const { return find(name, index); } ptr conf::find(const std::string& name, int index) const { std::multimap >::const_iterator it; for (it = _map.find(name); it != _map.end(); it++) { if (index-- <= 0) return it->second; } return ptr(); } ptr conf::operator[](const std::string& name) const { return find(name, 0); } std::vector > conf::find_all(const std::string& name) const { std::vector > vec; std::multimap >::const_iterator it; std::pair >::const_iterator, std::multimap >::const_iterator> ret; ret = _map.equal_range(name); for (it = ret.first; it != ret.second; it++) { vec.push_back(it->second); } return vec; } conf::operator const std::string&() { return _value; } NDPPD_NS_END