/* Copyright 2020, Michele Santullo * This file is part of orotool. * * Orotool 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. * * Orotool 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 Orotool. If not, see . */ #include "app_config.hpp" #include "orotool_config.hpp" #include #include #include #include #include #include #include namespace duck { namespace { constexpr const char g_db_path_sect[] = "system"; constexpr const char g_db_path[] = "db_path"; constexpr const char g_worker_threads_sect[] = "system"; constexpr const char g_worker_threads[] = "worker_threads"; constexpr const char g_backend_sect[] = "system"; constexpr const char g_backend[] = "backend"; constexpr const char g_fetch_extra_delay_sect[] = "rules"; constexpr const char g_fetch_extra_delay[] = "fetch_extra_delay"; constexpr const char g_fetch_extra_delay_def[] = "30"; constexpr const char g_api_key_sect[] = "rules"; constexpr const char g_api_key[] = "api_key"; constexpr const char g_api_key_def[] = ""; std::string whole_ini() { std::ifstream input(g_config_file_path); input >> std::noskipws; return { std::istream_iterator(input), std::istream_iterator() }; } std::string_view value_ifp ( const kamokan::IniFile& ini, std::string_view section, std::string_view key, std::string_view def, bool allow_empty ) { const auto& map = ini.parsed(); auto it_section = map.find(section); if (map.end() == it_section) return def; auto it_setting = it_section->second.find(key); if (it_section->second.end() == it_setting) return def; if (not allow_empty and it_setting->second.empty()) return def; else return it_setting->second; } void print_setting_read_err ( std::string_view section, std::string_view name, const std::logic_error& err ) { std::cerr << "Error reading setting [" << section << "] \"" << name << "\": " << err.what() << '\n'; } } //unnamed namespace AppConfig::AppConfig() : m_ini(whole_ini()) { } AppConfig::~AppConfig() noexcept = default; std::string_view AppConfig::db_path() const { return value_ifp(m_ini, g_db_path_sect, g_db_path, g_def_sqlite_db_name, false); } std::string_view AppConfig::api_key() const { return value_ifp(m_ini, g_api_key_sect, g_api_key, g_api_key_def, true); } std::size_t AppConfig::worker_threads() const { std::string_view val = value_ifp(m_ini, g_worker_threads_sect, g_worker_threads, g_def_worker_threads, false); if (val == "max") { return std::max(3U, std::thread::hardware_concurrency()) - 1; } else { try { const std::size_t num = std::stoul(std::string(val.data(), val.size())); const std::size_t hard_max = 4U * std::thread::hardware_concurrency(); return std::max(2U, std::min(num, hard_max)); } catch (const std::logic_error& err) { print_setting_read_err(g_worker_threads_sect, g_worker_threads, err); return std::stoul(g_def_worker_threads); } } } std::size_t AppConfig::fetch_extra_delay() const { std::string_view val = value_ifp(m_ini, g_fetch_extra_delay_sect, g_fetch_extra_delay, g_fetch_extra_delay_def, false); try { const std::size_t num = std::stoul(std::string(val.data(), val.size())); return std::min(3600 * 6, num); } catch (const std::logic_error& err) { print_setting_read_err(g_fetch_extra_delay_sect, g_fetch_extra_delay, err); return std::stoul(g_fetch_extra_delay_def); } } std::string_view AppConfig::backend() const { return value_ifp(m_ini, g_backend_sect, g_backend, g_def_backend_name, false); } } //namespace duck