]> git.lizzy.rs Git - minetest.git/blobdiff - src/settings.h
Fix invalid usage of texture->getSize() where actually texture->getOriginalSize(...
[minetest.git] / src / settings.h
index 1a29ef00a398fd4460e90d8c2b2b6d5da06978d1..4ee5b591322a9070f6bf7b685f034cd823b1e54c 100644 (file)
@@ -1,6 +1,6 @@
 /*
 /*
-Minetest-c55
-Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -21,10 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define SETTINGS_HEADER
 
 #include "irrlichttypes_bloated.h"
 #define SETTINGS_HEADER
 
 #include "irrlichttypes_bloated.h"
+#include "exceptions.h"
 #include <string>
 #include <string>
-#include <jthread.h>
-#include <jmutex.h>
-#include <jmutexautolock.h>
+#include "jthread/jmutex.h"
+#include "jthread/jmutexautolock.h"
 #include "strfnd.h"
 #include <iostream>
 #include <fstream>
 #include "strfnd.h"
 #include <iostream>
 #include <fstream>
@@ -32,6 +32,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "debug.h"
 #include "log.h"
 #include "util/string.h"
 #include "debug.h"
 #include "log.h"
 #include "util/string.h"
+#include "porting.h"
+#include <list>
+#include <map>
+#include <set>
+#include "filesys.h"
 
 enum ValueType
 {
 
 enum ValueType
 {
@@ -61,13 +66,13 @@ class Settings
        void writeLines(std::ostream &os)
        {
                JMutexAutoLock lock(m_mutex);
        void writeLines(std::ostream &os)
        {
                JMutexAutoLock lock(m_mutex);
-               
-               for(core::map<std::string, std::string>::Iterator
-                               i = m_settings.getIterator();
-                               i.atEnd() == false; i++)
+
+               for(std::map<std::string, std::string>::iterator
+                               i = m_settings.begin();
+                               i != m_settings.end(); ++i)
                {
                {
-                       std::string name = i.getNode()->getKey();
-                       std::string value = i.getNode()->getValue();
+                       std::string name = i->first;
+                       std::string value = i->second;
                        os<<name<<" = "<<value<<"\n";
                }
        }
                        os<<name<<" = "<<value<<"\n";
                }
        }
@@ -75,12 +80,11 @@ class Settings
        // return all keys used 
        std::vector<std::string> getNames(){
                std::vector<std::string> names;
        // return all keys used 
        std::vector<std::string> getNames(){
                std::vector<std::string> names;
-               for(core::map<std::string, std::string>::Iterator
-                               i = m_settings.getIterator();
-                               i.atEnd() == false; i++)
+               for(std::map<std::string, std::string>::iterator
+                               i = m_settings.begin();
+                               i != m_settings.end(); ++i)
                {
                {
-                       std::string name = i.getNode()->getKey();
-                       names.push_back(name);
+                       names.push_back(i->first);
                }
                return names;  
        }
                }
                return names;  
        }
@@ -88,16 +92,16 @@ class Settings
        // remove a setting
        bool remove(const std::string& name)
        {
        // remove a setting
        bool remove(const std::string& name)
        {
-               return m_settings.remove(name);
+               return m_settings.erase(name);
        }
 
 
        bool parseConfigLine(const std::string &line)
        {
                JMutexAutoLock lock(m_mutex);
        }
 
 
        bool parseConfigLine(const std::string &line)
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                std::string trimmedline = trim(line);
                std::string trimmedline = trim(line);
-               
+
                // Ignore empty lines and comments
                if(trimmedline.size() == 0 || trimmedline[0] == '#')
                        return true;
                // Ignore empty lines and comments
                if(trimmedline.size() == 0 || trimmedline[0] == '#')
                        return true;
@@ -111,15 +115,15 @@ class Settings
 
                if(name == "")
                        return true;
 
                if(name == "")
                        return true;
-               
+
                std::string value = sf.next("\n");
                value = trim(value);
 
                /*infostream<<"Config name=\""<<name<<"\" value=\""
                                <<value<<"\""<<std::endl;*/
                std::string value = sf.next("\n");
                value = trim(value);
 
                /*infostream<<"Config name=\""<<name<<"\" value=\""
                                <<value<<"\""<<std::endl;*/
-               
+
                m_settings[name] = value;
                m_settings[name] = value;
-               
+
                return true;
        }
 
                return true;
        }
 
