]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/settings.cpp
Clean up l_object.cpp (#10512)
[dragonfireclient.git] / src / settings.cpp
index 876c63e7b2c1ea57019a35a6b57f91be73f9463b..f30ef34e9ff5a2125340e4e837914e9a59de67e8 100644 (file)
@@ -45,7 +45,13 @@ Settings::~Settings()
 
 Settings & Settings::operator += (const Settings &other)
 {
-       update(other);
+       if (&other == this)
+               return *this;
+
+       MutexAutoLock lock(m_mutex);
+       MutexAutoLock lock2(other.m_mutex);
+
+       updateNoLock(other);
 
        return *this;
 }
@@ -484,30 +490,32 @@ v3f Settings::getV3F(const std::string &name) const
 u32 Settings::getFlagStr(const std::string &name, const FlagDesc *flagdesc,
        u32 *flagmask) const
 {
-       std::string val = get(name);
-       return std::isdigit(val[0])
-               ? stoi(val)
-               : readFlagString(val, flagdesc, flagmask);
-}
+       u32 flags = 0;
+       u32 mask_default = 0;
 
+       std::string value;
+       // Read default value (if there is any)
+       if (getDefaultNoEx(name, value)) {
+               flags = std::isdigit(value[0])
+                       ? stoi(value)
+                       : readFlagString(value, flagdesc, &mask_default);
+       }
 
-// N.B. if getStruct() is used to read a non-POD aggregate type,
-// the behavior is undefined.
-bool Settings::getStruct(const std::string &name, const std::string &format,
-       void *out, size_t olen) const
-{
-       std::string valstr;
+       // Apply custom flags "on top"
+       value = get(name);
+       u32 flags_user;
+       u32 mask_user = U32_MAX;
+       flags_user = std::isdigit(value[0])
+               ? stoi(value) // Override default
+               : readFlagString(value, flagdesc, &mask_user);
 
-       try {
-               valstr = get(name);
-       } catch (SettingNotFoundException &e) {
-               return false;
-       }
+       flags &= ~mask_user;
+       flags |=  flags_user;
 
-       if (!deSerializeStringToStruct(valstr, format, out, olen))
-               return false;
+       if (flagmask)
+               *flagmask = mask_default | mask_user;
 
-       return true;
+       return flags;
 }
 
 
@@ -525,6 +533,7 @@ bool Settings::getNoiseParamsFromValue(const std::string &name,
        if (!getNoEx(name, value))
                return false;
 
+       // Format: f32,f32,(f32,f32,f32),s32,s32,f32[,f32]
        Strfnd f(value);
 
        np.offset   = stof(f.next(","));
@@ -594,28 +603,6 @@ std::vector<std::string> Settings::getNames() const
  * Getters that don't throw exceptions *
  ***************************************/
 
-bool Settings::getEntryNoEx(const std::string &name, SettingsEntry &val) const
-{
-       try {
-               val = getEntry(name);
-               return true;
-       } catch (SettingNotFoundException &e) {
-               return false;
-       }
-}
-
-
-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 {
@@ -736,19 +723,16 @@ bool Settings::getV3FNoEx(const std::string &name, v3f &val) const
 }
 
 
-// N.B. getFlagStrNoEx() does not set val, but merely modifies it.  Thus,
-// val must be initialized before using getFlagStrNoEx().  The intention of
-// this is to simplify modifying a flags field from a default value.
 bool Settings::getFlagStrNoEx(const std::string &name, u32 &val,
-       FlagDesc *flagdesc) const
+       const FlagDesc *flagdesc) const
 {
-       try {
-               u32 flags, flagmask;
-
-               flags = getFlagStr(name, flagdesc, &flagmask);
+       if (!flagdesc) {
+               if (!(flagdesc = getFlagDescFallback(name)))
+                       return false; // Not found
+       }
 
-               val &= ~flagmask;
-               val |=  flags;
+       try {
+               val = getFlagStr(name, flagdesc, nullptr);
 
                return true;
        } catch (SettingNotFoundException &e) {
@@ -804,15 +788,23 @@ bool Settings::setDefault(const std::string &name, const std::string &value)
 }
 
 
-bool Settings::setGroup(const std::string &name, Settings *group)
+bool Settings::setGroup(const std::string &name, const Settings &group)
 {
-       return setEntry(name, &group, true, false);
+       // Settings must own the group pointer
+       // avoid double-free by copying the source
+       Settings *copy = new Settings();
+       *copy = group;
+       return setEntry(name, &copy, true, false);
 }
 
 
-bool Settings::setGroupDefault(const std::string &name, Settings *group)
+bool Settings::setGroupDefault(const std::string &name, const Settings &group)
 {
-       return setEntry(name, &group, true, true);
+       // Settings must own the group pointer
+       // avoid double-free by copying the source
+       Settings *copy = new Settings();
+       *copy = group;
+       return setEntry(name, &copy, true, true);
 }
 
 
@@ -873,18 +865,12 @@ bool Settings::setV3F(const std::string &name, v3f value)
 bool Settings::setFlagStr(const std::string &name, u32 flags,
        const FlagDesc *flagdesc, u32 flagmask)
 {
-       return set(name, writeFlagString(flags, flagdesc, flagmask));
-}
-
-
-bool Settings::setStruct(const std::string &name, const std::string &format,
-       void *value)
-{
-       std::string structstr;
-       if (!serializeStructToString(&structstr, format, value))
-               return false;
+       if (!flagdesc) {
+               if (!(flagdesc = getFlagDescFallback(name)))
+                       return false; // Not found
+       }
 
-       return set(name, structstr);
+       return set(name, writeFlagString(flags, flagdesc, flagmask));
 }
 
 
@@ -908,17 +894,20 @@ bool Settings::setNoiseParams(const std::string &name,
 
 bool Settings::remove(const std::string &name)
 {
-       MutexAutoLock lock(m_mutex);
+       // Lock as short as possible, unlock before doCallbacks()
+       m_mutex.lock();
 
        SettingEntries::iterator it = m_settings.find(name);
        if (it != m_settings.end()) {
                delete it->second.group;
                m_settings.erase(it);
+               m_mutex.unlock();
 
                doCallbacks(name);
                return true;
        }
 
+       m_mutex.unlock();
        return false;
 }
 
@@ -935,32 +924,6 @@ void Settings::clearDefaults()
        clearDefaultsNoLock();
 }
 
-void Settings::updateValue(const Settings &other, const std::string &name)
-{
-       if (&other == this)
-               return;
-
-       MutexAutoLock lock(m_mutex);
-
-       try {
-               m_settings[name] = other.get(name);
-       } catch (SettingNotFoundException &e) {
-       }
-}
-
-
-void Settings::update(const Settings &other)
-{
-       if (&other == this)
-               return;
-
-       MutexAutoLock lock(m_mutex);
-       MutexAutoLock lock2(other.m_mutex);
-
-       updateNoLock(other);
-}
-
-
 SettingsParseEvent Settings::parseConfigObject(const std::string &line,
        const std::string &end, std::string &name, std::string &value)
 {
@@ -1015,6 +978,42 @@ void Settings::clearDefaultsNoLock()
        m_defaults.clear();
 }
 
+void Settings::setDefault(const std::string &name, const FlagDesc *flagdesc,
+       u32 flags)
+{
+       m_flags[name] = flagdesc;
+       setDefault(name, writeFlagString(flags, flagdesc, U32_MAX));
+}
+
+void Settings::overrideDefaults(Settings *other)
+{
+       for (const auto &setting : other->m_settings) {
+               if (setting.second.is_group) {
+                       setGroupDefault(setting.first, *setting.second.group);
+                       continue;
+               }
+               const FlagDesc *flagdesc = getFlagDescFallback(setting.first);
+               if (flagdesc) {
+                       // Flags cannot be copied directly.
+                       // 1) Get the current set flags
+                       u32 flags = getFlagStr(setting.first, flagdesc, nullptr);
+                       // 2) Set the flags as defaults
+                       other->setDefault(setting.first, flagdesc, flags);
+                       // 3) Get the newly set flags and override the default setting value
+                       setDefault(setting.first, flagdesc,
+                               other->getFlagStr(setting.first, flagdesc, nullptr));
+                       continue;
+               }
+               // Also covers FlagDesc settings
+               setDefault(setting.first, setting.second.value);
+       }
+}
+
+const FlagDesc *Settings::getFlagDescFallback(const std::string &name) const
+{
+       auto it = m_flags.find(name);
+       return it == m_flags.end() ? nullptr : it->second;
+}
 
 void Settings::registerChangedCallback(const std::string &name,
        SettingsChangedCallback cbf, void *userdata)
@@ -1040,6 +1039,19 @@ void Settings::deregisterChangedCallback(const std::string &name,
        }
 }
 
+void Settings::removeSecureSettings()
+{
+       for (const auto &name : getNames()) {
+               if (name.compare(0, 7, "secure.") != 0)
+                       continue;
+
+               errorstream << "Secure setting " << name
+                               << " isn't allowed, so was ignored."
+                               << std::endl;
+               remove(name);
+       }
+}
+
 void Settings::doCallbacks(const std::string &name) const
 {
        MutexAutoLock lock(m_callback_mutex);