From fd7a883cbd580407a48cd3f370c65f1e82a2fcec Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 2 Jan 2025 09:03:38 +0100 Subject: [PATCH] Codechange: make the StringIndex (within a StringTab) a strong type --- src/game/game_text.cpp | 18 +++++++++--------- src/game/game_text.hpp | 8 +++++--- src/newgrf_text.cpp | 14 +++++++------- src/newgrf_text.h | 2 +- src/script/api/script_error.cpp | 2 +- src/script/api/script_text.cpp | 4 ++-- src/script/api/script_text.hpp | 6 +++--- src/strings.cpp | 12 ++++++------ src/strings_func.h | 10 +++++----- src/strings_type.h | 5 +++++ 10 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 3edd778512..f086f72407 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -315,10 +315,10 @@ GameStrings *_current_data = nullptr; * @param id The ID of the game string. * @return The encoded string. */ -const char *GetGameStringPtr(uint id) +const char *GetGameStringPtr(StringIndexInTab id) { - if (_current_data == nullptr || _current_data->cur_language == nullptr || id >= _current_data->cur_language->lines.size()) return GetStringPtr(STR_UNDEFINED); - return _current_data->cur_language->lines[id].c_str(); + if (_current_data == nullptr || _current_data->cur_language == nullptr || id.base() >= _current_data->cur_language->lines.size()) return GetStringPtr(STR_UNDEFINED); + return _current_data->cur_language->lines[id.base()].c_str(); } /** @@ -326,13 +326,13 @@ const char *GetGameStringPtr(uint id) * @param id The ID of the game string. * @return The string parameters. */ -const StringParams &GetGameStringParams(uint id) +const StringParams &GetGameStringParams(StringIndexInTab id) { /* An empty result for STR_UNDEFINED. */ static StringParams empty; - if (id >= _current_data->string_params.size()) return empty; - return _current_data->string_params[id]; + if (id.base() >= _current_data->string_params.size()) return empty; + return _current_data->string_params[id.base()]; } /** @@ -340,13 +340,13 @@ const StringParams &GetGameStringParams(uint id) * @param id The ID of the game string. * @return The name of the string. */ -const std::string &GetGameStringName(uint id) +const std::string &GetGameStringName(StringIndexInTab id) { /* The name for STR_UNDEFINED. */ static const std::string undefined = "STR_UNDEFINED"; - if (id >= _current_data->string_names.size()) return undefined; - return _current_data->string_names[id]; + if (id.base() >= _current_data->string_names.size()) return undefined; + return _current_data->string_names[id.base()]; } /** diff --git a/src/game/game_text.hpp b/src/game/game_text.hpp index e0c45741d8..47941d6e36 100644 --- a/src/game/game_text.hpp +++ b/src/game/game_text.hpp @@ -10,6 +10,8 @@ #ifndef GAME_TEXT_HPP #define GAME_TEXT_HPP +#include "../strings_type.h" + struct StringParam { enum ParamType { UNUSED, @@ -27,9 +29,9 @@ struct StringParam { using StringParams = std::vector; using StringParamsList = std::vector; -const char *GetGameStringPtr(uint id); -const StringParams &GetGameStringParams(uint id); -const std::string &GetGameStringName(uint id); +const char *GetGameStringPtr(StringIndexInTab id); +const StringParams &GetGameStringParams(StringIndexInTab id); +const std::string &GetGameStringName(StringIndexInTab id); void RegisterGameTranslation(class Squirrel *engine); void ReconsiderGameScriptLanguage(); diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index 56661e932f..2383212b5a 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -571,7 +571,7 @@ StringID AddGRFString(uint32_t grfid, GRFStringID stringid, uint8_t langid_to_ad it->stringid = stringid; it->def_string = def_string; } - uint id = static_cast(it - std::begin(_grf_text)); + StringIndexInTab id(it - std::begin(_grf_text)); std::string newtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add); AddGRFTextToList(it->textholder, langid_to_add, newtext); @@ -588,7 +588,7 @@ StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid) { auto it = std::ranges::find_if(_grf_text, [&grfid, &stringid](const GRFTextEntry &grf_text) { return grf_text.grfid == grfid && grf_text.stringid == stringid; }); if (it != std::end(_grf_text)) { - uint id = static_cast(it - std::begin(_grf_text)); + StringIndexInTab id(it - std::begin(_grf_text)); return MakeStringID(TEXT_TAB_NEWGRF_START, id); } @@ -636,16 +636,16 @@ const char *GetGRFStringFromGRFText(const GRFTextWrapper &text) /** * Get a C-string from a stringid set by a newgrf. */ -const char *GetGRFStringPtr(uint32_t stringid) +const char *GetGRFStringPtr(StringIndexInTab stringid) { - assert(stringid < _grf_text.size()); - assert(_grf_text[stringid].grfid != 0); + assert(stringid.base() < _grf_text.size()); + assert(_grf_text[stringid.base()].grfid != 0); - const char *str = GetGRFStringFromGRFText(_grf_text[stringid].textholder); + const char *str = GetGRFStringFromGRFText(_grf_text[stringid.base()].textholder); if (str != nullptr) return str; /* Use the default string ID if the fallback string isn't available */ - return GetStringPtr(_grf_text[stringid].def_string); + return GetStringPtr(_grf_text[stringid.base()].def_string); } /** diff --git a/src/newgrf_text.h b/src/newgrf_text.h index 3464523d22..2d1ea70886 100644 --- a/src/newgrf_text.h +++ b/src/newgrf_text.h @@ -18,7 +18,7 @@ StringID AddGRFString(uint32_t grfid, GRFStringID stringid, uint8_t langid, bool StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid); const char *GetGRFStringFromGRFText(const GRFTextList &text_list); const char *GetGRFStringFromGRFText(const GRFTextWrapper &text); -const char *GetGRFStringPtr(uint32_t stringid); +const char *GetGRFStringPtr(StringIndexInTab stringid); void CleanUpStrings(); void SetCurrentGrfLangID(uint8_t language_id); std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool allow_newlines, std::string_view str, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID); diff --git a/src/script/api/script_error.cpp b/src/script/api/script_error.cpp index 1d18ef112a..a3f0e48d96 100644 --- a/src/script/api/script_error.cpp +++ b/src/script/api/script_error.cpp @@ -30,7 +30,7 @@ ScriptError::ScriptErrorMapString ScriptError::error_map_string = ScriptError::S /* static */ ScriptErrorType ScriptError::StringToError(StringID internal_string_id) { - uint index = GetStringIndex(internal_string_id); + StringIndexInTab index = GetStringIndex(internal_string_id); switch (GetStringTab(internal_string_id)) { case TEXT_TAB_NEWGRF_START: case TEXT_TAB_GAMESCRIPT_START: diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index 9ec7b09e6b..0d923034a0 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -33,7 +33,7 @@ ScriptText::ScriptText(HSQUIRRELVM vm) if (SQ_FAILED(sq_getinteger(vm, 2, &sqstring))) { throw sq_throwerror(vm, "First argument must be a valid StringID"); } - this->string = sqstring; + this->string = StringIndexInTab(sqstring); /* The rest of the parameters must be arguments. */ for (int i = 0; i < nparam - 1; i++) { @@ -185,7 +185,7 @@ void ScriptText::_FillParamList(ParamList ¶ms, ScriptTextList &seen_texts) static Param dummy = 0; int nb_extra = SCRIPT_TEXT_MAX_PARAMETERS - (int)params.size(); for (int i = 0; i < nb_extra; i++) - params.emplace_back(-1, i, &dummy); + params.emplace_back(StringIndexInTab(-1), i, &dummy); } } diff --git a/src/script/api/script_text.hpp b/src/script/api/script_text.hpp index 03715398f3..6447e6cc76 100644 --- a/src/script/api/script_text.hpp +++ b/src/script/api/script_text.hpp @@ -132,13 +132,13 @@ private: using Param = std::variant; struct ParamCheck { - StringID owner; + StringIndexInTab owner; int idx; Param *param; bool used = false; const char *cmd = nullptr; - ParamCheck(StringID owner, int idx, Param *param) : owner(owner), idx(idx), param(param) {} + ParamCheck(StringIndexInTab owner, int idx, Param *param) : owner(owner), idx(idx), param(param) {} void Encode(std::back_insert_iterator &output, const char *cmd); }; @@ -146,7 +146,7 @@ private: using ParamList = std::vector; using ParamSpan = std::span; - StringID string; + StringIndexInTab string; std::array param = {}; int paramc = 0; diff --git a/src/strings.cpp b/src/strings.cpp index 9c8b01e204..ef5e6be1b5 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -239,7 +239,7 @@ const char *GetStringPtr(StringID string) case TEXT_TAB_OLD_NEWGRF: NOT_REACHED(); case TEXT_TAB_NEWGRF_START: return GetGRFStringPtr(GetStringIndex(string)); default: { - const uint offset = _langpack.langtab_start[GetStringTab(string)] + GetStringIndex(string); + const size_t offset = _langpack.langtab_start[GetStringTab(string)] + GetStringIndex(string).base(); if (offset < _langpack.offsets.size()) return _langpack.offsets[offset]; return nullptr; } @@ -261,14 +261,14 @@ void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters return; } - uint index = GetStringIndex(string); + StringIndexInTab index = GetStringIndex(string); StringTab tab = GetStringTab(string); switch (tab) { case TEXT_TAB_TOWN: if (index >= 0xC0 && !game_script) { try { - GetSpecialTownNameString(builder, index - 0xC0, args.GetNextParameter()); + GetSpecialTownNameString(builder, index.base() - 0xC0, args.GetNextParameter()); } catch (const std::runtime_error &e) { Debug(misc, 0, "GetStringWithArgs: {}", e.what()); builder += "(invalid string parameter)"; @@ -280,7 +280,7 @@ void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters case TEXT_TAB_SPECIAL: if (index >= 0xE4 && !game_script) { try { - GetSpecialNameString(builder, index - 0xE4, args); + GetSpecialNameString(builder, index.base() - 0xE4, args); } catch (const std::runtime_error &e) { Debug(misc, 0, "GetStringWithArgs: {}", e.what()); builder += "(invalid string parameter)"; @@ -987,7 +987,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara ArrayStringParameters<20> sub_args; char *p; - uint32_t stringid = std::strtoul(str, &p, 16); + StringIndexInTab stringid(std::strtoul(str, &p, 16)); if (*p != ':' && *p != '\0') { while (*p != '\0') p++; str = p; @@ -1048,7 +1048,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara builder += "(invalid sub-StringID)"; break; } - param = MakeStringID(TEXT_TAB_GAMESCRIPT_START, param); + param = MakeStringID(TEXT_TAB_GAMESCRIPT_START, StringIndexInTab(param)); } sub_args.SetParam(i++, param); diff --git a/src/strings_func.h b/src/strings_func.h index 43076207a5..6a43472db1 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -35,18 +35,18 @@ inline StringTab GetStringTab(StringID str) * @param str String identifier * @return StringIndex from \a str */ -inline uint GetStringIndex(StringID str) +inline StringIndexInTab GetStringIndex(StringID str) { - return str - (GetStringTab(str) << TAB_SIZE_BITS); + return StringIndexInTab{str - (GetStringTab(str) << TAB_SIZE_BITS)}; } /** * Create a StringID * @param tab StringTab - * @param index StringIndex + * @param index Index of the string within the given tab. * @return StringID composed from \a tab and \a index */ -inline StringID MakeStringID(StringTab tab, uint index) +inline StringID MakeStringID(StringTab tab, StringIndexInTab index) { if (tab == TEXT_TAB_NEWGRF_START) { assert(index < TAB_SIZE_NEWGRF); @@ -56,7 +56,7 @@ inline StringID MakeStringID(StringTab tab, uint index) assert(tab < TEXT_TAB_END); assert(index < TAB_SIZE); } - return (tab << TAB_SIZE_BITS) + index; + return (tab << TAB_SIZE_BITS) + index.base(); } std::string GetString(StringID string); diff --git a/src/strings_type.h b/src/strings_type.h index 49a0965d59..c99ea09580 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -10,6 +10,8 @@ #ifndef STRINGS_TYPE_H #define STRINGS_TYPE_H +#include "core/strong_typedef_type.hpp" + /** * Numeric value that represents a string, independent of the selected language. */ @@ -40,6 +42,9 @@ enum StringTab { TEXT_TAB_NEWGRF_START = 64, ///< Start of NewGRF supplied strings. }; +/** The index/offset of a string within a #StringTab. */ +using StringIndexInTab = StrongType::Typedef; + /** Number of bits for the StringIndex within a StringTab */ static const uint TAB_SIZE_BITS = 11; /** Number of strings per StringTab */