@@ -144,7 +148,7 @@ class Settings
        {
                if(is.eof())
                        return false;
        {
                if(is.eof())
                        return false;
-               
+
                /*
                        NOTE: This function might be expanded to allow multi-line
                              settings.
                /*
                        NOTE: This function might be expanded to allow multi-line
                              settings.
@@ -169,16 +173,16 @@ class Settings
 
                /*infostream<<"Parsing configuration file: \""
                                <<filename<<"\""<<std::endl;*/
 
                /*infostream<<"Parsing configuration file: \""
                                <<filename<<"\""<<std::endl;*/
-                               
+
                while(parseConfigObject(is));
                while(parseConfigObject(is));
-               
+
                return true;
        }
 
        /*
                Reads a configuration object from stream (usually a single line)
                and adds it to dst.
                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.
                Preserves comments and empty lines.
 
                Settings that were added to dst are also added to updated.
@@ -187,15 +191,15 @@ class Settings
                Returns false on EOF
        */
        bool getUpdatedConfigObject(std::istream &is,
                Returns false on EOF
        */
        bool getUpdatedConfigObject(std::istream &is,
-                       core::list<std::string> &dst,
-                       core::map<std::string, bool> &updated,
+                       std::list<std::string> &dst,
+                       std::set<std::string> &updated,
                        bool &value_changed)
        {
                JMutexAutoLock lock(m_mutex);
                        bool &value_changed)
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                if(is.eof())
                        return false;
                if(is.eof())
                        return false;
-               
+
                // NOTE: This function will be expanded to allow multi-line settings
                std::string line;
                std::getline(is, line);
                // NOTE: This function will be expanded to allow multi-line settings
                std::string line;
                std::getline(is, line);
@@ -205,7 +209,7 @@ class Settings
                std::string line_end = "";
                if(is.eof() == false)
                        line_end = "\n";
                std::string line_end = "";
                if(is.eof() == false)
                        line_end = "\n";
-               
+
                // Ignore empty lines and comments
                if(trimmedline.size() == 0 || trimmedline[0] == '#')
                {
                // Ignore empty lines and comments
                if(trimmedline.size() == 0 || trimmedline[0] == '#')
                {
@@ -223,14 +227,14 @@ class Settings
                        dst.push_back(line+line_end);
                        return true;
                }
                        dst.push_back(line+line_end);
                        return true;
                }
-               
+
                std::string value = sf.next("\n");
                value = trim(value);
                std::string value = sf.next("\n");
                value = trim(value);
-               
-               if(m_settings.find(name))
+
+               if(m_settings.find(name) != m_settings.end())
                {
                        std::string newvalue = m_settings[name];
                {
                        std::string newvalue = m_settings[name];
-                       
+
                        if(newvalue != value)
                        {
                                infostream<<"Changing value of \""<<name<<"\" = \""
                        if(newvalue != value)
                        {
                                infostream<<"Changing value of \""<<name<<"\" = \""
@@ -241,9 +245,11 @@ class Settings
 
                        dst.push_back(name + " = " + newvalue + line_end);
 
 
                        dst.push_back(name + " = " + newvalue + line_end);
 
-                       updated[name] = true;
+                       updated.insert(name);
                }
                }
-               
+               else //file contains a setting which is not in m_settings
+                       value_changed=true;
+                       
                return true;
        }
 
                return true;
        }
 
@@ -256,11 +262,11 @@ class Settings
        {
                infostream<<"Updating configuration file: \""
                                <<filename<<"\""<<std::endl;
        {
                infostream<<"Updating configuration file: \""
                                <<filename<<"\""<<std::endl;
-               
-               core::list<std::string> objects;
-               core::map<std::string, bool> updated;
+
+               std::list<std::string> objects;
+               std::set<std::string> updated;
                bool something_actually_changed = false;
                bool something_actually_changed = false;
-               
+
                // Read and modify stuff
                {
                        std::ifstream is(filename);
                // Read and modify stuff
                {
                        std::ifstream is(filename);
@@ -277,68 +283,68 @@ class Settings
                                                something_actually_changed));
                        }
                }
                                                something_actually_changed));
                        }
                }
