UsenetSearch/src/Configuration.cpp

261 lines
7.2 KiB
C++

/*
Copyright© 2021 John Sennesael
UsenetSearch is Free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
UsenetSearch is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with UsenetSearch. If not, see <https://www.gnu.org/licenses/>.
*/
#include "usenetsearch/Configuration.h"
#include "usenetsearch/Logger.h"
#include "usenetsearch/ScopeExit.h"
#include "usenetsearch/StringUtils.h"
#include <filesystem>
#include <fstream>
#include <regex>
#include <string>
namespace usenetsearch {
std::uint16_t Configuration::BatchSize() const
{
return m_batchSize;
}
std::filesystem::path Configuration::DatabasePath() const
{
return m_databasePath;
}
std::vector<std::string>& Configuration::FilterEraseSubtoken()
{
return m_filterEraseSubtoken;
}
std::vector<std::regex>& Configuration::FilterNewsgroupBlacklist()
{
return m_filterNewsgroupBlacklist;
}
std::vector<std::regex>& Configuration::FilterNewsgroupWhitelist()
{
return m_filterNewsgroupWhitelist;
}
std::vector<std::string>& Configuration::FilterWordsNoSubtoken()
{
return m_filterWordsNoSubtoken;
}
std::uint16_t Configuration::MaxThreads() const
{
return m_maxThreads;
}
std::uint8_t Configuration::MaxTreeDepth() const
{
return m_maxTreeDepth;
}
std::uint16_t Configuration::MinSubtokenWords() const
{
return m_minSubtokenWords;
}
std::string Configuration::NNTPServerHost() const
{
return m_nntpServerHost;
}
std::string Configuration::NNTPServerPassword() const
{
return m_nntpServerPassword;
}
int Configuration::NNTPServerPort() const
{
return m_nntpServerPort;
}
bool Configuration::NNTPServerSSL() const
{
return m_nntpServerSSL;
}
std::string Configuration::NNTPServerUser() const
{
return m_nntpServerUser;
}
void Configuration::Open(const std::string& filename)
{
std::string line;
std::ifstream fin(filename.c_str());
if (!fin.is_open())
{
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
"Could not open configuration file: " + filename
);
}
ScopeExit finCloser([&fin](){ fin.close(); });
int line_nr = 0;
while(std::getline(fin,line))
{
line_nr++;
line = StringTrim(line);
// Immediately skip blank lines.
if (line == "") continue;
// Skip comments.
if (StringStartsWith("#",line)==true) continue;
// Split line in key-value pair.
const auto kvp = StringSplit(line, std::string{":"}, 2);
if (kvp.size() != 2)
{
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
std::string("Invalid configuration in ")
+ filename + std::string(" line ")
+ std::to_string(line_nr)
);
}
const std::string key = StringToLower(kvp[0]);
const std::string value = StringTrim(kvp[1]);
if (key == "batch_size")
{
m_batchSize = stoi(value);
}
else if (key == "database_path")
{
m_databasePath = value;
}
else if (key == "filter_erase_subtoken")
{
const auto tokens = StringSplit(value, std::string{","});
for (const auto& token: tokens)
{
const auto trimmedToken = StringToLower(StringTrim(token));
if (trimmedToken != "")
{
m_filterEraseSubtoken.emplace_back(trimmedToken);
}
}
}
else if (key == "filter_newsgroup_blacklist")
{
try
{
std::regex re(value);
m_filterNewsgroupBlacklist.emplace_back(re);
}
catch (const std::regex_error& e)
{
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
std::string("Invalid configuration in ")
+ filename + std::string(" line ")
+ std::to_string(line_nr) + " : Regular expression \""
+ value + "\" did not parse: " + e.what()
);
}
}
else if (key == "filter_newsgroup_whitelist")
{
try
{
std::regex re(value);
m_filterNewsgroupWhitelist.emplace_back(re);
}
catch (const std::regex_error& e)
{
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
std::string("Invalid configuration in ")
+ filename + std::string(" line ")
+ std::to_string(line_nr) + " : Regular expression \""
+ value + "\" did not parse: " + e.what()
);
}
}
else if (key == "filter_no_subtoken")
{
const auto tokens = StringSplit(value, std::string{","});
for (const auto& token: tokens)
{
const auto trimmedToken = StringToLower(StringTrim(token));
if (trimmedToken != "")
{
m_filterWordsNoSubtoken.emplace_back(trimmedToken);
}
}
}
else if (key == "max_threads")
{
m_maxThreads = stoi(value);
}
else if (key == "max_tree_depth")
{
m_maxTreeDepth = stoi(value);
}
else if (key == "minimum_subtoken_words")
{
m_minSubtokenWords = stoi(value);
}
else if (key == "nntp_server_host")
{
m_nntpServerHost = value;
}
else if (key == "nntp_server_pass")
{
m_nntpServerPassword = value;
}
else if (key == "nntp_server_port")
{
m_nntpServerPort = stoi(value);
}
else if (key == "nntp_server_use_ssl")
{
try
{
m_nntpServerSSL = StringToBoolean(value);
}
catch (const StringException& e)
{
fin.close();
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
std::string("Invalid configuration in ")
+ filename + std::string(" line ")
+ std::to_string(line_nr) + " - " + e.what()
);
}
}
else if (key == "nntp_server_user")
{
m_nntpServerUser = value;
}
else
{
Logger::Get().Fatal<ConfigurationException>(
LOGID("Configuration"),
std::string("Invalid configuration in ")
+ filename + std::string(" line ")
+ std::to_string(line_nr)
);
}
}
}
} // namespace usenetsearch