mirror of https://github.com/OpenTTD/OpenTTD
Codechange: use std::string_view to parse setting values
parent
12118b201c
commit
fdb8defa64
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include <charconv>
|
||||
#include "core/string_consumer.hpp"
|
||||
#include "settings_table.h"
|
||||
#include "debug.h"
|
||||
#include "currency.h"
|
||||
|
@ -178,24 +179,21 @@ enum IniFileVersion : uint32_t {
|
|||
const uint16_t INIFILE_VERSION = (IniFileVersion)(IFV_MAX_VERSION - 1); ///< Current ini-file version of OpenTTD.
|
||||
|
||||
/**
|
||||
* Find the index value of a ONEofMANY type in a string separated by |
|
||||
* Find the index value of a ONEofMANY type in a string
|
||||
* @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
|
||||
* @return the integer index of the full-list, or SIZE_MAX if not found
|
||||
* @return the integer index of the full-list, or std::nullopt if not found
|
||||
*/
|
||||
size_t OneOfManySettingDesc::ParseSingleValue(const char *str, size_t len, const std::vector<std::string> &many)
|
||||
std::optional<uint32_t> OneOfManySettingDesc::ParseSingleValue(std::string_view str, const std::vector<std::string> &many)
|
||||
{
|
||||
StringConsumer consumer{str};
|
||||
auto digit = consumer.TryReadIntegerBase<uint32_t>(10);
|
||||
/* check if it's an integer */
|
||||
if (isdigit(*str)) return std::strtoul(str, nullptr, 0);
|
||||
if (digit.has_value()) return digit;
|
||||
|
||||
size_t idx = 0;
|
||||
for (const auto &one : many) {
|
||||
if (one.size() == len && strncmp(one.c_str(), str, len) == 0) return idx;
|
||||
idx++;
|
||||
}
|
||||
|
||||
return SIZE_MAX;
|
||||
auto it = std::ranges::find(many, str);
|
||||
if (it == many.end()) return std::nullopt;
|
||||
return static_cast<uint32_t>(it - many.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,10 +202,10 @@ size_t OneOfManySettingDesc::ParseSingleValue(const char *str, size_t len, const
|
|||
* @param str the current value of the setting for which a value needs found.
|
||||
* @return Either true/false, or nullopt if no boolean value found.
|
||||
*/
|
||||
std::optional<bool> BoolSettingDesc::ParseSingleValue(const char *str)
|
||||
std::optional<bool> BoolSettingDesc::ParseSingleValue(std::string_view str)
|
||||
{
|
||||
if (strcmp(str, "true") == 0 || strcmp(str, "on") == 0 || strcmp(str, "1") == 0) return true;
|
||||
if (strcmp(str, "false") == 0 || strcmp(str, "off") == 0 || strcmp(str, "0") == 0) return false;
|
||||
if (str == "true" || str == "on" || str == "1") return true;
|
||||
if (str == "false" || str == "off" || str == "0") return false;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -216,29 +214,26 @@ std::optional<bool> BoolSettingDesc::ParseSingleValue(const char *str)
|
|||
* Find the set-integer value MANYofMANY type in a string
|
||||
* @param many full domain of values the MANYofMANY setting can have
|
||||
* @param str the current string value of the setting, each individual
|
||||
* of separated by a whitespace,tab or | character
|
||||
* @return the 'fully' set integer, or SIZE_MAX if a set is not found
|
||||
* of separated by a whitespace, tab or | character
|
||||
* @return the 'fully' set integer, or std::nullopt if a set is not found
|
||||
*/
|
||||
static size_t LookupManyOfMany(const std::vector<std::string> &many, const char *str)
|
||||
static std::optional<uint32_t> LookupManyOfMany(const std::vector<std::string> &many, std::string_view str)
|
||||
{
|
||||
const char *s;
|
||||
size_t r;
|
||||
size_t res = 0;
|
||||
static const std::string_view separators{" \t|"};
|
||||
|
||||
for (;;) {
|
||||
uint32_t res = 0;
|
||||
StringConsumer consumer{str};
|
||||
while (consumer.AnyBytesLeft()) {
|
||||
/* skip "whitespace" */
|
||||
while (*str == ' ' || *str == '\t' || *str == '|') str++;
|
||||
if (*str == 0) break;
|
||||
consumer.SkipUntilCharNotIn(separators);
|
||||
|
||||
s = str;
|
||||
while (*s != 0 && *s != ' ' && *s != '\t' && *s != '|') s++;
|
||||
std::string_view value = consumer.ReadUntilCharIn(separators);
|
||||
if (value.empty()) break;
|
||||
|
||||
r = OneOfManySettingDesc::ParseSingleValue(str, s - str, many);
|
||||
if (r == SIZE_MAX) return r;
|
||||
auto r = OneOfManySettingDesc::ParseSingleValue(value, many);
|
||||
if (!r.has_value()) return r;
|
||||
|
||||
SetBit(res, (uint8_t)r); // value found, set it
|
||||
if (*s == 0) break;
|
||||
str = s + 1;
|
||||
SetBit(res, *r); // value found, set it
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -378,31 +373,32 @@ std::string ManyOfManySettingDesc::FormatValue(const void *object) const
|
|||
* @param str Input string that will be parsed based on the type of desc.
|
||||
* @return The value from the parse string, or the default value of the setting.
|
||||
*/
|
||||
size_t IntSettingDesc::ParseValue(const char *str) const
|
||||
int32_t IntSettingDesc::ParseValue(std::string_view str) const
|
||||
{
|
||||
char *end;
|
||||
size_t val = std::strtoul(str, &end, 0);
|
||||
if (end == str) {
|
||||
StringConsumer consumer{str};
|
||||
/* The actual settings value might be int32 or uint32. Read as int64 and just cast away the high bits. */
|
||||
auto value = consumer.TryReadIntegerBase<int64_t>(10);
|
||||
if (!value.has_value()) {
|
||||
_settings_error_list.emplace_back(
|
||||
GetEncodedString(STR_CONFIG_ERROR),
|
||||
GetEncodedString(STR_CONFIG_ERROR_INVALID_VALUE, str, this->GetName()));
|
||||
return this->GetDefaultValue();
|
||||
}
|
||||
if (*end != '\0') {
|
||||
if (consumer.AnyBytesLeft()) {
|
||||
_settings_error_list.emplace_back(
|
||||
GetEncodedString(STR_CONFIG_ERROR),
|
||||
GetEncodedString(STR_CONFIG_ERROR_TRAILING_CHARACTERS, this->GetName()));
|
||||
}
|
||||
return val;
|
||||
return static_cast<int32_t>(*value);
|
||||
}
|
||||
|
||||
size_t OneOfManySettingDesc::ParseValue(const char *str) const
|
||||
int32_t OneOfManySettingDesc::ParseValue(std::string_view str) const
|
||||
{
|
||||
size_t r = OneOfManySettingDesc::ParseSingleValue(str, strlen(str), this->many);
|
||||
auto r = OneOfManySettingDesc::ParseSingleValue(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_MAX && this->many_cnvt != nullptr) r = this->many_cnvt(str);
|
||||
if (r != SIZE_MAX) return r; // and here goes converted value
|
||||
if (!r.has_value() && this->many_cnvt != nullptr) r = this->many_cnvt(str);
|
||||
if (r.has_value()) return *r; // and here goes converted value
|
||||
|
||||
_settings_error_list.emplace_back(
|
||||
GetEncodedString(STR_CONFIG_ERROR),
|
||||
|
@ -410,10 +406,10 @@ size_t OneOfManySettingDesc::ParseValue(const char *str) const
|
|||
return this->GetDefaultValue();
|
||||
}
|
||||
|
||||
size_t ManyOfManySettingDesc::ParseValue(const char *str) const
|
||||
int32_t ManyOfManySettingDesc::ParseValue(std::string_view str) const
|
||||
{
|
||||
size_t r = LookupManyOfMany(this->many, str);
|
||||
if (r != SIZE_MAX) return r;
|
||||
auto r = LookupManyOfMany(this->many, str);
|
||||
if (r.has_value()) return *r;
|
||||
|
||||
_settings_error_list.emplace_back(
|
||||
GetEncodedString(STR_CONFIG_ERROR),
|
||||
|
@ -421,7 +417,7 @@ size_t ManyOfManySettingDesc::ParseValue(const char *str) const
|
|||
return this->GetDefaultValue();
|
||||
}
|
||||
|
||||
size_t BoolSettingDesc::ParseValue(const char *str) const
|
||||
int32_t BoolSettingDesc::ParseValue(std::string_view str) const
|
||||
{
|
||||
auto r = BoolSettingDesc::ParseSingleValue(str);
|
||||
if (r.has_value()) return *r;
|
||||
|
@ -673,8 +669,8 @@ static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, co
|
|||
|
||||
void IntSettingDesc::ParseValue(const IniItem *item, void *object) const
|
||||
{
|
||||
size_t val = (item == nullptr) ? this->GetDefaultValue() : this->ParseValue(item->value.has_value() ? item->value->c_str() : "");
|
||||
this->MakeValueValidAndWrite(object, (int32_t)val);
|
||||
int32_t val = (item != nullptr && item->value.has_value()) ? this->ParseValue(*item->value) : this->GetDefaultValue();
|
||||
this->MakeValueValidAndWrite(object, val);
|
||||
}
|
||||
|
||||
void StringSettingDesc::ParseValue(const IniItem *item, void *object) const
|
||||
|
@ -760,7 +756,7 @@ std::string BoolSettingDesc::FormatValue(const void *object) const
|
|||
|
||||
bool IntSettingDesc::IsSameValue(const IniItem *item, void *object) const
|
||||
{
|
||||
int32_t item_value = (int32_t)this->ParseValue(item->value->c_str());
|
||||
int32_t item_value = static_cast<int32_t>(this->ParseValue(*item->value));
|
||||
int32_t object_value = this->Read(object);
|
||||
return item_value == object_value;
|
||||
}
|
||||
|
@ -1413,13 +1409,13 @@ void LoadFromConfig(bool startup)
|
|||
const IniItem *old_item;
|
||||
|
||||
if (generic_version < IFV_GAME_TYPE && IsConversionNeeded(generic_ini, "network", "server_advertise", "server_game_type", &old_item)) {
|
||||
auto old_value = BoolSettingDesc::ParseSingleValue(old_item->value->c_str());
|
||||
auto old_value = BoolSettingDesc::ParseSingleValue(*old_item->value);
|
||||
_settings_client.network.server_game_type = old_value.value_or(false) ? SERVER_GAME_TYPE_PUBLIC : SERVER_GAME_TYPE_LOCAL;
|
||||
}
|
||||
|
||||
if (generic_version < IFV_AUTOSAVE_RENAME && IsConversionNeeded(generic_ini, "gui", "autosave", "autosave_interval", &old_item)) {
|
||||
static std::vector<std::string> _old_autosave_interval{"off", "monthly", "quarterly", "half year", "yearly"};
|
||||
auto old_value = OneOfManySettingDesc::ParseSingleValue(old_item->value->c_str(), old_item->value->size(), _old_autosave_interval);
|
||||
auto old_value = OneOfManySettingDesc::ParseSingleValue(*old_item->value, _old_autosave_interval).value_or(-1);
|
||||
|
||||
switch (old_value) {
|
||||
case 0: _settings_client.gui.autosave_interval = 0; break;
|
||||
|
@ -1433,7 +1429,7 @@ void LoadFromConfig(bool startup)
|
|||
|
||||
/* Persist the right click close option from older versions. */
|
||||
if (generic_version < IFV_RIGHT_CLICK_CLOSE && IsConversionNeeded(generic_ini, "gui", "right_mouse_wnd_close", "right_click_wnd_close", &old_item)) {
|
||||
auto old_value = BoolSettingDesc::ParseSingleValue(old_item->value->c_str());
|
||||
auto old_value = BoolSettingDesc::ParseSingleValue(*old_item->value);
|
||||
_settings_client.gui.right_click_wnd_close = old_value.value_or(false) ? RCC_YES : RCC_NO;
|
||||
}
|
||||
|
||||
|
|
|
@ -235,7 +235,7 @@ struct IntSettingDesc : SettingDesc {
|
|||
void ChangeValue(const void *object, int32_t newvalue) const;
|
||||
void MakeValueValidAndWrite(const void *object, int32_t value) const;
|
||||
|
||||
virtual size_t ParseValue(const char *str) const;
|
||||
virtual int32_t ParseValue(std::string_view str) const;
|
||||
std::string FormatValue(const void *object) const override;
|
||||
void ParseValue(const IniItem *item, void *object) const override;
|
||||
bool IsSameValue(const IniItem *item, void *object) const override;
|
||||
|
@ -258,16 +258,16 @@ struct BoolSettingDesc : IntSettingDesc {
|
|||
IntSettingDesc(save, flags, startup, def ? 1 : 0, 0, 1, 0, str, str_help, str_val, cat,
|
||||
pre_check, post_callback, get_title_cb, get_help_cb, get_value_params_cb, get_def_cb, nullptr) {}
|
||||
|
||||
static std::optional<bool> ParseSingleValue(const char *str);
|
||||
static std::optional<bool> ParseSingleValue(std::string_view str);
|
||||
|
||||
bool IsBoolSetting() const override { return true; }
|
||||
size_t ParseValue(const char *str) const override;
|
||||
int32_t ParseValue(std::string_view str) const override;
|
||||
std::string FormatValue(const void *object) const override;
|
||||
};
|
||||
|
||||
/** One of many setting. */
|
||||
struct OneOfManySettingDesc : IntSettingDesc {
|
||||
typedef size_t OnConvert(const char *value); ///< callback prototype for conversion error
|
||||
typedef std::optional<uint32_t> OnConvert(std::string_view value); ///< callback prototype for conversion error
|
||||
|
||||
template <ConvertibleThroughBaseOrTo<int32_t> Tdef, ConvertibleThroughBaseOrTo<uint32_t> Tmax>
|
||||
OneOfManySettingDesc(const SaveLoad &save, SettingFlags flags, bool startup, Tdef def,
|
||||
|
@ -284,10 +284,10 @@ struct OneOfManySettingDesc : IntSettingDesc {
|
|||
std::vector<std::string> 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<std::string> &many);
|
||||
static std::optional<uint32_t> ParseSingleValue(std::string_view str, const std::vector<std::string> &many);
|
||||
std::string FormatSingleValue(uint id) const;
|
||||
|
||||
size_t ParseValue(const char *str) const override;
|
||||
int32_t ParseValue(std::string_view str) const override;
|
||||
std::string FormatValue(const void *object) const override;
|
||||
};
|
||||
|
||||
|
@ -302,7 +302,7 @@ struct ManyOfManySettingDesc : OneOfManySettingDesc {
|
|||
OneOfManySettingDesc(save, flags, startup, def, (1 << many.size()) - 1, str, str_help,
|
||||
str_val, cat, pre_check, post_callback, get_title_cb, get_help_cb, get_value_params_cb, get_def_cb, many, many_cnvt) {}
|
||||
|
||||
size_t ParseValue(const char *str) const override;
|
||||
int32_t ParseValue(std::string_view str) const override;
|
||||
std::string FormatValue(const void *object) const override;
|
||||
};
|
||||
|
||||
|
|
|
@ -445,11 +445,11 @@ static bool CheckRoadSide(int32_t &)
|
|||
* @param value that was read from config file
|
||||
* @return the "hopefully" converted value
|
||||
*/
|
||||
static size_t ConvertLandscape(const char *value)
|
||||
static std::optional<uint32_t> ConvertLandscape(std::string_view value)
|
||||
{
|
||||
/* try with the old values */
|
||||
static std::vector<std::string> _old_landscape_values{"normal", "hilly", "desert", "candy"};
|
||||
return OneOfManySettingDesc::ParseSingleValue(value, strlen(value), _old_landscape_values);
|
||||
return OneOfManySettingDesc::ParseSingleValue(value, _old_landscape_values);
|
||||
}
|
||||
|
||||
static bool CheckFreeformEdges(int32_t &new_value)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "table/strings.h"
|
||||
|
||||
/* Callback function used in _settings[] as well as _company_settings[] */
|
||||
static size_t ConvertLandscape(const char *value);
|
||||
static std::optional<uint32_t> ConvertLandscape(std::string_view value);
|
||||
|
||||
static StringID SettingTitleWallclock(const IntSettingDesc &sd);
|
||||
static StringID SettingHelpWallclock(const IntSettingDesc &sd);
|
||||
|
|
Loading…
Reference in New Issue