-               
+
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock(m_mutex);
-               
+
                // If something not yet determined to have been changed, check if
                // any new stuff was added
                if(!something_actually_changed){
                // If something not yet determined to have been changed, check if
                // any new stuff was added
                if(!something_actually_changed){
-                       for(core::map<std::string, std::string>::Iterator
-                                       i = m_settings.getIterator();
-                                       i.atEnd() == false; i++)
+                       for(std::map<std::string, std::string>::iterator
+                                       i = m_settings.begin();
+                                       i != m_settings.end(); ++i)
                        {
                        {
-                               if(updated.find(i.getNode()->getKey()))
+                               if(updated.find(i->first) != updated.end())
                                        continue;
                                something_actually_changed = true;
                                break;
                        }
                }
                                        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;
                }
                // 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
                {
                // Write stuff back
                {
-                       std::ofstream os(filename);
-                       if(os.good() == false)
-                       {
-                               errorstream<<"Error opening configuration file"
-                                               " for writing: \""
-                                               <<filename<<"\""<<std::endl;
-                               return false;
-                       }
-                       
+                       std::ostringstream ss(std::ios_base::binary);
+
                        /*
                                Write updated stuff
                        */
                        /*
                                Write updated stuff
                        */
-                       for(core::list<std::string>::Iterator
+                       for(std::list<std::string>::iterator
                                        i = objects.begin();
                                        i = objects.begin();
-                                       i != objects.end(); i++)
+                                       i != objects.end(); ++i)
                        {
                        {
-                               os<<(*i);
+                               ss<<(*i);
                        }
 
                        /*
                                Write stuff that was not already in the file
                        */
                        }
 
                        /*
                                Write stuff that was not already in the file
                        */
-                       for(core::map<std::string, std::string>::Iterator
-                                       i = m_settings.getIterator();
-                                       i.atEnd() == false; i++)
+                       for(std::map<std::string, std::string>::iterator
+                                       i = m_settings.begin();
+                                       i != m_settings.end(); ++i)
                        {
                        {
-                               if(updated.find(i.getNode()->getKey()))
+                               if(updated.find(i->first) != updated.end())
                                        continue;
                                        continue;
-                               std::string name = i.getNode()->getKey();
-                               std::string value = i.getNode()->getValue();
+                               std::string name = i->first;
+                               std::string value = i->second;
                                infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
                                                <<std::endl;
                                infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
                                                <<std::endl;
-                               os<<name<<" = "<<value<<"\n";
+                               ss<<name<<" = "<<value<<"\n";
+                       }
+
+                       if(!fs::safeWriteToFile(filename, ss.str()))
+                       {
+                               errorstream<<"Error writing configuration file: \""
+                                               <<filename<<"\""<<std::endl;
+                               return false;
                        }
                }
                        }
                }
-               
+
                return true;
        }
 
                return true;
        }
 
