mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-12 16:58:39 +00:00
Split settings into seperate source and header files
This also cleans up settings a bit
This commit is contained in:
parent
2ae5d3f3ab
commit
6bc4cad0ed
27 changed files with 996 additions and 941 deletions
818
src/settings.h
818
src/settings.h
|
@ -21,23 +21,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define SETTINGS_HEADER
|
||||
|
||||
#include "irrlichttypes_bloated.h"
|
||||
#include "exceptions.h"
|
||||
#include <string>
|
||||
#include "jthread/jmutex.h"
|
||||
#include "jthread/jmutexautolock.h"
|
||||
#include "strfnd.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
#include "util/string.h"
|
||||
#include "util/serialize.h"
|
||||
#include <list>
|
||||
#include "jthread/jmutex.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include "filesys.h"
|
||||
#include <cctype>
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
|
@ -56,753 +45,126 @@ struct ValueSpec
|
|||
const char *help;
|
||||
};
|
||||
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings()
|
||||
{
|
||||
}
|
||||
Settings() {}
|
||||
|
||||
void writeLines(std::ostream &os) const
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_settings.begin();
|
||||
i != m_settings.end(); ++i)
|
||||
{
|
||||
std::string name = i->first;
|
||||
std::string value = i->second;
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
// return all keys used
|
||||
std::vector<std::string> getNames() const
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_settings.begin();
|
||||
i != m_settings.end(); ++i)
|
||||
{
|
||||
names.push_back(i->first);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// remove a setting
|
||||
bool remove(const std::string &name)
|
||||
{
|
||||
return m_settings.erase(name);
|
||||
}
|
||||
Settings & operator += (const Settings &other);
|
||||
Settings & operator = (const Settings &other);
|
||||
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
/***********************
|
||||
* Reading and writing *
|
||||
***********************/
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore empty lines and comments
|
||||
if(trimmedline.size() == 0 || trimmedline[0] == '#')
|
||||
return true;
|
||||
|
||||
//infostream<<"trimmedline=\""<<trimmedline<<"\""<<std::endl;
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
return true;
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
/*infostream<<"Config name=\""<<name<<"\" value=\""
|
||||
<<value<<"\""<<std::endl;*/
|
||||
|
||||
m_settings[name] = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseConfigLines(std::istream &is, const std::string &endstring)
|
||||
{
|
||||
for(;;){
|
||||
if(is.eof())
|
||||
break;
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
std::string trimmedline = trim(line);
|
||||
if(endstring != ""){
|
||||
if(trimmedline == endstring)
|
||||
break;
|
||||
}
|
||||
parseConfigLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
/*
|
||||
NOTE: This function might be expanded to allow multi-line
|
||||
settings.
|
||||
*/
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//infostream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
|
||||
return parseConfigLine(line);
|
||||
}
|
||||
|
||||
/*
|
||||
Read configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool readConfigFile(const char *filename)
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
return false;
|
||||
|
||||
/*infostream<<"Parsing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;*/
|
||||
|
||||
while(parseConfigObject(is));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Reads a configuration object from stream (usually a single line)
|
||||
and adds it to dst.
|
||||
|
||||
Preserves comments and empty lines.
|
||||
|
||||
Settings that were added to dst are also added to updated.
|
||||
key of updated is setting name, value of updated is dummy.
|
||||
|
||||
Returns false on EOF
|
||||
*/
|
||||
bool getUpdatedConfigObject(std::istream &is,
|
||||
std::list<std::string> &dst,
|
||||
std::set<std::string> &updated,
|
||||
bool &value_changed)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
std::string line_end = "";
|
||||
if(is.eof() == false)
|
||||
line_end = "\n";
|
||||
|
||||
// Ignore empty lines and comments
|
||||
if(trimmedline.size() == 0 || trimmedline[0] == '#')
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
Strfnd sf(trim(line));
|
||||
|
||||
std::string name = sf.next("=");
|
||||
name = trim(name);
|
||||
|
||||
if(name == "")
|
||||
{
|
||||
dst.push_back(line+line_end);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string value = sf.next("\n");
|
||||
value = trim(value);
|
||||
|
||||
if(m_settings.find(name) != m_settings.end())
|
||||
{
|
||||
std::string newvalue = m_settings[name];
|
||||
|
||||
if(newvalue != value)
|
||||
{
|
||||
infostream<<"Changing value of \""<<name<<"\" = \""
|
||||
<<value<<"\" -> \""<<newvalue<<"\""
|
||||
<<std::endl;
|
||||
value_changed = true;
|
||||
}
|
||||
|
||||
dst.push_back(name + " = " + newvalue + line_end);
|
||||
|
||||
updated.insert(name);
|
||||
}
|
||||
else //file contains a setting which is not in m_settings
|
||||
value_changed=true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates configuration file
|
||||
|
||||
Returns true on success
|
||||
*/
|
||||
bool updateConfigFile(const char *filename)
|
||||
{
|
||||
infostream<<"Updating configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
|
||||
std::list<std::string> objects;
|
||||
std::set<std::string> updated;
|
||||
bool something_actually_changed = false;
|
||||
|
||||
// Read and modify stuff
|
||||
{
|
||||
std::ifstream is(filename);
|
||||
if(is.good() == false)
|
||||
{
|
||||
infostream<<"updateConfigFile():"
|
||||
" Error opening configuration file"
|
||||
" for reading: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(getUpdatedConfigObject(is, objects, updated,
|
||||
something_actually_changed));
|
||||
}
|
||||
}
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
// If something not yet determined to have been changed, check if
|
||||
// any new stuff was added
|
||||
if(!something_actually_changed){
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_settings.begin();
|
||||
i != m_settings.end(); ++i)
|
||||
{
|
||||
if(updated.find(i->first) != updated.end())
|
||||
continue;
|
||||
something_actually_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing was actually changed, skip writing the file
|
||||
if(!something_actually_changed){
|
||||
infostream<<"Skipping writing of "<<filename
|
||||
<<" because content wouldn't be modified"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write stuff back
|
||||
{
|
||||
std::ostringstream ss(std::ios_base::binary);
|
||||
|
||||
/*
|
||||
Write updated stuff
|
||||
*/
|
||||
for(std::list<std::string>::const_iterator
|
||||
i = objects.begin();
|
||||
i != objects.end(); ++i)
|
||||
{
|
||||
ss<<(*i);
|
||||
}
|
||||
|
||||
/*
|
||||
Write stuff that was not already in the file
|
||||
*/
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
i = m_settings.begin();
|
||||
i != m_settings.end(); ++i)
|
||||
{
|
||||
if(updated.find(i->first) != updated.end())
|
||||
continue;
|
||||
std::string name = i->first;
|
||||
std::string value = i->second;
|
||||
infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
ss<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
|
||||
if(!fs::safeWriteToFile(filename, ss.str()))
|
||||
{
|
||||
errorstream<<"Error writing configuration file: \""
|
||||
<<filename<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: Types of allowed_options are ignored
|
||||
|
||||
returns true on success
|
||||
*/
|
||||
// Read configuration file. Returns success.
|
||||
bool readConfigFile(const char *filename);
|
||||
//Updates configuration file. Returns success.
|
||||
bool updateConfigFile(const char *filename);
|
||||
// NOTE: Types of allowed_options are ignored. Returns success.
|
||||
bool parseCommandLine(int argc, char *argv[],
|
||||
std::map<std::string, ValueSpec> &allowed_options)
|
||||
{
|
||||
int nonopt_index = 0;
|
||||
int i=1;
|
||||
for(;;)
|
||||
{
|
||||
if(i >= argc)
|
||||
break;
|
||||
std::string argname = argv[i];
|
||||
if(argname.substr(0, 2) != "--")
|
||||
{
|
||||
// If option doesn't start with -, read it in as nonoptX
|
||||
if(argname[0] != '-'){
|
||||
std::string name = "nonopt";
|
||||
name += itos(nonopt_index);
|
||||
set(name, argname);
|
||||
nonopt_index++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<argname<<"\": --<option> expected."<<std::endl;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
|
||||
std::string name = argname.substr(2);
|
||||
|
||||
std::map<std::string, ValueSpec>::iterator n;
|
||||
n = allowed_options.find(name);
|
||||
if(n == allowed_options.end())
|
||||
{
|
||||
errorstream<<"Unknown command-line parameter \""
|
||||
<<argname<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueType type = n->second.type;
|
||||
|
||||
std::string value = "";
|
||||
|
||||
if(type == VALUETYPE_FLAG)
|
||||
{
|
||||
value = "true";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i >= argc)
|
||||
{
|
||||
errorstream<<"Invalid command-line parameter \""
|
||||
<<name<<"\": missing value"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[i];
|
||||
i++;
|
||||
}
|
||||
std::map<std::string, ValueSpec> &allowed_options);
|
||||
bool parseConfigLines(std::istream &is, const std::string &end = "");
|
||||
void writeLines(std::ostream &os) const;
|
||||
|
||||
|
||||
infostream<<"Valid command-line parameter: \""
|
||||
<<name<<"\" = \""<<value<<"\""
|
||||
<<std::endl;
|
||||
set(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void set(const std::string &name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
void set(const std::string &name, const char *value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_settings[name] = value;
|
||||
}
|
||||
|
||||
|
||||
void setDefault(const std::string &name, std::string value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
m_defaults[name] = value;
|
||||
}
|
||||
|
||||
bool exists(const std::string &name) const
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
return (m_settings.find(name) != m_settings.end() ||
|
||||
m_defaults.find(name) != m_defaults.end());
|
||||
}
|
||||
|
||||
std::string get(const std::string &name) const
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
std::map<std::string, std::string>::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 ").c_str());
|
||||
|
||||
return n->second;
|
||||
}
|
||||
|
||||
//////////// Get setting
|
||||
bool getBool(const std::string &name) const
|
||||
{
|
||||
return is_yes(get(name));
|
||||
}
|
||||
|
||||
bool getFlag(const std::string &name) const
|
||||
{
|
||||
try {
|
||||
return getBool(name);
|
||||
} catch(SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
float getFloat(const std::string &name) const
|
||||
{
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(const std::string &name) const
|
||||
{
|
||||
return stoi(get(name), 0, 65535);
|
||||
}
|
||||
|
||||
s16 getS16(const std::string &name) const
|
||||
{
|
||||
return stoi(get(name), -32768, 32767);
|
||||
}
|
||||
|
||||
s32 getS32(const std::string &name) const
|
||||
{
|
||||
return stoi(get(name));
|
||||
}
|
||||
|
||||
v3f getV3F(const std::string &name) const
|
||||
{
|
||||
v3f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(","));
|
||||
value.Z = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
v2f getV2F(const std::string &name) const
|
||||
{
|
||||
v2f value;
|
||||
Strfnd f(get(name));
|
||||
f.next("(");
|
||||
value.X = stof(f.next(","));
|
||||
value.Y = stof(f.next(")"));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 getU64(const std::string &name) const
|
||||
{
|
||||
u64 value = 0;
|
||||
std::string s = get(name);
|
||||
std::istringstream ss(s);
|
||||
ss >> value;
|
||||
return value;
|
||||
}
|
||||
/***********
|
||||
* Getters *
|
||||
***********/
|
||||
|
||||
std::string get(const std::string &name) const;
|
||||
bool getBool(const std::string &name) const;
|
||||
u16 getU16(const std::string &name) const;
|
||||
s16 getS16(const std::string &name) const;
|
||||
s32 getS32(const std::string &name) const;
|
||||
u64 getU64(const std::string &name) const;
|
||||
float getFloat(const std::string &name) const;
|
||||
v2f getV2F(const std::string &name) const;
|
||||
v3f getV3F(const std::string &name) const;
|
||||
u32 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 *flagmask) const;
|
||||
// N.B. if getStruct() is used to read a non-POD aggregate type,
|
||||
// the behavior is undefined.
|
||||
bool getStruct(const std::string &name, const std::string &format,
|
||||
void *out, size_t olen) const
|
||||
{
|
||||
std::string valstr;
|
||||
void *out, size_t olen) const;
|
||||
|
||||
try {
|
||||
valstr = get(name);
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
// return all keys used
|
||||
std::vector<std::string> getNames() const;
|
||||
bool exists(const std::string &name) const;
|
||||
|
||||
if (!deSerializeStringToStruct(valstr, format, out, olen))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////// Try to get value, no exception thrown
|
||||
bool getNoEx(const std::string &name, std::string &val) const
|
||||
{
|
||||
try {
|
||||
val = get(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/***************************************
|
||||
* Getters that don't throw exceptions *
|
||||
***************************************/
|
||||
|
||||
bool getNoEx(const std::string &name, std::string &val) const;
|
||||
bool getFlag(const std::string &name) const;
|
||||
bool getU16NoEx(const std::string &name, u16 &val) const;
|
||||
bool getS16NoEx(const std::string &name, s16 &val) const;
|
||||
bool getS32NoEx(const std::string &name, s32 &val) const;
|
||||
bool getU64NoEx(const std::string &name, u64 &val) const;
|
||||
bool getFloatNoEx(const std::string &name, float &val) const;
|
||||
bool getV2FNoEx(const std::string &name, v2f &val) const;
|
||||
bool 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 getFlagStrNoEx(const std::string &name, u32 &val, FlagDesc *flagdesc) const
|
||||
{
|
||||
try {
|
||||
u32 flags, flagmask;
|
||||
bool getFlagStrNoEx(const std::string &name, u32 &val, FlagDesc *flagdesc) const;
|
||||
|
||||
flags = getFlagStr(name, flagdesc, &flagmask);
|
||||
|
||||
val &= ~flagmask;
|
||||
val |= flags;
|
||||
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getFloatNoEx(const std::string &name, float &val) const
|
||||
{
|
||||
try {
|
||||
val = getFloat(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getU16NoEx(const std::string &name, int &val) const
|
||||
{
|
||||
try {
|
||||
val = getU16(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getU16NoEx(const std::string &name, u16 &val) const
|
||||
{
|
||||
try {
|
||||
val = getU16(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getS16NoEx(const std::string &name, int &val) const
|
||||
{
|
||||
try {
|
||||
val = getU16(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getS16NoEx(const std::string &name, s16 &val) const
|
||||
{
|
||||
try {
|
||||
val = getS16(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getS32NoEx(const std::string &name, s32 &val) const
|
||||
{
|
||||
try {
|
||||
val = getS32(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getV3FNoEx(const std::string &name, v3f &val) const
|
||||
{
|
||||
try {
|
||||
val = getV3F(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getV2FNoEx(const std::string &name, v2f &val) const
|
||||
{
|
||||
try {
|
||||
val = getV2F(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool getU64NoEx(const std::string &name, u64 &val) const
|
||||
{
|
||||
try {
|
||||
val = getU64(name);
|
||||
return true;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////// Set setting
|
||||
/***********
|
||||
* Setters *
|
||||
***********/
|
||||
|
||||
void set(const std::string &name, std::string value);
|
||||
void set(const std::string &name, const char *value);
|
||||
void setDefault(const std::string &name, std::string value);
|
||||
void setBool(const std::string &name, bool value);
|
||||
void setS16(const std::string &name, s16 value);
|
||||
void setS32(const std::string &name, s32 value);
|
||||
void setU64(const std::string &name, u64 value);
|
||||
void setFloat(const std::string &name, float value);
|
||||
void setV2F(const std::string &name, v2f value);
|
||||
void setV3F(const std::string &name, v3f value);
|
||||
void setFlagStr(const std::string &name, u32 flags,
|
||||
const FlagDesc *flagdesc, u32 flagmask);
|
||||
// N.B. if setStruct() is used to write a non-POD aggregate type,
|
||||
// the behavior is undefined.
|
||||
bool setStruct(const std::string &name, const std::string &format, void *value)
|
||||
{
|
||||
std::string structstr;
|
||||
if (!serializeStructToString(&structstr, format, value))
|
||||
return false;
|
||||
bool setStruct(const std::string &name, const std::string &format, void *value);
|
||||
|
||||
set(name, structstr);
|
||||
return true;
|
||||
}
|
||||
// remove a setting
|
||||
bool remove(const std::string &name);
|
||||
void clear();
|
||||
void updateValue(const Settings &other, const std::string &name);
|
||||
void update(const Settings &other);
|
||||
|
||||
void setFlagStr(const std::string &name, u32 flags,
|
||||
const FlagDesc *flagdesc, u32 flagmask)
|
||||
{
|
||||
set(name, writeFlagString(flags, flagdesc, flagmask));
|
||||
}
|
||||
|
||||
void setBool(const std::string &name, bool value)
|
||||
{
|
||||
set(name, value ? "true" : "false");
|
||||
}
|
||||
|
||||
void setFloat(const std::string &name, float value)
|
||||
{
|
||||
set(name, ftos(value));
|
||||
}
|
||||
|
||||
void setV3F(const std::string &name, v3f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setV2F(const std::string &name, v2f value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"("<<value.X<<","<<value.Y<<")";
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void setS16(const std::string &name, s16 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setS32(const std::string &name, s32 value)
|
||||
{
|
||||
set(name, itos(value));
|
||||
}
|
||||
|
||||
void setU64(const std::string &name, u64 value)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<value;
|
||||
set(name, os.str());
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
clearNoLock();
|
||||
}
|
||||
|
||||
void updateValue(const Settings &other, const std::string &name)
|
||||
{
|
||||
if (&other == this)
|
||||
return;
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
|
||||
try {
|
||||
std::string val = other.get(name);
|
||||
m_settings[name] = val;
|
||||
} catch (SettingNotFoundException &e) {
|
||||
}
|
||||
}
|
||||
|
||||
void update(const Settings &other)
|
||||
{
|
||||
if (&other == this)
|
||||
return;
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
updateNoLock(other);
|
||||
}
|
||||
|
||||
Settings & operator+=(const Settings &other)
|
||||
{
|
||||
update(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Settings & operator=(const Settings &other)
|
||||
{
|
||||
if (&other == this)
|
||||
return *this;
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
JMutexAutoLock lock2(other.m_mutex);
|
||||
|
||||
clearNoLock();
|
||||
updateNoLock(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
/***********************
|
||||
* Reading and writing *
|
||||
***********************/
|
||||
|
||||
void updateNoLock(const Settings &other)
|
||||
{
|
||||
m_settings.insert(other.m_settings.begin(), other.m_settings.end());
|
||||
m_defaults.insert(other.m_defaults.begin(), other.m_defaults.end());
|
||||
}
|
||||
bool parseConfigObject(std::istream &is,
|
||||
std::string &name, std::string &value);
|
||||
bool parseConfigObject(std::istream &is,
|
||||
std::string &name, std::string &value,
|
||||
const std::string &end, bool &end_found);
|
||||
/*
|
||||
* Reads a configuration object from stream (usually a single line)
|
||||
* and adds it to dst.
|
||||
* Preserves comments and empty lines.
|
||||
* Setting names that were added to dst are also added to updated.
|
||||
*/
|
||||
void getUpdatedConfigObject(std::istream &is,
|
||||
std::list<std::string> &dst,
|
||||
std::set<std::string> &updated,
|
||||
bool &changed);
|
||||
|
||||
void clearNoLock()
|
||||
{
|
||||
m_settings.clear();
|
||||
m_defaults.clear();
|
||||
}
|
||||
|
||||
void updateNoLock(const Settings &other);
|
||||
void clearNoLock();
|
||||
|
||||
|
||||
std::map<std::string, std::string> m_settings;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue