ndppd/src/conf.cc
Jiri Kosina fe5fe8e894 ndppd: remove unused variables
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Daniel Adolfsson <daniel@priv.nu>
2012-03-08 00:25:47 +01:00

289 lines
5.8 KiB
C++

// ndppd - NDP Proxy Daemon
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
//
// 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 <http://www.gnu.org/licenses/>.
#include <cstdio>
#include <cstdarg>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <memory>
#include <string>
#include <iostream>
#include <fstream>
#include <netinet/ip6.h>
#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> 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<char>(ifs)), std::istreambuf_iterator<char>());
const char* c_buf = buf.c_str();
ptr<conf> 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<conf>();
}
bool conf::is_block() const
{
return _is_block;
}
const char* conf::skip(const char* str, bool newlines)
{
while (*str) {
while (*str && isspace(*str) && ((*str != '\n') || newlines))
str++;
if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) {
while (*str && (*str != '\n')) {
str++;
}
} else if ((*str == '/') && (*(str + 1) == '*')) {
while (*str) {
if ((*str == '*') && (*(str + 1) == '/')) {
str += 2;
break;
}
str++;
}
} else {
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 (isalnum(*p) || (*p == '_') || (*p == '-')) {
ss << *p++;
}
p = skip(p, false);
if (*p == '=') {
p++;
p = skip(p, false);
}
ptr<conf> cf(new conf);
if (cf->parse(&p)) {
_map.insert(std::pair<std::string, ptr<conf> >(ss.str(), cf));
} else {
return false;
}
}
*str = p;
return true;
}
bool conf::parse(const char** str)
{
const char* p = *str;
std::stringstream ss;
p = skip(p, false);
if ((*p == '\'') || (*p == '"')) {
for (char e = *p++; *p && (*p != e) && (*p != '\n'); p++)
ss << *p;
p = skip(p, false);
} else {
while (*p && isgraph(*p) && (*p != '{') && (*p != '}')) {
ss << *p++;
}
}
_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
{
std::string pfx;
for (int i = 0; i < level; i++) {
pfx += " ";
}
if (_value != "") {
l << _value << " ";
}
if (_is_block) {
l << "{" << logger::endl;
std::multimap<std::string, ptr<conf> >::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> conf::operator()(const std::string& name, int index) const
{
return find(name, index);
}
ptr<conf> conf::find(const std::string& name, int index) const
{
std::multimap<std::string, ptr<conf> >::const_iterator it;
for (it = _map.find(name); it != _map.end(); it++) {
if (index-- <= 0)
return it->second;
}
return ptr<conf>();
}
ptr<conf> conf::operator[](const std::string& name) const
{
return find(name, 0);
}
std::vector<ptr<conf> > conf::find_all(const std::string& name) const
{
std::vector<ptr<conf> > vec;
std::multimap<std::string, ptr<conf> >::const_iterator it;
std::pair<std::multimap<std::string, ptr<conf> >::const_iterator,
std::multimap<std::string, ptr<conf> >::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