@@ -348,7 +354,7 @@ class Settings
                returns true on success
        */
        bool parseCommandLine(int argc, char *argv[],
                returns true on success
        */
        bool parseCommandLine(int argc, char *argv[],
-                       core::map<std::string, ValueSpec> &allowed_options)
+                       std::map<std::string, ValueSpec> &allowed_options)
        {
                int nonopt_index = 0;
                int i=1;
        {
                int nonopt_index = 0;
                int i=1;
@@ -376,19 +382,19 @@ class Settings
 
                        std::string name = argname.substr(2);
 
 
                        std::string name = argname.substr(2);
 
-                       core::map<std::string, ValueSpec>::Node *n;
+                       std::map<std::string, ValueSpec>::iterator n;
                        n = allowed_options.find(name);
                        n = allowed_options.find(name);
-                       if(n == NULL)
+                       if(n == allowed_options.end())
                        {
                                errorstream<<"Unknown command-line parameter \""
                                                <<argname<<"\""<<std::endl;
                                return false;
                        }
 
                        {
                                errorstream<<"Unknown command-line parameter \""
                                                <<argname<<"\""<<std::endl;
                                return false;
                        }
 
-                       ValueType type = n->getValue().type;
+                       ValueType type = n->second.type;
 
                        std::string value = "";
 
                        std::string value = "";
-                       
+
                        if(type == VALUETYPE_FLAG)
                        {
                                value = "true";
                        if(type == VALUETYPE_FLAG)
                        {
                                value = "true";
@@ -404,7 +410,7 @@ class Settings
                                value = argv[i];
                                i++;
                        }
                                value = argv[i];
                                i++;
                        }
-                       
+
 
                        infostream<<"Valid command-line parameter: \""
                                        <<name<<"\" = \""<<value<<"\""
 
                        infostream<<"Valid command-line parameter: \""
                                        <<name<<"\" = \""<<value<<"\""
@@ -418,7 +424,7 @@ class Settings
        void set(std::string name, std::string value)
        {
                JMutexAutoLock lock(m_mutex);
        void set(std::string name, std::string value)
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                m_settings[name] = value;
        }
 
                m_settings[name] = value;
        }
 
@@ -433,40 +439,40 @@ class Settings
        void setDefault(std::string name, std::string value)
        {
                JMutexAutoLock lock(m_mutex);
        void setDefault(std::string name, std::string value)
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                m_defaults[name] = value;
        }
 
        bool exists(std::string name)
        {
                JMutexAutoLock lock(m_mutex);
                m_defaults[name] = value;
        }
 
        bool exists(std::string name)
        {
                JMutexAutoLock lock(m_mutex);
-               
-               return (m_settings.find(name) || m_defaults.find(name));
+
+               return (m_settings.find(name) != m_settings.end() || m_defaults.find(name) != m_defaults.end());
        }
 
        std::string get(std::string name)
        {
                JMutexAutoLock lock(m_mutex);
        }
 
        std::string get(std::string name)
        {
                JMutexAutoLock lock(m_mutex);
-               
-               core::map<std::string, std::string>::Node *n;
+
+               std::map<std::string, std::string>::iterator n;
                n = m_settings.find(name);
                n = m_settings.find(name);
-               if(n == NULL)
+               if(n == m_settings.end())
                {
                        n = m_defaults.find(name);
                {
                        n = m_defaults.find(name);
-                       if(n == NULL)
+                       if(n == m_defaults.end())
                        {
                        {
-                               throw SettingNotFoundException("Setting not found");
+                               throw SettingNotFoundException(("Setting [" + name + "] not found ").c_str());
                        }
                }
 
                        }
                }
 
-               return n->getValue();
+               return n->second;
        }
 
        bool getBool(std::string name)
        {
                return is_yes(get(name));
        }
        }
 
        bool getBool(std::string name)
        {
                return is_yes(get(name));
        }
-       
+
        bool getFlag(std::string name)
        {
                try
        bool getFlag(std::string name)
        {
                try
@@ -485,7 +491,7 @@ class Settings
                // If it is in settings
                if(exists(name))
                        return getBool(name);
                // If it is in settings
                if(exists(name))
                        return getBool(name);
-               
+
                std::string s;
                char templine[10];
                std::cout<<question<<" [y/N]: ";
                std::string s;
                char templine[10];
                std::cout<<question<<" [y/N]: ";
@@ -513,7 +519,7 @@ class Settings
                // If it is in settings
                if(exists(name))
                        return getU16(name);
                // If it is in settings
                if(exists(name))
                        return getU16(name);
-               
+
                std::string s;
                char templine[10];
                std::cout<<question<<" ["<<def<<"]: ";
                std::string s;
                char templine[10];
                std::cout<<question<<" ["<<def<<"]: ";
@@ -566,6 +572,281 @@ class Settings
                return value;
        }
 
                return value;
        }
 
