21#include <boost/filesystem/operations.hpp>
22#include <boost/property_tree/ini_parser.hpp>
28namespace bpt = boost::property_tree;
33 std::string _filename;
34 std::vector<std::string> _additonalFiles;
35 std::vector<std::string> _args;
37 std::mutex _configLock;
39 bool LoadFile(std::string
const& file, bpt::ptree& fullTree, std::string& error)
43 bpt::ini_parser::read_ini(file, fullTree);
47 error =
"empty file (" + file +
")";
51 catch (bpt::ini_parser::ini_parser_error
const& e)
54 error = e.message() +
" (" + e.filename() +
")";
56 error = e.message() +
" (" + e.filename() +
":" + std::to_string(e.line()) +
")";
68 std::string IniKeyToEnvVarKey(std::string
const& key)
72 const char *str = key.c_str();
73 size_t n = key.length();
81 for (
size_t i = 0; i < n; ++i)
84 if (curr ==
' ' || curr ==
'.' || curr ==
'-')
93 nextIsUpper = isupper(str[i + 1]);
96 if (!isupper(curr) && nextIsUpper)
98 result +=
static_cast<char>(std::toupper(curr));
107 if (!currIsNumeric && nextIsNumeric)
109 result +=
static_cast<char>(std::toupper(curr));
115 if (currIsNumeric && !nextIsNumeric)
117 result +=
static_cast<char>(std::toupper(curr));
123 result +=
static_cast<char>(std::toupper(curr));
130 std::string envKey =
"TC_" + IniKeyToEnvVarKey(key);
131 char* val = std::getenv(envKey.c_str());
135 return std::string(val);
142 std::lock_guard<std::mutex> lock(_configLock);
144 _filename = std::move(file);
145 _args = std::move(args);
148 if (!LoadFile(_filename, fullTree, error))
152 _config = fullTree.begin()->second;
160 if (!LoadFile(file, fullTree, error))
163 std::lock_guard<std::mutex> lock(_configLock);
165 for (bpt::ptree::value_type
const& child : fullTree.begin()->second)
166 _config.put_child(bpt::ptree::path_type(child.first,
'/'), child.second);
169 _additonalFiles.emplace_back(std::move(file));
176 fs::path dirPath = dir;
177 if (!fs::exists(dirPath) || !fs::is_directory(dirPath))
180 for (fs::directory_entry
const& f : fs::recursive_directory_iterator(dirPath))
182 if (!fs::is_regular_file(f))
185 fs::path configFile = fs::absolute(f);
186 if (configFile.extension() !=
".conf")
189 std::string fileName = configFile.generic_string();
192 loadedFiles.push_back(std::move(fileName));
194 errors.push_back(std::move(error));
197 return errors.empty();
202 std::lock_guard<std::mutex> lock(_configLock);
204 std::vector<std::string> overriddenKeys;
206 for (bpt::ptree::value_type& itr: _config)
208 if (!itr.second.empty() || itr.first.empty())
215 itr.second = bpt::ptree(*envVar);
217 overriddenKeys.push_back(itr.first);
220 return overriddenKeys;
232 if (!
LoadInitial(_filename, std::move(_args), error))
233 errors.push_back(std::move(error));
235 for (std::string
const& additionalFile : _additonalFiles)
237 errors.push_back(std::move(error));
241 return errors.empty();
249 return _config.get<T>(bpt::ptree::path_type(name,
'/'));
251 catch (bpt::ptree_bad_path
const&)
256 Optional<T> castedVar = Trinity::StringTo<T>(*envVar);
259 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in environment variables, going to use default instead", name);
264 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, recovered with environment '{}' value.", name, _filename, *envVar);
270 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, add \"{} = {}\" to this file",
271 name, _filename, name, def);
274 catch (bpt::ptree_bad_data
const&)
276 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use {} instead",
277 name, _filename, def);
284std::string ConfigMgr::GetValueDefault<std::string>(std::string
const& name, std::string def,
bool quiet)
const
288 return _config.get<std::string>(bpt::ptree::path_type(name,
'/'));
290 catch (bpt::ptree_bad_path
const&)
296 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, recovered with environment '{}' value.", name, _filename, *envVar);
302 TC_LOG_WARN(
"server.loading",
"Missing name {} in config file {}, add \"{} = {}\" to this file",
303 name, _filename, name, def);
306 catch (bpt::ptree_bad_data
const&)
308 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use {} instead",
309 name, _filename, def);
318 val.erase(std::remove(val.begin(), val.end(),
'"'), val.end());
324 std::string val =
GetValueDefault(name, std::string(def ?
"1" :
"0"), quiet);
325 val.erase(std::remove(val.begin(), val.end(),
'"'), val.end());
331 TC_LOG_ERROR(
"server.loading",
"Bad value defined for name {} in config file {}, going to use '{}' instead",
332 name, _filename, def ?
"true" :
"false");
354 std::lock_guard<std::mutex> lock(_configLock);
365 std::lock_guard<std::mutex> lock(_configLock);
367 std::vector<std::string> keys;
369 for (bpt::ptree::value_type
const& child : _config)
370 if (child.first.compare(0, name.length(), name) == 0)
371 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()
bool GetBoolDefault(std::string const &name, bool def, bool quiet=false) const
int64 GetInt64Default(std::string const &name, int64 def, bool quiet=false) const
int32 GetIntDefault(std::string const &name, int32 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 (bnetserver.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