21#include <boost/filesystem/directory.hpp>
22#include <boost/filesystem/operations.hpp>
23#include <boost/property_tree/ini_parser.hpp>
29namespace bpt = boost::property_tree;
34 std::string _filename;
35 std::vector<std::string> _additonalFiles;
36 std::vector<std::string> _args;
38 std::mutex _configLock;
40 bool LoadFile(std::string
const& file, bpt::ptree& fullTree, std::string& error)
44 bpt::ini_parser::read_ini(file, fullTree);
48 error =
"empty file (" + file +
")";
52 catch (bpt::ini_parser::ini_parser_error
const& e)
55 error = e.message() +
" (" + e.filename() +
")";
57 error = e.message() +
" (" + e.filename() +
":" + std::to_string(e.line()) +
")";
69 std::string IniKeyToEnvVarKey(std::string
const& key)
73 const char *str = key.c_str();
74 size_t n = key.length();
82 for (
size_t i = 0; i < n; ++i)
85 if (curr ==
' ' || curr ==
'.' || curr ==
'-')
94 nextIsUpper = isupper(str[i + 1]);
97 if (!isupper(curr) && nextIsUpper)
99 result +=
static_cast<char>(std::toupper(curr));
108 if (!currIsNumeric && nextIsNumeric)
110 result +=
static_cast<char>(std::toupper(curr));
116 if (currIsNumeric && !nextIsNumeric)
118 result +=
static_cast<char>(std::toupper(curr));
124 result +=
static_cast<char>(std::toupper(curr));
131 std::string envKey =
"TC_" + IniKeyToEnvVarKey(key);
132 char* val = std::getenv(envKey.c_str());
136 return std::string(val);
143 std::lock_guard<std::mutex> lock(_configLock);
145 _filename = std::move(file);
146 _args = std::move(args);
149 if (!LoadFile(_filename, fullTree, error))
153 _config = fullTree.begin()->second;
161 if (!LoadFile(file, fullTree, error))
164 std::lock_guard<std::mutex> lock(_configLock);
166 for (bpt::ptree::value_type
const& child : fullTree.begin()->second)
167 _config.put_child(bpt::ptree::path_type(child.first,
'/'), child.second);
170 _additonalFiles.emplace_back(std::move(file));
177 fs::path dirPath = dir;
178 if (!fs::exists(dirPath) || !fs::is_directory(dirPath))
181 for (fs::directory_entry
const& f : fs::recursive_directory_iterator(dirPath))
183 if (!fs::is_regular_file(f))
186 fs::path configFile = fs::absolute(f);
187 if (configFile.extension() !=
".conf")
190 std::string fileName = configFile.generic_string();
193 loadedFiles.push_back(std::move(fileName));
195 errors.push_back(std::move(error));
198 return errors.empty();
203 std::lock_guard<std::mutex> lock(_configLock);
205 std::vector<std::string> overriddenKeys;
207 for (bpt::ptree::value_type& itr: _config)
209 if (!itr.second.empty() || itr.first.empty())
216 itr.second = bpt::ptree(*envVar);
218 overriddenKeys.push_back(itr.first);
221 return overriddenKeys;
233 if (!
LoadInitial(_filename, std::move(_args), error))
234 errors.push_back(std::move(error));
236 for (std::string
const& additionalFile : _additonalFiles)
238 errors.push_back(std::move(error));
242 return errors.empty();
250 return _config.get<T>(bpt::ptree::path_type(name,
'/'));
252 catch (bpt::ptree_bad_path
const&)
257 Optional<T> castedVar = Trinity::StringTo<T>(*envVar);
260 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in environment variables, going to use default instead", name);
265 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, recovered with environment '{}' value.", name, _filename, envVar->c_str());
271 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, add \"{} = {}\" to this file",
272 name, _filename, name, def);
275 catch (bpt::ptree_bad_data
const&)
277 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use {} instead",
278 name, _filename, def);
285std::string ConfigMgr::GetValueDefault<std::string>(std::string
const& name, std::string def,
bool quiet)
const
289 return _config.get<std::string>(bpt::ptree::path_type(name,
'/'));
291 catch (bpt::ptree_bad_path
const&)
297 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, recovered with environment '{}' value.", name, _filename, envVar->c_str());
303 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, add \"{} = {}\" to this file",
304 name, _filename, name, def);
307 catch (bpt::ptree_bad_data
const&)
309 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use {} instead",
310 name, _filename, def);
319 val.erase(std::remove(val.begin(), val.end(),
'"'), val.end());
325 std::string val =
GetValueDefault(name, std::string(def ?
"1" :
"0"), quiet);
326 val.erase(std::remove(val.begin(), val.end(),
'"'), val.end());
332 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use '{}' instead",
333 name, _filename, def ?
"true" :
"false");
350 std::lock_guard<std::mutex> lock(_configLock);
361 std::lock_guard<std::mutex> lock(_configLock);
363 std::vector<std::string> keys;
365 for (bpt::ptree::value_type
const& child : _config)
366 if (child.first.compare(0, name.length(), name) == 0)
367 keys.push_back(child.first);
#define TC_LOG_WARN(filterType__,...)
#define TC_LOG_ERROR(filterType__,...)
std::optional< T > Optional
Optional helper class to wrap optional values within.
bool isNumeric(wchar_t wchar)
std::vector< std::string > OverrideWithEnvVariablesIfAny()
Overrides configuration with environment variables and returns overridden keys.
float GetFloatDefault(std::string const &name, float def, bool quiet=false) const
std::string const & GetFilename()
int GetIntDefault(std::string const &name, int def, bool quiet=false) const
bool GetBoolDefault(std::string const &name, bool def, bool quiet=false) const
std::vector< std::string > GetKeysByString(std::string const &name)
bool Reload(std::vector< std::string > &errors)
static ConfigMgr * instance()
bool LoadInitial(std::string file, std::vector< std::string > args, std::string &error)
Method used only for loading main configuration files (authserver.conf and worldserver....
std::vector< std::string > const & GetArguments() const
bool LoadAdditionalDir(std::string const &dir, bool keepOnReload, std::vector< std::string > &loadedFiles, std::vector< std::string > &errors)
T GetValueDefault(std::string const &name, T def, bool quiet) const
bool LoadAdditionalFile(std::string file, bool keepOnReload, std::string &error)
std::string GetStringDefault(std::string const &name, const std::string &def, bool quiet=false) const