1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#include <config/config.hpp>
#include <utils/tolower.hpp>
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std::string_literals;
extern char** environ;
std::string Config::filename{};
std::map<std::string, std::string> Config::values{};
std::vector<t_config_changed_callback> Config::callbacks{};
std::string Config::get(const std::string& option, const std::string& def)
{
auto it = Config::values.find(option);
if (it == Config::values.end())
return def;
return it->second;
}
bool Config::get_bool(const std::string& option, const bool def)
{
auto res = Config::get(option, "");
if (res.empty())
return def;
return res == "true";
}
int Config::get_int(const std::string& option, const int& def)
{
std::string res = Config::get(option, "");
if (!res.empty())
return std::atoi(res.c_str());
else
return def;
}
void Config::set(const std::string& option, const std::string& value, bool save)
{
Config::values[option] = value;
if (save)
{
Config::save_to_file();
Config::trigger_configuration_change();
}
}
void Config::connect(const t_config_changed_callback& callback)
{
Config::callbacks.push_back(callback);
}
void Config::clear()
{
Config::values.clear();
}
/**
* Private methods
*/
void Config::trigger_configuration_change()
{
std::vector<t_config_changed_callback>::iterator it;
for (it = Config::callbacks.begin(); it < Config::callbacks.end(); ++it)
(*it)();
}
bool Config::read_conf(const std::string& name)
{
if (!name.empty())
Config::filename = name;
std::ifstream file(Config::filename.data());
if (!file.is_open())
{
std::cerr << "Error while opening file " << filename << " for reading: " << strerror(errno) << std::endl;
return false;
}
Config::clear();
auto parse_line = [](const std::string& line, const bool env)
{
static const auto env_option_prefix = "BIBOUMI_"s;
if (line == "" || line[0] == '#')
return;
size_t pos = line.find('=');
if (pos == std::string::npos)
return;
std::string option = line.substr(0, pos);
std::string value = line.substr(pos+1);
if (env)
{
auto a = option.substr(0, env_option_prefix.size());
if (a == env_option_prefix)
option = utils::tolower(option.substr(env_option_prefix.size()));
else
return;
}
Config::values[option] = value;
};
std::string line;
while (file.good())
{
std::getline(file, line);
parse_line(line, false);
}
char** env_line = environ;
while (*env_line)
{
parse_line(*env_line, true);
env_line++;
}
return true;
}
void Config::save_to_file()
{
std::ofstream file(Config::filename.data());
if (file.fail())
{
std::cerr << "Could not save config file." << std::endl;
return ;
}
for (const auto& it: Config::values)
file << it.first << "=" << it.second << '\n';
}
|