#include "options.h" #include #include #define MAX_LINE 2048 // Remove whitespace around a string std::string trim(const std::string &in) { size_t first = in.find_first_not_of(" "); size_t last = in.find_last_not_of(" "); if (first == std::string::npos || last == std::string::npos) { return in; } else { return in.substr(first, last - first + 1); } } Options::Options() {} Options::~Options() {} int Options::load(const std::string &filename) { FILE *fd; char line[MAX_LINE]; int lineno = 1; fd = fopen(filename.c_str(), "r"); if (!fd) { return -1; } while (fgets(line, MAX_LINE, fd) != nullptr) { // split line at the = sign std::string ln = trim(line); size_t eqPos = ln.find("="); if (eqPos == std::string::npos) { // clean up and exit fclose(fd); return lineno; } else { std::string key = trim(ln.substr(0, eqPos - 1)); std::string value = trim(ln.substr(eqPos + 1)); m_data[key] = value; } lineno++; } fclose(fd); return 0; } int Options::save(const std::string &filename) { FILE *fd; fd = fopen(filename.c_str(), "w"); if (!fd) { return -1; } for (auto it : m_data) { fprintf(fd, "%s = %s\n", it.first.c_str(), it.second.c_str()); } fclose(fd); return 0; } int Options::getInt(const std::string &name, int def) { int result; if (!has(name)) return def; if (sscanf(m_data[name].c_str(), "%d", &result) != 1) result = def; return result; } double Options::getNum(const std::string &name, double def) { double result; if (!has(name)) return def; if (sscanf(m_data[name].c_str(), "%lf", &result) != 1) result = def; return result; } bool Options::getBool(const std::string &name, bool def) { if (!has(name)) return def; // test for true/false strings const std::string &value = m_data[name]; if (string_icompare(value, "true") == 0) return true; if (string_icompare(value, "false") == 0) return false; // try to convert to an int and use that as a bool size_t pos; int asInt = std::stoi(value, &pos); if (pos) return (bool)asInt; // fall back to default return def; } const std::string &Options::getString(const std::string &name, const std::string &def) { if (!has(name)) return def; return m_data[name]; } void Options::set(const std::string &name, const std::string &value) { m_data[name] = value; } void Options::set(const std::string &name, double value) { m_data[name] = std::to_string(value); } void Options::set(const std::string &name, bool value) { m_data[name] = value ? "true" : "false"; } bool Options::has(const std::string &name) { return m_data.find(name) != m_data.end(); } int string_icompare(const std::string &a, const std::string &b) { auto itA = a.begin(); auto itB = b.begin(); while (itA != a.end() && itB != b.end()) { int diff = toupper(*itA) - toupper(*itB); if (diff) return diff; itA++; itB++; } return 0; }