+       u32 getFlagStr(std::string name, FlagDesc *flagdesc)
+       {
+               std::string val = get(name);
+               return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc);
+       }
+
+       bool getStruct(std::string name, std::string format, void *out, size_t olen)
+       {
+               size_t len = olen;
+               std::vector<std::string *> strs_alloced;
+               std::string *str;
+               std::string valstr = get(name);
+               char *s = &valstr[0];
+               char *buf = new char[len];
+               char *bufpos = buf;
+               char *f, *snext;
+               size_t pos;
+
+               char *fmtpos, *fmt = &format[0];
+               while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
+                       fmt = NULL;
+
+                       bool is_unsigned = false;
+                       int width = 0;
+                       char valtype = *f;
+
+                       width = (int)strtol(f + 1, &f, 10);
+                       if (width && valtype == 's')
+                               valtype = 'i';
+
+                       switch (valtype) {
+                               case 'u':
+                                       is_unsigned = true;
+                                       /* FALLTHROUGH */
+                               case 'i':
+                                       if (width == 16) {
+                                               bufpos += PADDING(bufpos, u16);
+                                               if ((bufpos - buf) + sizeof(u16) <= len) {
+                                                       if (is_unsigned)
+                                                               *(u16 *)bufpos = (u16)strtoul(s, &s, 10);
+                                                       else
+                                                               *(s16 *)bufpos = (s16)strtol(s, &s, 10);
+                                               }
+                                               bufpos += sizeof(u16);
+                                       } else if (width == 32) {
+                                               bufpos += PADDING(bufpos, u32);
+                                               if ((bufpos - buf) + sizeof(u32) <= len) {
+                                                       if (is_unsigned)
+                                                               *(u32 *)bufpos = (u32)strtoul(s, &s, 10);
+                                                       else
+                                                               *(s32 *)bufpos = (s32)strtol(s, &s, 10);
+                                               }
+                                               bufpos += sizeof(u32);
+                                       } else if (width == 64) {
+                                               bufpos += PADDING(bufpos, u64);
+                                               if ((bufpos - buf) + sizeof(u64) <= len) {
+                                                       if (is_unsigned)
+                                                               *(u64 *)bufpos = (u64)strtoull(s, &s, 10);
+                                                       else
+                                                               *(s64 *)bufpos = (s64)strtoll(s, &s, 10);
+                                               }
+                                               bufpos += sizeof(u64);
+                                       }
+                                       s = strchr(s, ',');
+                                       break;
+                               case 'b':
+                                       snext = strchr(s, ',');
+                                       if (snext)
+                                               *snext++ = 0;
+
+                                       bufpos += PADDING(bufpos, bool);
+                                       if ((bufpos - buf) + sizeof(bool) <= len)
+                                               *(bool *)bufpos = is_yes(std::string(s));
+                                       bufpos += sizeof(bool);
+
+                                       s = snext;
+                                       break;
+                               case 'f':
+                                       bufpos += PADDING(bufpos, float);
+                                       if ((bufpos - buf) + sizeof(float) <= len)
+                                               *(float *)bufpos = strtof(s, &s);
+                                       bufpos += sizeof(float);
+
+                                       s = strchr(s, ',');
+                                       break;
+                               case 's':
+                                       while (*s == ' ' || *s == '\t')
+                                               s++;
+                                       if (*s++ != '"') //error, expected string
+                                               goto fail;
+                                       snext = s;
+
+                                       while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"'))
+                                               snext++;
+                                       *snext++ = 0;
+
+                                       bufpos += PADDING(bufpos, std::string *);
+
+                                       str = new std::string(s);
+                                       pos = 0;
+                                       while ((pos = str->find("\\\"", pos)) != std::string::npos)
+                                               str->erase(pos, 1);
+
+                                       if ((bufpos - buf) + sizeof(std::string *) <= len)
+                                               *(std::string **)bufpos = str;
+                                       bufpos += sizeof(std::string *);
+                                       strs_alloced.push_back(str);
+
+                                       s = *snext ? snext + 1 : NULL;
+                                       break;
+                               case 'v':
+                                       while (*s == ' ' || *s == '\t')
+                                               s++;
+                                       if (*s++ != '(') //error, expected vector
+                                               goto fail;
+
+                                       if (width == 2) {
+                                               bufpos += PADDING(bufpos, v2f);
+
+                                               if ((bufpos - buf) + sizeof(v2f) <= len) {
+                                               v2f *v = (v2f *)bufpos;
+                                                       v->X = strtof(s, &s);
+                                                       s++;
+                                                       v->Y = strtof(s, &s);
+                                               }
+
+                                               bufpos += sizeof(v2f);
+                                       } else if (width == 3) {
+                                               bufpos += PADDING(bufpos, v3f);
+                                               if ((bufpos - buf) + sizeof(v3f) <= len) {
+                                                       v3f *v = (v3f *)bufpos;
+                                                       v->X = strtof(s, &s);
+                                                       s++;
+                                                       v->Y = strtof(s, &s);
+                                                       s++;
+                                                       v->Z = strtof(s, &s);
+                                               }
+
+                                               bufpos += sizeof(v3f);
+                                       }
+                                       s = strchr(s, ',');
+                                       break;
+                               default: //error, invalid format specifier
+                                       goto fail;
+                       }
+
+                       if (s && *s == ',')
+                               s++;
+
+                       if ((size_t)(bufpos - buf) > len) //error, buffer too small
+                               goto fail;
+               }
+
+               if (f && *f) { //error, mismatched number of fields and values
+fail:
+                       for (size_t i = 0; i != strs_alloced.size(); i++)
+                               delete strs_alloced[i];
+                       delete[] buf;
+                       return false;
+               }
+
+               memcpy(out, buf, olen);
+               delete[] buf;
+               return true;
+       }
+
+       bool setStruct(std::string name, std::string format, void *value)
+       {
+               char sbuf[2048];
+               int sbuflen = sizeof(sbuf) - 1;
+               sbuf[sbuflen] = 0;
+               std::string str;
+               int pos = 0;
+               size_t fpos;
+               char *f;
+
+               char *bufpos = (char *)value;
+               char *fmtpos, *fmt = &format[0];
+               while ((f = strtok_r(fmt, ",", &fmtpos))) {
+                       fmt = NULL;
+                       bool is_unsigned = false;
+                       int width = 0, nprinted = 0;
+                       char valtype = *f;
+
+                       width = (int)strtol(f + 1, &f, 10);
+                       if (width && valtype == 's')
+                               valtype = 'i';
+
+                       switch (valtype) {
+                               case 'u':
+                                       is_unsigned = true;
+                                       /* FALLTHROUGH */
+                               case 'i':
+                                       if (width == 16) {
+                                               bufpos += PADDING(bufpos, u16);
+                                               nprinted = snprintf(sbuf + pos, sbuflen,
+                                                                       is_unsigned ? "%u, " : "%d, ",
+                                                                       *((u16 *)bufpos));
+                                               bufpos += sizeof(u16);
+                                       } else if (width == 32) {
+                                               bufpos += PADDING(bufpos, u32);
+                                               nprinted = snprintf(sbuf + pos, sbuflen,
+                                                                       is_unsigned ? "%u, " : "%d, ",
+                                                                       *((u32 *)bufpos));
+                                               bufpos += sizeof(u32);
+                                       } else if (width == 64) {
+                                               bufpos += PADDING(bufpos, u64);
+                                               nprinted = snprintf(sbuf + pos, sbuflen,
+                                                                       is_unsigned ? "%llu, " : "%lli, ",
+                                                                       (unsigned long long)*((u64 *)bufpos));
+                                               bufpos += sizeof(u64);
+                                       }
+                                       break;
+                               case 'b':
+                                       bufpos += PADDING(bufpos, bool);
+                                       nprinted = snprintf(sbuf + pos, sbuflen, "%s, ",
+                                                                               *((bool *)bufpos) ? "true" : "false");
+                                       bufpos += sizeof(bool);
+                                       break;
+                               case 'f':
+                                       bufpos += PADDING(bufpos, float);
+                                       nprinted = snprintf(sbuf + pos, sbuflen, "%f, ",
+                                                                               *((float *)bufpos));
+                                       bufpos += sizeof(float);
+                                       break;
+                               case 's':
+                                       bufpos += PADDING(bufpos, std::string *);
+                                       str = **((std::string **)bufpos);
+
+                                       fpos = 0;
+                                       while ((fpos = str.find('"', fpos)) != std::string::npos) {
+                                               str.insert(fpos, 1, '\\');
+                                               fpos += 2;
+                                       }
+
+                                       nprinted = snprintf(sbuf + pos, sbuflen, "\"%s\", ",
+                                                                               (*((std::string **)bufpos))->c_str());
+                                       bufpos += sizeof(std::string *);
+                                       break;
+                               case 'v':
+                                       if (width == 2) {
+                                               bufpos += PADDING(bufpos, v2f);
+                                               v2f *v = (v2f *)bufpos;
+                                               nprinted = snprintf(sbuf + pos, sbuflen,
+                                                                                       "(%f, %f), ", v->X, v->Y);
+                                               bufpos += sizeof(v2f);
+                                       } else {
+                                               bufpos += PADDING(bufpos, v3f);
+                                               v3f *v = (v3f *)bufpos;
+                                               nprinted = snprintf(sbuf + pos, sbuflen,
+                                                                                       "(%f, %f, %f), ", v->X, v->Y, v->Z);
+                                               bufpos += sizeof(v3f);
+                                       }
+                                       break;
+                               default:
+                                       return false;
+                       }
+                       if (nprinted < 0) //error, buffer too small
+                               return false;
+                       pos     += nprinted;
+                       sbuflen -= nprinted;
+               }
+
+               if (pos >= 2)
+                       sbuf[pos - 2] = 0;
+
+               set(name, std::string(sbuf));
+               return true;
+       }
+       
+       void setFlagStr(std::string name, u32 flags, FlagDesc *flagdesc)
+       {
+               set(name, writeFlagString(flags, flagdesc));
+       }
+
        void setBool(std::string name, bool value)
        {
                if(value)
        void setBool(std::string name, bool value)
        {
                if(value)
@@ -574,11 +855,6 @@ class Settings
                        set(name, "false");
        }
 
                        set(name, "false");
        }
 
