X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fsettings.cpp;h=0c34eb10c921b7236db6423204ec7a5fd3d4a1b0;hb=1e94a7feaff940494a474ee549d4f2dc61f6a869;hp=d1a2576074f880ed24889fe4a3390283c0d2c390;hpb=a89f37bb653eda393d835b9546ec86244d3932b6;p=minetest.git diff --git a/src/settings.cpp b/src/settings.cpp index d1a257607..0c34eb10c 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -20,8 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "irrlichttypes_bloated.h" #include "exceptions.h" -#include "jthread/jmutexautolock.h" -#include "strfnd.h" +#include "threading/mutex_auto_lock.h" +#include "util/strfnd.h" #include #include #include @@ -33,6 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +static Settings main_settings; +Settings *g_settings = &main_settings; +std::string g_settings_path; Settings::~Settings() { @@ -53,8 +56,8 @@ Settings & Settings::operator = (const Settings &other) if (&other == this) return *this; - JMutexAutoLock lock(m_mutex); - JMutexAutoLock lock2(other.m_mutex); + MutexAutoLock lock(m_mutex); + MutexAutoLock lock2(other.m_mutex); clearNoLock(); updateNoLock(other); @@ -63,6 +66,30 @@ Settings & Settings::operator = (const Settings &other) } +bool Settings::checkNameValid(const std::string &name) +{ + bool valid = name.find_first_of("=\"{}#") == std::string::npos; + if (valid) valid = trim(name) == name; + if (!valid) { + errorstream << "Invalid setting name \"" << name << "\"" + << std::endl; + return false; + } + return true; +} + + +bool Settings::checkValueValid(const std::string &value) +{ + if (value.substr(0, 3) == "\"\"\"" || + value.find("\n\"\"\"") != std::string::npos) { + errorstream << "Invalid character sequence '\"\"\"' found in" + " setting value!" << std::endl; + return false; + } + return true; +} + std::string Settings::getMultiline(std::istream &is, size_t *num_lines) { size_t lines = 1; @@ -101,7 +128,7 @@ bool Settings::readConfigFile(const char *filename) bool Settings::parseConfigLines(std::istream &is, const std::string &end) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::string line, name, value; @@ -140,12 +167,10 @@ bool Settings::parseConfigLines(std::istream &is, const std::string &end) void Settings::writeLines(std::ostream &os, u32 tab_depth) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); - for (std::map::const_iterator - it = m_settings.begin(); - it != m_settings.end(); ++it) - printEntry(os, it->first, it->second, tab_depth); + for (const auto &setting_it : m_settings) + printEntry(os, setting_it.first, setting_it.second, tab_depth); } @@ -177,7 +202,7 @@ void Settings::printEntry(std::ostream &os, const std::string &name, bool Settings::updateConfigObject(std::istream &is, std::ostream &os, const std::string &end, u32 tab_depth) { - std::map::const_iterator it; + SettingEntries::const_iterator it; std::set present_entries; std::string line, name, value; bool was_modified = false; @@ -204,7 +229,6 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, printEntry(os, name, it->second, tab_depth); was_modified = true; } else { - assert(it->second.group == NULL); os << line << "\n"; if (event == SPE_MULTILINE) os << value << "\n\"\"\"\n"; @@ -215,7 +239,7 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, it = m_settings.find(name); if (it != m_settings.end() && it->second.is_group) { os << line << "\n"; - assert(it->second.group != NULL); + sanity_check(it->second.group != NULL); was_modified |= it->second.group->updateConfigObject(is, os, "}", tab_depth + 1); } else { @@ -245,7 +269,7 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, bool Settings::updateConfigFile(const char *filename) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::ifstream is(filename); std::ostringstream os(std::ios_base::binary); @@ -298,7 +322,7 @@ bool Settings::parseCommandLine(int argc, char *argv[], ValueType type = n->second.type; - std::string value = ""; + std::string value; if (type == VALUETYPE_FLAG) { value = "true"; @@ -326,9 +350,9 @@ bool Settings::parseCommandLine(int argc, char *argv[], const SettingsEntry &Settings::getEntry(const std::string &name) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); - std::map::const_iterator n; + SettingEntries::const_iterator n; if ((n = m_settings.find(name)) == m_settings.end()) { if ((n = m_defaults.find(name)) == m_defaults.end()) throw SettingNotFoundException("Setting [" + name + "] not found."); @@ -337,6 +361,18 @@ const SettingsEntry &Settings::getEntry(const std::string &name) const } +const SettingsEntry &Settings::getEntryDefault(const std::string &name) const +{ + MutexAutoLock lock(m_mutex); + + SettingEntries::const_iterator n; + if ((n = m_defaults.find(name)) == m_defaults.end()) { + throw SettingNotFoundException("Setting [" + name + "] not found."); + } + return n->second; +} + + Settings *Settings::getGroup(const std::string &name) const { const SettingsEntry &entry = getEntry(name); @@ -346,7 +382,7 @@ Settings *Settings::getGroup(const std::string &name) const } -std::string Settings::get(const std::string &name) const +const std::string &Settings::get(const std::string &name) const { const SettingsEntry &entry = getEntry(name); if (entry.is_group) @@ -355,6 +391,15 @@ std::string Settings::get(const std::string &name) const } +const std::string &Settings::getDefault(const std::string &name) const +{ + const SettingsEntry &entry = getEntryDefault(name); + if (entry.is_group) + throw SettingNotFoundException("Setting [" + name + "] is a group."); + return entry.value; +} + + bool Settings::getBool(const std::string &name) const { return is_yes(get(name)); @@ -373,6 +418,11 @@ s16 Settings::getS16(const std::string &name) const } +u32 Settings::getU32(const std::string &name) const +{ + return (u32) stoi(get(name)); +} + s32 Settings::getS32(const std::string &name) const { return stoi(get(name)); @@ -476,7 +526,7 @@ bool Settings::getNoiseParamsFromValue(const std::string &name, np.persist = stof(f.next(",")); std::string optional_params = f.next(""); - if (optional_params != "") + if (!optional_params.empty()) np.lacunarity = stof(optional_params); return true; @@ -509,7 +559,7 @@ bool Settings::getNoiseParamsFromGroup(const std::string &name, bool Settings::exists(const std::string &name) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return (m_settings.find(name) != m_settings.end() || m_defaults.find(name) != m_defaults.end()); @@ -519,10 +569,8 @@ bool Settings::exists(const std::string &name) const std::vector Settings::getNames() const { std::vector names; - for (std::map::const_iterator - i = m_settings.begin(); - i != m_settings.end(); ++i) { - names.push_back(i->first); + for (const auto &settings_it : m_settings) { + names.push_back(settings_it.first); } return names; } @@ -544,6 +592,17 @@ bool Settings::getEntryNoEx(const std::string &name, SettingsEntry &val) const } +bool Settings::getEntryDefaultNoEx(const std::string &name, SettingsEntry &val) const +{ + try { + val = getEntryDefault(name); + return true; + } catch (SettingNotFoundException &e) { + return false; + } +} + + bool Settings::getGroupNoEx(const std::string &name, Settings *&val) const { try { @@ -566,6 +625,17 @@ bool Settings::getNoEx(const std::string &name, std::string &val) const } +bool Settings::getDefaultNoEx(const std::string &name, std::string &val) const +{ + try { + val = getDefault(name); + return true; + } catch (SettingNotFoundException &e) { + return false; + } +} + + bool Settings::getFlag(const std::string &name) const { try { @@ -678,21 +748,20 @@ bool Settings::getFlagStrNoEx(const std::string &name, u32 &val, * Setters * ***********/ -void Settings::setEntry(const std::string &name, const void *data, +bool Settings::setEntry(const std::string &name, const void *data, bool set_group, bool set_default) { Settings *old_group = NULL; - // Strip any potentially dangerous characters from the name (note the value - // has no such restrictions) - std::string n(name); - for (const char *s = "\t\n\v\f\r\b =\""; *s; s++) - n.erase(std::remove(n.begin(), n.end(), *s), n.end()); + if (!checkNameValid(name)) + return false; + if (!set_group && !checkValueValid(*(const std::string *)data)) + return false; { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); - SettingsEntry &entry = set_default ? m_defaults[n] : m_settings[n]; + SettingsEntry &entry = set_default ? m_defaults[name] : m_settings[name]; old_group = entry.group; entry.value = set_group ? "" : *(const std::string *)data; @@ -701,93 +770,97 @@ void Settings::setEntry(const std::string &name, const void *data, } delete old_group; + + return true; } -void Settings::set(const std::string &name, const std::string &value) +bool Settings::set(const std::string &name, const std::string &value) { - setEntry(name, &value, false, false); + if (!setEntry(name, &value, false, false)) + return false; doCallbacks(name); + return true; } -void Settings::setDefault(const std::string &name, const std::string &value) +bool Settings::setDefault(const std::string &name, const std::string &value) { - setEntry(name, &value, false, true); + return setEntry(name, &value, false, true); } -void Settings::setGroup(const std::string &name, Settings *group) +bool Settings::setGroup(const std::string &name, Settings *group) { - setEntry(name, &group, true, false); + return setEntry(name, &group, true, false); } -void Settings::setGroupDefault(const std::string &name, Settings *group) +bool Settings::setGroupDefault(const std::string &name, Settings *group) { - setEntry(name, &group, true, true); + return setEntry(name, &group, true, true); } -void Settings::setBool(const std::string &name, bool value) +bool Settings::setBool(const std::string &name, bool value) { - set(name, value ? "true" : "false"); + return set(name, value ? "true" : "false"); } -void Settings::setS16(const std::string &name, s16 value) +bool Settings::setS16(const std::string &name, s16 value) { - set(name, itos(value)); + return set(name, itos(value)); } -void Settings::setU16(const std::string &name, u16 value) +bool Settings::setU16(const std::string &name, u16 value) { - set(name, itos(value)); + return set(name, itos(value)); } -void Settings::setS32(const std::string &name, s32 value) +bool Settings::setS32(const std::string &name, s32 value) { - set(name, itos(value)); + return set(name, itos(value)); } -void Settings::setU64(const std::string &name, u64 value) +bool Settings::setU64(const std::string &name, u64 value) { std::ostringstream os; os << value; - set(name, os.str()); + return set(name, os.str()); } -void Settings::setFloat(const std::string &name, float value) +bool Settings::setFloat(const std::string &name, float value) { - set(name, ftos(value)); + return set(name, ftos(value)); } -void Settings::setV2F(const std::string &name, v2f value) +bool Settings::setV2F(const std::string &name, v2f value) { std::ostringstream os; os << "(" << value.X << "," << value.Y << ")"; - set(name, os.str()); + return set(name, os.str()); } -void Settings::setV3F(const std::string &name, v3f value) +bool Settings::setV3F(const std::string &name, v3f value) { std::ostringstream os; os << "(" << value.X << "," << value.Y << "," << value.Z << ")"; - set(name, os.str()); + return set(name, os.str()); } -void Settings::setFlagStr(const std::string &name, u32 flags, +bool Settings::setFlagStr(const std::string &name, u32 flags, const FlagDesc *flagdesc, u32 flagmask) { - set(name, writeFlagString(flags, flagdesc, flagmask)); + return set(name, writeFlagString(flags, flagdesc, flagmask)); } @@ -798,12 +871,11 @@ bool Settings::setStruct(const std::string &name, const std::string &format, if (!serializeStructToString(&structstr, format, value)) return false; - set(name, structstr); - return true; + return set(name, structstr); } -void Settings::setNoiseParams(const std::string &name, +bool Settings::setNoiseParams(const std::string &name, const NoiseParams &np, bool set_default) { Settings *group = new Settings; @@ -817,37 +889,46 @@ void Settings::setNoiseParams(const std::string &name, group->setFloat("lacunarity", np.lacunarity); group->setFlagStr("flags", np.flags, flagdesc_noiseparams, np.flags); - setEntry(name, &group, true, set_default); + return setEntry(name, &group, true, set_default); } bool Settings::remove(const std::string &name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); - delete m_settings[name].group; - return m_settings.erase(name); + SettingEntries::iterator it = m_settings.find(name); + if (it != m_settings.end()) { + delete it->second.group; + m_settings.erase(it); + return true; + } + + return false; } void Settings::clear() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); clearNoLock(); } +void Settings::clearDefaults() +{ + MutexAutoLock lock(m_mutex); + clearDefaultsNoLock(); +} void Settings::updateValue(const Settings &other, const std::string &name) { if (&other == this) return; - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); try { - std::string val = other.get(name); - - m_settings[name] = val; + m_settings[name] = other.get(name); } catch (SettingNotFoundException &e) { } } @@ -858,8 +939,8 @@ void Settings::update(const Settings &other) if (&other == this) return; - JMutexAutoLock lock(m_mutex); - JMutexAutoLock lock2(other.m_mutex); + MutexAutoLock lock(m_mutex); + MutexAutoLock lock2(other.m_mutex); updateNoLock(other); } @@ -902,38 +983,56 @@ void Settings::updateNoLock(const Settings &other) void Settings::clearNoLock() { - std::map::const_iterator it; - for (it = m_settings.begin(); it != m_settings.end(); ++it) + + for (SettingEntries::const_iterator it = m_settings.begin(); + it != m_settings.end(); ++it) delete it->second.group; m_settings.clear(); - for (it = m_defaults.begin(); it != m_defaults.end(); ++it) + clearDefaultsNoLock(); +} + +void Settings::clearDefaultsNoLock() +{ + for (SettingEntries::const_iterator it = m_defaults.begin(); + it != m_defaults.end(); ++it) delete it->second.group; m_defaults.clear(); } -void Settings::registerChangedCallback(std::string name, - setting_changed_callback cbf) +void Settings::registerChangedCallback(const std::string &name, + SettingsChangedCallback cbf, void *userdata) { - m_callbacks[name].push_back(cbf); + MutexAutoLock lock(m_callback_mutex); + m_callbacks[name].emplace_back(cbf, userdata); } - -void Settings::doCallbacks(const std::string name) +void Settings::deregisterChangedCallback(const std::string &name, + SettingsChangedCallback cbf, void *userdata) { - std::vector tempvector; - { - JMutexAutoLock lock(m_mutex); - if (m_callbacks.find(name) != m_callbacks.end()) - { - tempvector = m_callbacks[name]; - } + MutexAutoLock lock(m_callback_mutex); + SettingsCallbackMap::iterator it_cbks = m_callbacks.find(name); + + if (it_cbks != m_callbacks.end()) { + SettingsCallbackList &cbks = it_cbks->second; + + SettingsCallbackList::iterator position = + std::find(cbks.begin(), cbks.end(), std::make_pair(cbf, userdata)); + + if (position != cbks.end()) + cbks.erase(position); } +} - std::vector::iterator iter; - for (iter = tempvector.begin(); iter != tempvector.end(); iter++) - { - (*iter)(name); +void Settings::doCallbacks(const std::string &name) const +{ + MutexAutoLock lock(m_callback_mutex); + + SettingsCallbackMap::const_iterator it_cbks = m_callbacks.find(name); + if (it_cbks != m_callbacks.end()) { + SettingsCallbackList::const_iterator it; + for (it = it_cbks->second.begin(); it != it_cbks->second.end(); ++it) + (it->first)(name, it->second); } }