Index: source/ps/ConfigDB.h =================================================================== --- source/ps/ConfigDB.h +++ source/ps/ConfigDB.h @@ -31,7 +31,9 @@ #include "ps/CStr.h" #include "ps/Singleton.h" +#include #include +#include // Namespace priorities: User supersedes mod supersedes system. // Command-line arguments override everything. @@ -60,17 +62,17 @@ * will search CFG_COMMAND first, and then all namespaces from the specified * namespace down. */ - void GetValue(EConfigNamespace ns, const CStr& name, bool& value); - ///@copydoc CConfigDB::GetValue - void GetValue(EConfigNamespace ns, const CStr& name, int& value); - ///@copydoc CConfigDB::GetValue - void GetValue(EConfigNamespace ns, const CStr& name, u32& value); - ///@copydoc CConfigDB::GetValue - void GetValue(EConfigNamespace ns, const CStr& name, float& value); - ///@copydoc CConfigDB::GetValue - void GetValue(EConfigNamespace ns, const CStr& name, double& value); - ///@copydoc CConfigDB::GetValue - void GetValue(EConfigNamespace ns, const CStr& name, std::string& value); + template + void GetValue(const CStr& name, T& value, EConfigNamespace ns = CFG_USER); + + /** + * Attempt to retrieve the value of a config variable with the given name; + * will search CFG_COMMAND first, and then all namespaces from the specified + * namespace down. Call the successCallback if the value is found. + */ + // TODO: use move semantics, when it will be fully supported. + template + void GetValue(const CStr& name, const std::function& successCallback, EConfigNamespace ns = CFG_USER); /** * Returns true if changed with respect to last write on file @@ -163,15 +165,19 @@ bool WriteValueToFile(EConfigNamespace ns, const CStr& name, const CStr& value); private: - static std::map m_Map[]; + typedef std::map TConfigMap; + static TConfigMap m_Map[]; static VfsPath m_ConfigFile[]; static bool m_HasChanges[]; -}; + // Internal function to find an iterator the config value by the name. + // Not thread-safe, because should be used in other thread-safe functions. + std::pair GetValueIterator(EConfigNamespace ns, const CStr& name); +}; -// stores the value of the given key into . this quasi-template -// convenience wrapper on top of GetValue simplifies user code +// Stores the value of the given key into . This quasi-template +// convenience wrapper on top of GetValue simplifies user code. #define CFG_GET_VAL(name, destination)\ - g_ConfigDB.GetValue(CFG_USER, name, destination) + g_ConfigDB.GetValue(name, destination) #endif // INCLUDED_CONFIGDB Index: source/ps/ConfigDB.cpp =================================================================== --- source/ps/ConfigDB.cpp +++ source/ps/ConfigDB.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -30,8 +30,7 @@ #include -typedef std::map TConfigMap; -TConfigMap CConfigDB::m_Map[CFG_LAST]; +CConfigDB::TConfigMap CConfigDB::m_Map[CFG_LAST]; VfsPath CConfigDB::m_ConfigFile[CFG_LAST]; bool CConfigDB::m_HasChanges[CFG_LAST]; @@ -82,6 +81,10 @@ { ret = value; } +template<> void Get<>(const CStr& value, CStr& ret) +{ + ret = value; +} std::string EscapeString(const CStr& str) { std::string ret; @@ -98,26 +101,44 @@ } } // namespace -#define GETVAL(type)\ - void CConfigDB::GetValue(EConfigNamespace ns, const CStr& name, type& value)\ +std::pair CConfigDB::GetValueIterator(EConfigNamespace ns, const CStr& name) +{ + CHECK_NS(std::make_pair(CFG_COMMAND, m_Map[CFG_COMMAND].end())); + TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name); + if (it != m_Map[CFG_COMMAND].end()) + return std::make_pair(CFG_COMMAND, it); + for (int search_ns = ns; search_ns >= 0; --search_ns) + { + it = m_Map[search_ns].find(name); + if (it != m_Map[search_ns].end()) + return std::make_pair(static_cast(search_ns), it); + } + return std::make_pair(CFG_COMMAND, m_Map[CFG_COMMAND].end()); +} + +#define GETVAL(TYPE)\ + template<>\ + void CConfigDB::GetValue(const CStr& name, TYPE& value, EConfigNamespace ns)\ {\ CHECK_NS(;);\ CScopeLock s(&cfgdb_mutex);\ - TConfigMap::iterator it = m_Map[CFG_COMMAND].find(name);\ - if (it != m_Map[CFG_COMMAND].end())\ - {\ - Get(it->second[0], value);\ + std::pair p = GetValueIterator(ns, name);\ + if (p.second == m_Map[p.first].end())\ return;\ - }\ - for (int search_ns = ns; search_ns >= 0; --search_ns)\ - {\ - it = m_Map[search_ns].find(name);\ - if (it != m_Map[search_ns].end())\ - {\ - Get(it->second[0], value);\ - return;\ - }\ - }\ + Get(p.second->second[0], value);\ + }\ + template<>\ + void CConfigDB::GetValue(const CStr& name, const std::function& successCallback, EConfigNamespace ns)\ + {\ + CHECK_NS(;);\ + ENSURE(successCallback);\ + CScopeLock s(&cfgdb_mutex);\ + std::pair p = GetValueIterator(ns, name);\ + if (p.second == m_Map[p.first].end())\ + return;\ + TYPE value;\ + Get(p.second->second[0], value);\ + successCallback(value);\ } GETVAL(bool) GETVAL(int) @@ -125,6 +146,7 @@ GETVAL(float) GETVAL(double) GETVAL(std::string) +GETVAL(CStr) #undef GETVAL bool CConfigDB::HasChanges(EConfigNamespace ns) const Index: source/ps/ModIo.cpp =================================================================== --- source/ps/ModIo.cpp +++ source/ps/ModIo.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -72,17 +72,17 @@ // provide some shortcut/script that sets these using command line // parameters. std::string pk_str; - g_ConfigDB.GetValue(CFG_SYSTEM, "modio.public_key", pk_str); - g_ConfigDB.GetValue(CFG_SYSTEM, "modio.v1.baseurl", m_BaseUrl); + g_ConfigDB.GetValue("modio.public_key", pk_str, CFG_SYSTEM); + g_ConfigDB.GetValue("modio.v1.baseurl", m_BaseUrl, CFG_SYSTEM); { std::string api_key; - g_ConfigDB.GetValue(CFG_SYSTEM, "modio.v1.api_key", api_key); + g_ConfigDB.GetValue("modio.v1.api_key", api_key, CFG_SYSTEM); m_ApiKey = "api_key=" + api_key; } { std::string nameid; - g_ConfigDB.GetValue(CFG_SYSTEM, "modio.v1.name_id", nameid); - m_IdQuery = "name_id="+nameid; + g_ConfigDB.GetValue("modio.v1.name_id", nameid, CFG_SYSTEM); + m_IdQuery = "name_id=" + nameid; } m_CurlMulti = curl_multi_init(); Index: source/ps/VideoMode.cpp =================================================================== --- source/ps/VideoMode.cpp +++ source/ps/VideoMode.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -60,9 +60,9 @@ void CVideoMode::ReadConfig() { - bool windowed = !m_ConfigFullscreen; - CFG_GET_VAL("windowed", windowed); - m_ConfigFullscreen = !windowed; + g_ConfigDB.GetValue("windowed", [this](const bool& windowed) { + m_ConfigFullscreen = !windowed; + }); CFG_GET_VAL("xres", m_ConfigW); CFG_GET_VAL("yres", m_ConfigH); Index: source/ps/scripting/JSInterface_ConfigDB.cpp =================================================================== --- source/ps/scripting/JSInterface_ConfigDB.cpp +++ source/ps/scripting/JSInterface_ConfigDB.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -89,7 +89,7 @@ return std::string(); std::string value; - g_ConfigDB.GetValue(cfgNs, name, value); + g_ConfigDB.GetValue(name, value, cfgNs); return value; }