-       void setS32(std::string name, s32 value)
-       {
-               set(name, itos(value));
-       }
-
        void setFloat(std::string name, float value)
        {
                set(name, ftos(value));
        void setFloat(std::string name, float value)
        {
                set(name, ftos(value));
@@ -598,6 +874,16 @@ class Settings
                set(name, os.str());
        }
 
                set(name, os.str());
        }
 
+       void setS16(std::string name, s16 value)
+       {
+               set(name, itos(value));
+       }
+
+       void setS32(std::string name, s32 value)
+       {
+               set(name, itos(value));
+       }
+
        void setU64(std::string name, u64 value)
        {
                std::ostringstream os;
        void setU64(std::string name, u64 value)
        {
                std::ostringstream os;
@@ -608,7 +894,7 @@ class Settings
        void clear()
        {
                JMutexAutoLock lock(m_mutex);
        void clear()
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                m_settings.clear();
                m_defaults.clear();
        }
                m_settings.clear();
                m_defaults.clear();
        }
@@ -616,7 +902,7 @@ class Settings
        void updateValue(Settings &other, const std::string &name)
        {
                JMutexAutoLock lock(m_mutex);
        void updateValue(Settings &other, const std::string &name)
        {
                JMutexAutoLock lock(m_mutex);
-               
+
                if(&other == this)
                        return;
 
                if(&other == this)
                        return;
 
@@ -633,23 +919,12 @@ class Settings
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
-               
+
                if(&other == this)
                        return;
 
                if(&other == this)
                        return;
 
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_settings.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_settings[i.getNode()->getKey()] = i.getNode()->getValue();
-               }
-               
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_defaults.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_defaults[i.getNode()->getKey()] = i.getNode()->getValue();
-               }
+               m_settings.insert(other.m_settings.begin(), other.m_settings.end());
+               m_defaults.insert(other.m_defaults.begin(), other.m_defaults.end());
 
                return;
        }
 
                return;
        }
