X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsettings.cpp;h=e95bd436d527dcda81df3d98186380880ca90712;hb=c6766b275f25368e78eeffc68719b0ca1979c819;hp=8d2e9fa6c8a699c0240e19dabdacdc8977da277c;hpb=b0c4fd6d3f1c8e44896358ee9b0af20e9b304944;p=oweals%2Fminetest.git diff --git a/src/settings.cpp b/src/settings.cpp index 8d2e9fa6c..e95bd436d 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -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() { @@ -63,11 +66,36 @@ 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::sanitizeName(const std::string &name) { - std::string n(name); + std::string n = trim(name); - for (const char *s = "\t\n\v\f\r\b =\"{}#"; *s; s++) + for (const char *s = "=\"{}#"; *s; s++) n.erase(std::remove(n.begin(), n.end(), *s), n.end()); return n; @@ -230,7 +258,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"; @@ -241,7 +268,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 { @@ -704,112 +731,119 @@ 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; - std::string n = sanitizeName(name); + if (!checkNameValid(name)) + return false; + if (!set_group && !checkValueValid(*(const std::string *)data)) + return false; { JMutexAutoLock 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 ? "" : sanitizeValue(*(const std::string *)data); + entry.value = set_group ? "" : *(const std::string *)data; entry.group = set_group ? *(Settings **)data : NULL; entry.is_group = set_group; } 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)); } @@ -820,12 +854,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; @@ -839,7 +872,7 @@ 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); } @@ -858,6 +891,11 @@ void Settings::clear() clearNoLock(); } +void Settings::clearDefaults() +{ + JMutexAutoLock lock(m_mutex); + clearDefaultsNoLock(); +} void Settings::updateValue(const Settings &other, const std::string &name) { @@ -929,6 +967,12 @@ void Settings::clearNoLock() delete it->second.group; m_settings.clear(); + clearDefaultsNoLock(); +} + +void Settings::clearDefaultsNoLock() +{ + std::map::const_iterator it; for (it = m_defaults.begin(); it != m_defaults.end(); ++it) delete it->second.group; m_defaults.clear(); @@ -936,26 +980,38 @@ void Settings::clearNoLock() void Settings::registerChangedCallback(std::string name, - setting_changed_callback cbf) + setting_changed_callback cbf, void *userdata) { - m_callbacks[name].push_back(cbf); + JMutexAutoLock lock(m_callbackMutex); + m_callbacks[name].push_back(std::make_pair(cbf, userdata)); } +void Settings::deregisterChangedCallback(std::string name, setting_changed_callback cbf, void *userdata) +{ + JMutexAutoLock lock(m_callbackMutex); + std::map > >::iterator iterToVector = m_callbacks.find(name); + if (iterToVector != m_callbacks.end()) + { + std::vector > &vector = iterToVector->second; + + std::vector >::iterator position = + std::find(vector.begin(), vector.end(), std::make_pair(cbf, userdata)); + + if (position != vector.end()) + vector.erase(position); + } +} void Settings::doCallbacks(const std::string name) { - std::vector tempvector; + JMutexAutoLock lock(m_callbackMutex); + std::map > >::iterator iterToVector = m_callbacks.find(name); + if (iterToVector != m_callbacks.end()) { - JMutexAutoLock lock(m_mutex); - if (m_callbacks.find(name) != m_callbacks.end()) + std::vector >::iterator iter; + for (iter = iterToVector->second.begin(); iter != iterToVector->second.end(); iter++) { - tempvector = m_callbacks[name]; + (iter->first)(name, iter->second); } } - - std::vector::iterator iter; - for (iter = tempvector.begin(); iter != tempvector.end(); iter++) - { - (*iter)(name); - } }