1
0
Fork 0
mirror of https://gitlab.com/niansa/commoncpp.git synced 2025-03-06 20:48:30 +01:00
commoncpp/config.cpp
2023-08-06 16:14:30 +02:00

108 lines
3 KiB
C++

#ifndef COMMONCPP_LITE
#include "config.hpp"
#include "utils.hpp"
#include <fstream>
#include <filesystem>
namespace common {
bool Configuration::parse_bool(const std::string &value) {
if (value == "true")
return true;
if (value == "false")
return false;
throw Exception("Error: Failed to parse configuration file: Unknown bool (true/false): "+value);
}
std::string Configuration::parse_string(const std::string &value) {
std::string fres;
fres.reserve(value.size());
bool escaped = false;
for (const char c : value) {
if (!escaped) {
if (c == '\\') {
escaped = true;
continue;
} else
fres.push_back(c);
} else {
char nc;
switch (c) {
case 'n':
nc = '\n';
break;
case 'r':
nc = '\r';
break;
case 't':
nc = '\t';
break;
case 'b':
nc = '\b';
break;
case '\\':
nc = '\\';
break;
default:
throw Exception("Unknown escape sequence: \\"+std::string(1, c));
}
fres.push_back(nc);
escaped = false;
}
}
return fres;
}
bool Configuration::file_exists(std::string_view path) {
// Make sure we don't respond to some file that is actually called "none"...
if (path.empty() || path == "none") return false;
return std::filesystem::exists(path);
}
Configuration::KeyValueMap Configuration::file_parser(const std::string& path) {
std::unordered_map<std::string, std::string> fres;
// Open file
std::ifstream cfgf(path);
if (!cfgf) {
throw Exception("Failed to open configuration file: "+path);
}
// Read each entry
for (std::string key; cfgf >> key;) {
// Read value
std::string value;
std::getline(cfgf, value);
// Ignore comment and empty lines
if (key.empty() || key[0] == '#') continue;
// Erase all leading spaces in value
while (!value.empty() && (value[0] == ' ' || value[0] == '\t')) value.erase(0, 1);
// Add to function result
fres.emplace(std::move(key), std::move(value));
}
// Return final result
return fres;
}
extern "C" char **environ;
Configuration::KeyValueMap Configuration::environment_parser() {
std::unordered_map<std::string, std::string> fres;
for (char **s = environ; *s; s++) {
const auto pair = utils::str_split(*s, '=', 1);
fres.emplace(pair[0], pair[1]);
}
return fres;
}
void Configuration::parse(const std::string &file) {
const auto file_location = file.empty()?
std::filesystem::current_path():
std::filesystem::path(file).parent_path();
if (!ignore_environment)
fill(environment_parser());
if (!file.empty())
fill(file_parser(file), true);
}
}
#endif // COMMONCPP_LITE