@@ -658,25 +933,11 @@ class Settings
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
-               
+
                if(&other == this)
                        return *this;
 
                if(&other == this)
                        return *this;
 
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_settings.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_settings.insert(i.getNode()->getKey(),
-                                       i.getNode()->getValue());
-               }
-               
-               for(core::map<std::string, std::string>::Iterator
-                               i = other.m_defaults.getIterator();
-                               i.atEnd() == false; i++)
-               {
-                       m_defaults.insert(i.getNode()->getKey(),
-                                       i.getNode()->getValue());
-               }
+               update(other);
 
                return *this;
 
 
                return *this;
 
@@ -686,19 +947,19 @@ class Settings
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
        {
                JMutexAutoLock lock(m_mutex);
                JMutexAutoLock lock2(other.m_mutex);
-               
+
                if(&other == this)
                        return *this;
 
                clear();
                (*this) += other;
                if(&other == this)
                        return *this;
 
                clear();
                (*this) += other;
-               
+
                return *this;
        }
 
 private:
                return *this;
        }
 
 private:
-       core::map<std::string, std::string> m_settings;
-       core::map<std::string, std::string> m_defaults;
+       std::map<std::string, std::string> m_settings;
+       std::map<std::string, std::string> m_defaults;
        // All methods that access m_settings/m_defaults directly should lock this.
        JMutex m_mutex;
 };
        // All methods that access m_settings/m_defaults directly should lock this.
        JMutex m_mutex;
 };