]> git.lizzy.rs Git - minetest.git/blobdiff - src/settings.h
Fix lost pause support in singleplayer
[minetest.git] / src / settings.h
index f019ce50c8e2c1ca93f0b233c22ef248fc721b2b..13c8e1e65e6a7d42b61933629d624560bca05e97 100644 (file)
@@ -32,11 +32,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "debug.h"
 #include "log.h"
 #include "util/string.h"
-#include "porting.h"
+#include "util/serialize.h"
 #include <list>
 #include <map>
 #include <set>
 #include "filesys.h"
+#include <cctype>
 
 enum ValueType
 {
@@ -572,19 +573,18 @@ class Settings
                return value;
        }
 
-       u32 getFlagStr(std::string name, FlagDesc *flagdesc)
+       u32 getFlagStr(std::string name, FlagDesc *flagdesc, u32 *flagmask)
        {
                std::string val = get(name);
-               return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc);
+               return (std::isdigit(val[0])) ? stoi(val) :
+                       readFlagString(val, flagdesc, flagmask);
        }
 
+       // N.B. if getStruct() is used to read a non-POD aggregate type,
+       // the behavior is undefined.
        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, valstr;
-               char *f, *snext;
-               size_t pos;
+               std::string valstr;
 
                try {
                        valstr = get(name);
@@ -592,160 +592,14 @@ class Settings
                        return false;
                }
 
-               char *s = &valstr[0];
-               char *buf = new char[len];
-               char *bufpos = buf;
-
-               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;
+               if (!deSerializeStringToStruct(valstr, format, out, olen))
                        return false;
-               }
 
-               memcpy(out, buf, olen);
-               delete[] buf;
                return true;
        }
 
        //////////// Try to get value, no exception thrown
-       bool tryGet(std::string name, std::string &val)
+       bool getNoEx(std::string name, std::string &val)
        {
                try {
                        val = get(name);
@@ -755,17 +609,26 @@ class Settings
                }
        }
 
-       bool tryGetFlagStr(std::string name, u32 &val, FlagDesc *flagdesc)
+       // 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(std::string name, u32 &val, FlagDesc *flagdesc)
        {
                try {
-                       val = getFlagStr(name, flagdesc);
+                       u32 flags, flagmask;
+
+                       flags = getFlagStr(name, flagdesc, &flagmask);
+
+                       val &= ~flagmask;
+                       val |=  flags;
+
                        return true;
                } catch (SettingNotFoundException &e) {
                        return false;
                }
        }
 
-       bool tryGetFloat(std::string name, float &val)
+       bool getFloatNoEx(std::string name, float &val)
        {
                try {
                        val = getFloat(name);
@@ -775,7 +638,7 @@ class Settings
                }
        }
 
-       bool tryGetU16(std::string name, int &val)
+       bool getU16NoEx(std::string name, int &val)
        {
                try {
                        val = getU16(name);
@@ -785,7 +648,7 @@ class Settings
                }
        }
 
-       bool tryGetU16(std::string name, u16 &val)
+       bool getU16NoEx(std::string name, u16 &val)
        {
                try {
                        val = getU16(name);
@@ -795,7 +658,7 @@ class Settings
                }
        }
 
-       bool tryGetS16(std::string name, int &val)
+       bool getS16NoEx(std::string name, int &val)
        {
                try {
                        val = getU16(name);
@@ -805,7 +668,7 @@ class Settings
                }
        }
 
-       bool tryGetS16(std::string name, s16 &val)
+       bool getS16NoEx(std::string name, s16 &val)
        {
                try {
                        val = getS16(name);
@@ -815,7 +678,7 @@ class Settings
                }
        }
 
-       bool tryGetS32(std::string name, s32 &val)
+       bool getS32NoEx(std::string name, s32 &val)
        {
                try {
                        val = getS32(name);
@@ -825,7 +688,7 @@ class Settings
                }
        }
 
-       bool tryGetV3F(std::string name, v3f &val)
+       bool getV3FNoEx(std::string name, v3f &val)
        {
                try {
                        val = getV3F(name);
@@ -835,7 +698,7 @@ class Settings
                }
        }
 
-       bool tryGetV2F(std::string name, v2f &val)
+       bool getV2FNoEx(std::string name, v2f &val)
        {
                try {
                        val = getV2F(name);
@@ -845,7 +708,7 @@ class Settings
                }
        }
 
-       bool tryGetU64(std::string name, u64 &val)
+       bool getU64NoEx(std::string name, u64 &val)
        {
                try {
                        val = getU64(name);
@@ -856,113 +719,23 @@ class Settings
        }
 
        //////////// Set setting
+
+       // N.B. if setStruct() is used to write a non-POD aggregate type,
+       // the behavior is undefined.
        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;
+               std::string structstr;
+               if (!serializeStructToString(&structstr, format, value))
+                       return false;
 
-               set(name, std::string(sbuf));
+               set(name, structstr);
                return true;
        }
-       
-       void setFlagStr(std::string name, u32 flags, FlagDesc *flagdesc)
+
+       void setFlagStr(std::string name, u32 flags,
+               FlagDesc *flagdesc, u32 flagmask)
        {
-               set(name, writeFlagString(flags, flagdesc));
+               set(name, writeFlagString(flags, flagdesc, flagmask));
        }
 
        void setBool(std::string name, bool value)