]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/settings.h
Fix crack overlay for animated textures
[dragonfireclient.git] / src / settings.h
index 07966f2dac193f8e5c5210bff1b2c8d11af12f50..e7b49b6d7798497cc3d25f8bda08a596abe4acf9 100644 (file)
@@ -1,18 +1,18 @@
 /*
 /*
-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
 
 This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
 
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU Lesser General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef SETTINGS_HEADER
 #define SETTINGS_HEADER
 
 #ifndef SETTINGS_HEADER
 #define SETTINGS_HEADER
 
-#include "common_irrlicht.h"
+#include "irrlichttypes_bloated.h"
 #include <string>
 #include <jthread.h>
 #include <jmutex.h>
 #include <string>
 #include <jthread.h>
 #include <jmutex.h>
@@ -30,8 +30,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <fstream>
 #include <sstream>
 #include "debug.h"
 #include <fstream>
 #include <sstream>
 #include "debug.h"
-#include "utility.h"
 #include "log.h"
 #include "log.h"
+#include "util/string.h"
+#include "porting.h"
+#include <list>
+#include <map>
+#include <set>
 
 enum ValueType
 {
 
 enum ValueType
 {
@@ -61,23 +65,42 @@ 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";
                }
        }
+  
+       // return all keys used 
+       std::vector<std::string> getNames(){
+               std::vector<std::string> names;
+               for(std::map<std::string, std::string>::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);
+       }
+
 
        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;
@@ -91,15 +114,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;
        }
 
@@ -124,7 +147,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.
@@ -149,16 +172,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.
@@ -167,15 +190,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);
@@ -185,7 +208,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] == '#')
                {
@@ -203,14 +226,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<<"\" = \""
@@ -221,9 +244,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;
        }
 
@@ -236,11 +261,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);
@@ -257,30 +282,30 @@ 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
                {
                        std::ofstream os(filename);
                // Write stuff back
                {
                        std::ofstream os(filename);
@@ -291,13 +316,13 @@ class Settings
                                                <<filename<<"\""<<std::endl;
                                return false;
                        }
                                                <<filename<<"\""<<std::endl;
                                return false;
                        }
-                       
+
                        /*
                                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);
                        }
                        {
                                os<<(*i);
                        }
@@ -305,20 +330,20 @@ class Settings
                        /*
                                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;
                                os<<name<<" = "<<value<<"\n";
                        }
                }
                                infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
                                                <<std::endl;
                                os<<name<<" = "<<value<<"\n";
                        }
                }
-               
+
                return true;
        }
 
                return true;
        }
 
@@ -328,7 +353,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;
@@ -356,19 +381,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";
@@ -384,7 +409,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<<"\""
@@ -398,7 +423,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;
        }
 
@@ -413,40 +438,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
@@ -465,7 +490,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]: ";
@@ -493,7 +518,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<<"]: ";
@@ -546,6 +571,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)
@@ -554,11 +854,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));
@@ -578,6 +873,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;
@@ -588,7 +893,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();
        }
@@ -596,7 +901,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;
 
@@ -613,23 +918,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;
        }
@@ -638,25 +932,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;
 
@@ -666,19 +946,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;
 };