28 changes: 22 additions & 6 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,12 +572,15 @@ 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 (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;
Expand Down Expand Up @@ -755,10 +758,19 @@ class Settings
}
}

// 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;
Expand Down Expand Up @@ -856,6 +868,9 @@ 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];
Expand Down Expand Up @@ -959,10 +974,11 @@ class Settings
set(name, std::string(sbuf));
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)
Expand Down
46 changes: 32 additions & 14 deletions src/util/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,46 +108,63 @@ std::string urldecode(std::string str)
return oss.str();
}

u32 readFlagString(std::string str, FlagDesc *flagdesc) {
u32 result = 0;
u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask)
{
u32 result = 0, mask = 0;
char *s = &str[0];
char *flagstr, *strpos = NULL;

while ((flagstr = strtok_r(s, ",", &strpos))) {
s = NULL;

while (*flagstr == ' ' || *flagstr == '\t')
flagstr++;


bool flagset = true;
if (!strncasecmp(flagstr, "no", 2)) {
flagset = false;
flagstr += 2;
}

for (int i = 0; flagdesc[i].name; i++) {
if (!strcasecmp(flagstr, flagdesc[i].name)) {
result |= flagdesc[i].flag;
mask |= flagdesc[i].flag;
if (flagset)
result |= flagdesc[i].flag;
break;
}
}
}


if (flagmask)
*flagmask = mask;

return result;
}

std::string writeFlagString(u32 flags, FlagDesc *flagdesc) {
std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask)
{
std::string result;

for (int i = 0; flagdesc[i].name; i++) {
if (flags & flagdesc[i].flag) {
if (flagmask & flagdesc[i].flag) {
if (!(flags & flagdesc[i].flag))
result += "no";

result += flagdesc[i].name;
result += ", ";
}
}

size_t len = result.length();
if (len >= 2)
result.erase(len - 2, 2);

return result;
}

char *mystrtok_r(char *s, const char *sep, char **lasts) {
char *mystrtok_r(char *s, const char *sep, char **lasts)
{
char *t;

if (!s)
Expand All @@ -172,7 +189,8 @@ char *mystrtok_r(char *s, const char *sep, char **lasts) {
return s;
}

u64 read_seed(const char *str) {
u64 read_seed(const char *str)
{
char *endptr;
u64 num;

Expand Down
4 changes: 2 additions & 2 deletions src/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ inline std::string unescape_string(std::string &s)
std::string translatePassword(std::string playername, std::wstring password);
std::string urlencode(std::string str);
std::string urldecode(std::string str);
u32 readFlagString(std::string str, FlagDesc *flagdesc);
std::string writeFlagString(u32 flags, FlagDesc *flagdesc);
u32 readFlagString(std::string str, FlagDesc *flagdesc, u32 *flagmask);
std::string writeFlagString(u32 flags, FlagDesc *flagdesc, u32 flagmask);
char *mystrtok_r(char *s, const char *sep, char **lasts);
u64 read_seed(const char *str);

Expand Down