mirror of
https://gitlab.com/niansa/commoncpp.git
synced 2025-03-06 20:48:30 +01:00
108 lines
3 KiB
C++
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
|