bool Settings::checkNameValid(const std::string &name)
{
bool valid = name.find_first_of("=\"{}#") == std::string::npos;
- if (valid) valid = trim(name) == name;
+ if (valid)
+ valid = std::find_if(name.begin(), name.end(), ::isspace) == name.end();
+
if (!valid) {
errorstream << "Invalid setting name \"" << name << "\""
<< std::endl;
} else if (it == m_settings.end()) {
// Remove by skipping
was_modified = true;
+ Settings removed_group; // Move 'is' to group end
+ std::stringstream ss;
+ removed_group.updateConfigObject(is, ss, "}", tab_depth + 1);
break;
} else {
printEntry(os, name, it->second, tab_depth);
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);
+ }
+
+ // 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);
+ flags &= ~mask_user;
+ flags |= flags_user;
+
+ if (flagmask)
+ *flagmask = mask_default | mask_user;
+
+ return flags;
+}
// N.B. if getStruct() is used to read a non-POD aggregate type,
// the behavior is undefined.
}
-// 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) {
bool Settings::setFlagStr(const std::string &name, u32 flags,
const FlagDesc *flagdesc, u32 flagmask)
{
+ if (!flagdesc) {
+ if (!(flagdesc = getFlagDescFallback(name)))
+ return false; // Not found
+ }
+
return set(name, writeFlagString(flags, flagdesc, flagmask));
}
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;
}
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)