So I merged some of the above solutions into my own, which for me made more sense, became more intuitive and a bit less error prone. I use a public stp::map
to keep track of the possible config ids, and a struct
to keep track of the possible values. Her it goes:
struct{
std::string PlaybackAssisted = "assisted";
std::string Playback = "playback";
std::string Recording = "record";
std::string Normal = "normal";
} mode_def;
std::map<std::string, std::string> settings = {
{"mode", mode_def.Normal},
{"output_log_path", "/home/root/output_data.log"},
{"input_log_path", "/home/root/input_data.log"},
};
void read_config(const std::string & settings_path){
std::ifstream settings_file(settings_path);
std::string line;
if (settings_file.fail()){
LOG_WARN("Config file does not exist. Default options set to:");
for (auto it = settings.begin(); it != settings.end(); it++){
LOG_INFO("%s=%s", it->first.c_str(), it->second.c_str());
}
}
while (std::getline(settings_file, line)){
std::istringstream iss(line);
std::string id, eq, val;
if (std::getline(iss, id, '=')){
if (std::getline(iss, val)){
if (settings.find(id) != settings.end()){
if (val.empty()){
LOG_INFO("Config \"%s\" is empty. Keeping default \"%s\"", id.c_str(), settings[id].c_str());
}
else{
settings[id] = val;
LOG_INFO("Config \"%s\" read as \"%s\"", id.c_str(), settings[id].c_str());
}
}
else{ //Not present in map
LOG_ERROR("Setting \"%s\" not defined, ignoring it", id.c_str());
continue;
}
}
else{
// Comment line, skiping it
continue;
}
}
else{
//Empty line, skipping it
continue;
}
}
}