-
Ramin Yaghoubzadeh Torky authoredRamin Yaghoubzadeh Torky authored
ipaaca-config.cc 6.10 KiB
/*
* This file is part of IPAACA, the
* "Incremental Processing Architecture
* for Artificial Conversational Agents".
*
* Copyright (c) 2009-2019 Social Cognitive Systems Group
* (formerly the Sociable Agents Group)
* CITEC, Bielefeld University
*
* http://opensource.cit-ec.de/projects/ipaaca/
* http://purl.org/net/ipaaca
*
* This file may be licensed under the terms of of the
* GNU Lesser General Public License Version 3 (the ``LGPL''),
* or (at your option) any later version.
*
* Software distributed under the License is distributed
* on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the LGPL for the specific language
* governing rights and limitations.
*
* You should have received a copy of the LGPL along with this
* program. If not, go to http://www.gnu.org/licenses/lgpl.html
* or write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The development of this software was supported by the
* Excellence Cluster EXC 277 Cognitive Interaction Technology.
* The Excellence Cluster EXC 277 is a grant of the Deutsche
* Forschungsgemeinschaft (DFG) in the context of the German
* Excellence Initiative.
*/
/**
* \file ipaaca-config.cc
*
* \brief Source file for IPAACA configuration handling
*
* \author Ramin Yaghoubzadeh Torky (ryaghoubzadeh@uni-bielefeld.de)
* \date January, 2019
*/
#include <ipaaca/ipaaca.h>
extern char **environ;
namespace ipaaca {
template<>
int Config::get_with_default_internal<int>(const std::string& key, int const& default_value, bool warn)
{
auto it = _data.find(key);
if (it==_data.end()) {
config_key_not_found(key, default_value, warn);
return default_value;
}
std::size_t processed;
int res = std::stoi(it->second, &processed);
if (processed != it->second.size()) {
config_conversion_failed(key, default_value);
return default_value;
}
return res;
}
template<>
std::string Config::get_with_default_internal<std::string>(const std::string& key, std::string const& default_value, bool warn)
{
auto it = _data.find(key);
if (it==_data.end()) {
config_key_not_found(key, default_value, warn);
return default_value;
}
return it->second;
}
Config::ptr get_global_config(bool auto_parse_on_demand){
static bool first = true;
static Config::ptr global_config = std::make_shared<Config>();
if (first) {
first = false;
IPAACA_DEBUG("This is IPAACA-C++ version " << IPAACA_PROTOCOL_VERSION_MAJOR << "." << IPAACA_PROTOCOL_VERSION_MINOR << " (release " << IPAACA_CPP_RELEASE_NUMBER << " with nominal release date " << IPAACA_CPP_RELEASE_DATE << ") - library compiled on " << __DATE__)
if (auto_parse_on_demand) {
IPAACA_DEBUG("Populating global configuration from default sources")
global_config->populate_from_global_sources();
}
}
return global_config;
}
void Config::populate_from_global_sources()
{
_messages_delivered.clear(); // message variable warnings
populate_from_any_conf_files();
populate_from_environment();
}
bool Config::get_key_and_value(const std::string& s, std::string& key, std::string& value)
{
bool good = true;
size_t pos = 0;
for (pos=0; pos<s.size(); ++pos) {
auto c = s[pos]; //std::tolower(s[pos]);
if (c=='=') {
value = ipaaca::str_trim(s.substr(pos+1));
break;
} else if (c=='_') {
key += '.';
} else if (c=='.') {
key += '.';
} else if ((c>='a')&&(c<='z')) {
key += c;
} else if ((c>='A')&&(c<='Z')) {
key += (c+32);
} else {
good = false;
break;
}
}
if (!good) {
IPAACA_ERROR("Malformed configuration ignored: " << s.substr(0, pos+1))
}
return good;
}
void Config::populate_from_environment()
{
int i = 1;
char* envline = *environ;
while (envline) {
if(strncmp(envline, "IPAACA_", 7) == 0) {
if (strlen(envline) > 1023) {
IPAACA_ERROR("Ignoring overly long environment entry starting with IPAACA_")
} else {
std::string s(envline);
s = s.substr(7);
std::string key("");
std::string value("");
bool good = get_key_and_value(s, key, value);
if (good) {
IPAACA_INFO("Configuration set from environment: " << key << "=\"" << value << "\"");
_data[key] = value;
}
}
}
envline = *(environ+i);
i++;
}
}
void Config::populate_from_any_conf_files()
{
std::fstream f1;
f1.open("ipaaca.conf", std::fstream::in);
bool had_file = false;
if (f1.is_open()) {
IPAACA_DEBUG("Including configuration from ./ipaaca.conf")
populate_from_conf_file(f1);
f1.close();
had_file = true;
} else {
std::fstream f2;
char* homedir = std::getenv("HOME"); // TODO: windows
if (homedir) {
std::string conf_in_home(homedir);
conf_in_home += "/.config/ipaaca.conf";
f2.open(conf_in_home, std::fstream::in);
if (f2.is_open()) {
IPAACA_DEBUG("Including configuration from ~/.config/ipaaca.conf")
populate_from_conf_file(f2);
f2.close();
had_file = true;
}
}
}
if (!had_file) {
IPAACA_INFO("Could not load ipaaca.conf either here or in ~/.config")
}
}
void Config::populate_from_conf_file(std::fstream& fs)
{
std::string line;
while (std::getline(fs, line)) {
//std::cout << "---> " << line << std::endl;
line = ipaaca::str_trim(line);
std::string key("");
std::string value("");
if ((line.length() > 0) && (line[0] != '#') && (line[0] != '[')) {
bool good = get_key_and_value(line, key, value);
if (good) {
IPAACA_INFO("Configuration set from conf file: " << key << "=\"" << value << "\"");
_data[key] = value;
}
}
}
}
} // of namespace ipaaca