From aeda7b341454f243ff8a3d742222c24bf75c338d Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 12 Apr 2013 01:52:29 +0200 Subject: [PATCH] Split config parsing out of parse.h. --- config.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++ config.h | 32 ++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 config.cpp create mode 100644 config.h diff --git a/config.cpp b/config.cpp new file mode 100644 index 0000000..b6ad99b --- /dev/null +++ b/config.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "parse.h" + +using namespace std; + +vector parse_config(const string &filename) +{ + vector ret; + + FILE *fp = fopen(filename.c_str(), "r"); + if (fp == NULL) { + perror(filename.c_str()); + exit(1); + } + + char buf[4096]; + while (!feof(fp)) { + if (fgets(buf, sizeof(buf), fp) == NULL) { + break; + } + + // Chop off the string at the first #, \r or \n. + buf[strcspn(buf, "#\r\n")] = 0; + + // Remove all whitespace from the end of the string. + size_t len = strlen(buf); + while (len > 0 && isspace(buf[len - 1])) { + buf[--len] = 0; + } + + // If the line is now all blank, ignore it. + if (len == 0) { + continue; + } + + vector tokens = split_tokens(buf); + assert(!tokens.empty()); + + ConfigLine line; + line.keyword = tokens[0]; + + for (size_t i = 1; i < tokens.size(); ++i) { + // foo=bar is a parameter; anything else is an argument. + size_t equals_pos = tokens[i].find_first_of('='); + if (equals_pos == string::npos) { + line.arguments.push_back(tokens[i]); + } else { + string key = tokens[i].substr(0, equals_pos); + string value = tokens[i].substr(equals_pos + 1, string::npos); + line.parameters.insert(make_pair(key, value)); + } + } + + ret.push_back(line); + } + + fclose(fp); + return ret; +} + +string fetch_config_string(const vector &config, const string &keyword, + ParameterType parameter_type, const string &default_value) +{ + assert(parameter_type == PARAMATER_MANDATORY || parameter_type == PARAMETER_OPTIONAL); + for (unsigned i = 0; i < config.size(); ++i) { + if (config[i].keyword != keyword) { + continue; + } + if (config[i].parameters.size() > 0 || + config[i].arguments.size() != 1) { + fprintf(stderr, "ERROR: '%s' takes one argument and no parameters\n", keyword.c_str()); + exit(1); + } + return config[i].arguments[0]; + } + if (parameter_type == PARAMATER_MANDATORY) { + fprintf(stderr, "ERROR: Missing '%s' statement in config file.\n", + keyword.c_str()); + exit(1); + } else { + return default_value; + } +} + +int fetch_config_int(const std::vector &config, const std::string &keyword, + int min_limit, int max_limit, + ParameterType parameter_type, int default_value) +{ + assert(parameter_type == PARAMATER_MANDATORY || parameter_type == PARAMETER_OPTIONAL); + bool value_found = false; + int value = -1; + for (unsigned i = 0; i < config.size(); ++i) { + if (config[i].keyword != keyword) { + continue; + } + if (config[i].parameters.size() > 0 || + config[i].arguments.size() != 1) { + fprintf(stderr, "ERROR: '%s' takes one argument and no parameters\n", keyword.c_str()); + exit(1); + } + value_found = true; + value = atoi(config[i].arguments[0].c_str()); // TODO: verify int validity. + } + if (!value_found) { + if (parameter_type == PARAMETER_OPTIONAL) { + return default_value; + } + fprintf(stderr, "ERROR: Missing '%s' statement in config file.\n", + keyword.c_str()); + exit(1); + } + if (value < min_limit || value > max_limit) { + fprintf(stderr, "ERROR: '%s' is set to %d, must be in [%d,%d]\n", + keyword.c_str(), value, min_limit, max_limit); + exit(1); + } + return value; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..0600083 --- /dev/null +++ b/config.h @@ -0,0 +1,32 @@ +#ifndef _CONFIG_H +#define _CONFIG_H + +// Various routines that deal with parsing the configuration file. + +#include +#include +#include + +struct ConfigLine { + std::string keyword; + std::vector arguments; + std::map parameters; +}; + +// Parse the configuration file. +std::vector parse_config(const std::string &filename); + +enum ParameterType { + PARAMETER_OPTIONAL, + PARAMATER_MANDATORY, +}; + +std::string fetch_config_string(const std::vector &config, const std::string &keyword, + ParameterType parameter_type, const std::string &default_value = ""); + +// Note: Limits are inclusive. +int fetch_config_int(const std::vector &config, const std::string &keyword, + int min_limit, int max_limit, + ParameterType parameter_type, int default_value = -1); + +#endif // !defined(_CONFIG_H) -- 2.39.2