From e666a962b1f0f8eeb3bab2232ce77556ddab974a Mon Sep 17 00:00:00 2001 From: rubidium42 Date: Sun, 23 May 2021 19:16:56 +0200 Subject: Codechange: let OneOfMany and ManyOfMany be their own classes as well --- src/settings.cpp | 190 +++++++++++++++-------------------------- src/settings_internal.h | 41 ++++++++- src/table/gameopt_settings.ini | 20 ++--- src/table/misc_settings.ini | 5 +- src/table/settings.h.preamble | 8 +- 5 files changed, 122 insertions(+), 142 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index f26e56686..24950e779 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -127,31 +127,23 @@ static const char * const _list_group_names[] = { /** * Find the index value of a ONEofMANY type in a string separated by | + * @param str the current value of the setting for which a value needs found + * @param len length of the string * @param many full domain of values the ONEofMANY setting can have - * @param one the current value of the setting for which a value needs found - * @param onelen force calculation of the *one parameter * @return the integer index of the full-list, or -1 if not found */ -static size_t LookupOneOfMany(const char *many, const char *one, size_t onelen = 0) +size_t OneOfManySettingDesc::ParseSingleValue(const char *str, size_t len, const std::vector &many) { - const char *s; - size_t idx; - - if (onelen == 0) onelen = strlen(one); - /* check if it's an integer */ - if (*one >= '0' && *one <= '9') return strtoul(one, nullptr, 0); + if (isdigit(*str)) return strtoul(str, nullptr, 0); - idx = 0; - for (;;) { - /* find end of item */ - s = many; - while (*s != '|' && *s != 0) s++; - if ((size_t)(s - many) == onelen && !memcmp(one, many, onelen)) return idx; - if (*s == 0) return (size_t)-1; - many = s + 1; + size_t idx = 0; + for (auto one : many) { + if (one.size() == len && strncmp(one.c_str(), str, len) == 0) return idx; idx++; } + + return (size_t)-1; } /** @@ -161,7 +153,7 @@ static size_t LookupOneOfMany(const char *many, const char *one, size_t onelen = * of separated by a whitespace,tab or | character * @return the 'fully' set integer, or -1 if a set is not found */ -static size_t LookupManyOfMany(const char *many, const char *str) +static size_t LookupManyOfMany(const std::vector &many, const char *str) { const char *s; size_t r; @@ -175,7 +167,7 @@ static size_t LookupManyOfMany(const char *many, const char *str) s = str; while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++; - r = LookupOneOfMany(many, str, s - str); + r = OneOfManySettingDesc::ParseSingleValue(str, s - str, many); if (r == (size_t)-1) return r; SetBit(res, (uint8)r); // value found, set it @@ -311,66 +303,30 @@ void ListSettingDesc::FormatValue(char *buf, const char *last, const void *objec } } -/** - * Convert a ONEofMANY structure to a string representation. - * @param buf output buffer where the string-representation will be stored - * @param last last item to write to in the output buffer - * @param many the full-domain string of possible values - * @param id the value of the variable and whose string-representation must be found - */ -static void MakeOneOfMany(char *buf, const char *last, const char *many, int id) +char *OneOfManySettingDesc::FormatSingleValue(char *buf, const char *last, uint id) const { - int orig_id = id; - - /* Look for the id'th element */ - while (--id >= 0) { - for (; *many != '|'; many++) { - if (*many == '\0') { // not found - seprintf(buf, last, "%d", orig_id); - return; - } - } - many++; // pass the |-character + if (id >= this->many.size()) { + return buf + seprintf(buf, last, "%d", id); } - - /* copy string until next item (|) or the end of the list if this is the last one */ - while (*many != '\0' && *many != '|' && buf < last) *buf++ = *many++; - *buf = '\0'; + return strecpy(buf, this->many[id].c_str(), last); } -/** - * Convert a MANYofMANY structure to a string representation. - * @param buf output buffer where the string-representation will be stored - * @param last last item to write to in the output buffer - * @param many the full-domain string of possible values - * @param x the value of the variable and whose string-representation must - * be found in the bitmasked many string - */ -static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 x) +void OneOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const { - const char *start; - int i = 0; - bool init = true; - - for (; x != 0; x >>= 1, i++) { - start = many; - while (*many != 0 && *many != '|') many++; // advance to the next element - - if (HasBit(x, 0)) { // item found, copy it - if (!init) buf += seprintf(buf, last, "|"); - init = false; - if (start == many) { - buf += seprintf(buf, last, "%d", i); - } else { - memcpy(buf, start, many - start); - buf += many - start; - } - } + uint id = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + this->FormatSingleValue(buf, last, id); +} - if (*many == '|') many++; +void ManyOfManySettingDesc::FormatValue(char *buf, const char *last, const void *object) const +{ + uint bitmask = (uint)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); + uint id = 0; + bool first = true; + FOR_EACH_SET_BIT(id, bitmask) { + if (!first) buf = strecpy(buf, "|", last); + buf = this->FormatSingleValue(buf, last, id); + first = false; } - - *buf = '\0'; } /** @@ -380,52 +336,46 @@ static void MakeManyOfMany(char *buf, const char *last, const char *many, uint32 */ size_t IntSettingDesc::ParseValue(const char *str) const { - switch (this->cmd) { - case SDT_NUMX: { - char *end; - size_t val = strtoul(str, &end, 0); - if (end == str) { - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } - if (*end != '\0') { - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS); - msg.SetDParamStr(0, this->name); - _settings_error_list.push_back(msg); - } - return val; - } - - case SDT_ONEOFMANY: { - size_t r = LookupOneOfMany(this->many, str); - /* if the first attempt of conversion from string to the appropriate value fails, - * look if we have defined a converter from old value to new value. */ - if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str); - if (r != (size_t)-1) return r; // and here goes converted value - - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } + char *end; + size_t val = strtoul(str, &end, 0); + if (end == str) { + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); + return this->def; + } + if (*end != '\0') { + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_TRAILING_CHARACTERS); + msg.SetDParamStr(0, this->name); + _settings_error_list.push_back(msg); + } + return val; +} - case SDT_MANYOFMANY: { - size_t r = LookupManyOfMany(this->many, str); - if (r != (size_t)-1) return r; - ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); - msg.SetDParamStr(0, str); - msg.SetDParamStr(1, this->name); - _settings_error_list.push_back(msg); - break; - } +size_t OneOfManySettingDesc::ParseValue(const char *str) const +{ + size_t r = OneOfManySettingDesc::ParseSingleValue(str, strlen(str), this->many); + /* if the first attempt of conversion from string to the appropriate value fails, + * look if we have defined a converter from old value to new value. */ + if (r == (size_t)-1 && this->many_cnvt != nullptr) r = this->many_cnvt(str); + if (r != (size_t)-1) return r; // and here goes converted value - default: NOT_REACHED(); - } + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); + return this->def; +} +size_t ManyOfManySettingDesc::ParseValue(const char *str) const +{ + size_t r = LookupManyOfMany(this->many, str); + if (r != (size_t)-1) return r; + ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_VALUE); + msg.SetDParamStr(0, str); + msg.SetDParamStr(1, this->name); + _settings_error_list.push_back(msg); return this->def; } @@ -663,12 +613,7 @@ static void IniSaveSettings(IniFile *ini, const SettingTable &settings_table, co void IntSettingDesc::FormatValue(char *buf, const char *last, const void *object) const { uint32 i = (uint32)ReadValue(GetVariableAddress(object, &this->save), this->save.conv); - switch (this->cmd) { - case SDT_NUMX: seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); break; - case SDT_ONEOFMANY: MakeOneOfMany(buf, last, this->many, i); break; - case SDT_MANYOFMANY: MakeManyOfMany(buf, last, this->many, i); break; - default: NOT_REACHED(); - } + seprintf(buf, last, IsSignedVarMemType(this->save.conv) ? "%d" : (this->save.conv & SLF_HEX) ? "%X" : "%u", i); } void BoolSettingDesc::FormatValue(char *buf, const char *last, const void *object) const @@ -1263,7 +1208,8 @@ static bool CheckRoadSide(int p1) static size_t ConvertLandscape(const char *value) { /* try with the old values */ - return LookupOneOfMany("normal|hilly|desert|candy", value); + static std::vector _old_landscape_values{"normal", "hilly", "desert", "candy"}; + return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values); } static bool CheckFreeformEdges(int32 p1) diff --git a/src/settings_internal.h b/src/settings_internal.h index 1174a1f63..488b85441 100644 --- a/src/settings_internal.h +++ b/src/settings_internal.h @@ -133,9 +133,9 @@ struct SettingDesc { struct IntSettingDesc : SettingDesc { IntSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, int32 def, int32 min, uint32 max, int32 interval, StringID str, StringID str_help, StringID str_val, - SettingCategory cat, OnChange *proc, const char *many = nullptr, OnConvert *many_cnvt = nullptr) : + SettingCategory cat, OnChange *proc) : SettingDesc(save, name, flags, cmd, startup), def(def), min(min), max(max), interval(interval), - str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc), many(many), many_cnvt(many_cnvt) {} + str(str), str_help(str_help), str_val(str_val), cat(cat), proc(proc) {} virtual ~IntSettingDesc() {} int32 def; ///< default value given when none is present @@ -147,8 +147,6 @@ struct IntSettingDesc : SettingDesc { StringID str_val; ///< (Translated) first string describing the value. SettingCategory cat; ///< assigned categories of the setting OnChange *proc; ///< callback procedure for when the value is changed - const char *many; ///< ONE/MANY_OF_MANY: string of possible values for this type - OnConvert *many_cnvt; ///< callback procedure when loading value mechanism fails void ChangeValue(const void *object, int32 newvalue) const; void Write_ValidateSetting(const void *object, int32 value) const; @@ -170,6 +168,41 @@ struct BoolSettingDesc : IntSettingDesc { void FormatValue(char *buf, const char *last, const void *object) const override; }; +/** One of many setting. */ +struct OneOfManySettingDesc : IntSettingDesc { + OneOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + int32 def, int32 max, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, + std::initializer_list many, OnConvert *many_cnvt) : + IntSettingDesc(save, name, flags, cmd, startup, def, 0, max, 0, str, str_help, str_val, cat, proc), many_cnvt(many_cnvt) + { + for (auto one : many) this->many.push_back(one); + } + + virtual ~OneOfManySettingDesc() {} + + std::vector many; ///< possible values for this type + OnConvert *many_cnvt; ///< callback procedure when loading value mechanism fails + + static size_t ParseSingleValue(const char *str, size_t len, const std::vector &many); + char *FormatSingleValue(char *buf, const char *last, uint id) const; + + size_t ParseValue(const char *str) const override; + void FormatValue(char *buf, const char *last, const void *object) const override; +}; + +/** Many of many setting. */ +struct ManyOfManySettingDesc : OneOfManySettingDesc { + ManyOfManySettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, + int32 def, StringID str, StringID str_help, StringID str_val, SettingCategory cat, OnChange *proc, + std::initializer_list many, OnConvert *many_cnvt) : + OneOfManySettingDesc(save, name, flags, cmd, startup, def, (1 << many.size()) - 1, str, str_help, + str_val, cat, proc, many, many_cnvt) {} + virtual ~ManyOfManySettingDesc() {} + + size_t ParseValue(const char *str) const override; + void FormatValue(char *buf, const char *last, const void *object) const override; +}; + /** String settings. */ struct StringSettingDesc : SettingDesc { StringSettingDesc(SaveLoad save, const char *name, SettingGuiFlag flags, SettingDescType cmd, bool startup, const char *def, diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index 1e60770f2..56ac7d781 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -12,16 +12,16 @@ uint8 _old_units; ///< Old units from old s /* Most of these strings are used both for gameopt-backward compatibility * and the settings tables. The rest is here for consistency. */ -static const char *_locale_currencies = "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|RON|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom"; -static const char *_locale_units = "imperial|metric|si|gameunits"; -static const char *_town_names = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovak|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan"; -static const char *_climates = "temperate|arctic|tropic|toyland"; -static const char *_autosave_interval = "off|monthly|quarterly|half year|yearly"; -static const char *_roadsides = "left|right"; -static const char *_savegame_date = "long|short|iso"; -static const char *_osk_activation = "disabled|double|single|immediately"; -static const char *_settings_profiles = "easy|medium|hard"; -static const char *_news_display = "off|summarized|full"; +static std::initializer_list _locale_currencies{"GBP", "USD", "EUR", "YEN", "ATS", "BEF", "CHF", "CZK", "DEM", "DKK", "ESP", "FIM", "FRF", "GRD", "HUF", "ISK", "ITL", "NLG", "NOK", "PLN", "RON", "RUR", "SIT", "SEK", "YTL", "SKK", "BRL", "EEK", "custom"}; +static std::initializer_list _locale_units{"imperial", "metric", "si", "gameunits"}; +static std::initializer_list _town_names{"english", "french", "german", "american", "latin", "silly", "swedish", "dutch", "finnish", "polish", "slovak", "norwegian", "hungarian", "austrian", "romanian", "czech", "swiss", "danish", "turkish", "italian", "catalan"}; +static std::initializer_list _climates{"temperate", "arctic", "tropic", "toyland"}; +static std::initializer_list _autosave_interval{"off", "monthly", "quarterly", "half year", "yearly"}; +static std::initializer_list _roadsides{"left", "right"}; +static std::initializer_list _savegame_date{"long", "short", "iso"}; +static std::initializer_list _osk_activation{"disabled", "double", "single", "immediately"}; +static std::initializer_list _settings_profiles{"easy", "medium", "hard"}; +static std::initializer_list _news_display{ "off", "summarized", "full"}; static const SettingTable _gameopt_settings{ /* In version 4 a new difficulty setting has been added to the difficulty settings, diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index a3efbc65e..017320c86 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -7,7 +7,8 @@ [pre-amble] extern std::string _config_language_file; -static const char *_support8bppmodes = "no|system|hardware"; +static std::initializer_list _support8bppmodes{"no", "system" , "hardware"}; +static std::initializer_list _display_opt_modes{"SHOW_TOWN_NAMES", "SHOW_STATION_NAMES", "SHOW_SIGNS", "FULL_ANIMATION", "", "FULL_DETAIL", "WAYPOINTS", "SHOW_COMPETITOR_SIGNS"}; #ifdef WITH_COCOA extern bool _allow_hidpi_window; @@ -53,7 +54,7 @@ name = ""display_opt"" type = SLE_UINT8 var = _display_opt def = (1 << DO_SHOW_TOWN_NAMES | 1 << DO_SHOW_STATION_NAMES | 1 << DO_SHOW_SIGNS | 1 << DO_FULL_ANIMATION | 1 << DO_FULL_DETAIL | 1 << DO_SHOW_WAYPOINT_NAMES | 1 << DO_SHOW_COMPETITOR_SIGNS) -full = ""SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION||FULL_DETAIL|WAYPOINTS|SHOW_COMPETITOR_SIGNS"" +full = _display_opt_modes [SDTG_BOOL] name = ""fullscreen"" diff --git a/src/table/settings.h.preamble b/src/table/settings.h.preamble index c6788f707..df10b6deb 100644 --- a/src/table/settings.h.preamble +++ b/src/table/settings.h.preamble @@ -71,10 +71,10 @@ static size_t ConvertLandscape(const char *value); NSD(String, SLEG_GENERAL(SL_STDSTR, var, type | flags, sizeof(var), from, to, extra), name, guiflags, SDT_STDSTRING, startup, def, max_length, proc) #define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full) + NSD(OneOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat, extra, startup)\ - NSD(Int, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full) + NSD(ManyOfMany, SLEG_GENERAL(SL_VAR, var, type | flags, 1, from, to, extra), name, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDTG_NULL(length, from, to)\ NSD(Null, SLEG_NULL(length, from, to)) @@ -94,10 +94,10 @@ static size_t ConvertLandscape(const char *value); NSD(String, SLE_GENERAL(SL_STDSTR, base, var, type | flags, sizeof(((base*)8)->var), from, to, extra), #var, guiflags, SDT_STDSTRING, startup, def, 0, proc) #define SDT_OMANY(base, var, type, flags, guiflags, def, max, full, str, strhelp, strval, proc, from, to, load, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, 0, max, 0, str, strhelp, strval, cat, proc, full, load) + NSD(OneOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_ONEOFMANY, startup, def, max, str, strhelp, strval, cat, proc, full, load) #define SDT_MMANY(base, var, type, flags, guiflags, def, full, str, proc, strhelp, strval, from, to, cat, extra, startup)\ - NSD(Int, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, 0, 0, 0, str, strhelp, strval, cat, proc, full, nullptr) + NSD(ManyOfMany, SLE_GENERAL(SL_VAR, base, var, type | flags, 1, from, to, extra), #var, guiflags, SDT_MANYOFMANY, startup, def, str, strhelp, strval, cat, proc, full, nullptr) #define SDT_NULL(length, from, to)\ NSD(Null, SLE_CONDNULL(length, from, to)) -- cgit v1.2.3-54-g00ecf