diff --git a/src/error.h b/src/error.h index 0f1964fb80..f9480745f4 100644 --- a/src/error.h +++ b/src/error.h @@ -31,7 +31,7 @@ enum WarningLevel { class ErrorMessageData { protected: bool is_critical; ///< Whether the error message is critical. - std::vector params; ///< Backup of parameters of the message strings. + std::vector params; ///< Backup of parameters of the message strings. const GRFFile *textref_stack_grffile; ///< NewGRF that filled the #TextRefStack for the error message. uint textref_stack_size; ///< Number of uint32_t values to put on the #TextRefStack for the error message. uint32_t textref_stack[16]; ///< Values to put on the #TextRefStack for the error message. diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index 86e55c6c90..e2761fda4e 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -621,8 +621,8 @@ STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Kravas a STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Dienas ceļā STR_GRAPH_CARGO_PAYMENT_RATES_SECONDS :{TINY_FONT}{BLACK}Sekundes tranzītā STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Izmaksas par 10 vienību (vai 10,000 litru) kravas pārvadāšanu par 20 lauciņiem -STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Iespējot visu -STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Atspējot visu +STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Viss +STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Nav STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}Rādīt visas kravas samaksu salīdzināšanas diagrammā STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Nerādīt nevienu kravu samaksu salīdzināšanas diagrammā STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Paslēgt kravas veida diagrammu @@ -801,8 +801,8 @@ STR_SMALLMAP_INDUSTRY :{TINY_FONT}{STR STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} STR_SMALLMAP_COMPANY :{TINY_FONT}{COMPANY} STR_SMALLMAP_TOWN :{TINY_FONT}{WHITE}{TOWN} -STR_SMALLMAP_DISABLE_ALL :{BLACK}Atspējot visu -STR_SMALLMAP_ENABLE_ALL :{BLACK}Iespējot visu +STR_SMALLMAP_DISABLE_ALL :{BLACK}Neviena +STR_SMALLMAP_ENABLE_ALL :{BLACK}Viss STR_SMALLMAP_SHOW_HEIGHT :{BLACK}Rādīt augstumu STR_SMALLMAP_SHOW_INDUSTRY_NAMES :{BLACK}Rādīt ražotņu nosaukumus STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES :{BLACK}Nerādīt uz kartes ražotnes @@ -3905,6 +3905,7 @@ STR_COMPANY_VIEW_CAPTION :{WHITE}{COMPANY STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE :{WHITE}{PRESIDENT_NAME}{}{GOLD}(vadītājs) STR_COMPANY_VIEW_INAUGURATED_TITLE :{GOLD}Dibināts: {WHITE}{NUM} +STR_COMPANY_VIEW_INAUGURATED_TITLE_WALLCLOCK :{GOLD}Inaugurācija: {WHITE}{NUM} ({NUM}. period) STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE :{GOLD}Identitātes krāsu shēma STR_COMPANY_VIEW_VEHICLES_TITLE :{GOLD}Transportlīdzekļi: STR_COMPANY_VIEW_TRAINS :{WHITE}{COMMA} vilcien{P s i u} diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 5372833f0c..887e3169c9 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -620,8 +620,8 @@ STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Tarifas STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Dias em trânsito STR_GRAPH_CARGO_PAYMENT_RATES_SECONDS :{TINY_FONT}{BLACK}Segundos em trânsito STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Pagamento por entregar 10 unidades (ou 10 000 litros) de carga numa distância de 20 quadrados -STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Ativar tudo -STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Desativar tudo +STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Tudo +STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Nenhum STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}Mostrar todas as cargas no gráfico de tarifas por carga STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Não mostrar carga no gráfico de tarifas por carga STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Alternar o gráfico para este tipo de carga @@ -800,8 +800,8 @@ STR_SMALLMAP_INDUSTRY :{TINY_FONT}{STR STR_SMALLMAP_LINKSTATS :{TINY_FONT}{STRING} STR_SMALLMAP_COMPANY :{TINY_FONT}{COMPANY} STR_SMALLMAP_TOWN :{TINY_FONT}{WHITE}{TOWN} -STR_SMALLMAP_DISABLE_ALL :{BLACK}Desativar tudo -STR_SMALLMAP_ENABLE_ALL :{BLACK}Ativar tudo +STR_SMALLMAP_DISABLE_ALL :{BLACK}Nenhum +STR_SMALLMAP_ENABLE_ALL :{BLACK}Tudo STR_SMALLMAP_SHOW_HEIGHT :{BLACK}Mostrar altura STR_SMALLMAP_SHOW_INDUSTRY_NAMES :{BLACK}Mostrar nomes das indústrias STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES :{BLACK}Não mostrar indústrias no mapa diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index cb97d7c8c3..f77caa42e0 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -668,7 +668,7 @@ static WindowDesc _tool_tips_desc( struct TooltipsWindow : public Window { StringID string_id; ///< String to display as tooltip. - std::vector params; ///< The string parameters. + std::vector params; ///< The string parameters. TooltipCloseCondition close_cond; ///< Condition for closing the window. TooltipsWindow(Window *parent, StringID str, uint paramcount, TooltipCloseCondition close_tooltip) : Window(_tool_tips_desc) @@ -1089,7 +1089,7 @@ void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *paren */ struct QueryWindow : public Window { QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise - std::vector params; ///< local copy of #_global_string_params + std::vector params; ///< local copy of #_global_string_params StringID message; ///< message shown for query window QueryWindow(WindowDesc &desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc) diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index bef7e61c5a..8a307b2640 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -125,7 +125,7 @@ uint32_t GetPlatformInfo(Axis axis, uint8_t tile, int platforms, int length, int } SB(retval, 16, 4, std::min(15, length)); SB(retval, 20, 4, std::min(15, platforms)); - SB(retval, 24, 4, tile); + SB(retval, 24, 8, tile); return retval; } diff --git a/src/news_gui.cpp b/src/news_gui.cpp index c5aedecbf6..3ba464b0e5 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -296,7 +296,7 @@ struct NewsWindow : Window { this->CreateNestedTree(); /* For company news with a face we have a separate headline in param[0] */ - if (&desc == &_company_news_desc) this->GetWidget(WID_N_TITLE)->widget_data = this->ni->params[0].data; + if (&desc == &_company_news_desc) this->GetWidget(WID_N_TITLE)->widget_data = std::get(this->ni->params[0]); NWidgetCore *nwid = this->GetWidget(WID_N_SHOW_GROUP); if (ni->reftype1 == NR_VEHICLE && nwid != nullptr) { @@ -603,7 +603,7 @@ private: { /* Company news with a face have a separate headline, so the normal message is shifted by two params */ CopyInDParam(std::span(this->ni->params.data() + 2, this->ni->params.size() - 2)); - return this->ni->params[1].data; + return std::get(this->ni->params[1]); } StringID GetNewVehicleMessageString(WidgetID widget) const @@ -986,7 +986,7 @@ void ChangeVehicleNews(VehicleID from_index, VehicleID to_index) for (auto &ni : _news) { if (ni.reftype1 == NR_VEHICLE && ni.ref1 == from_index) ni.ref1 = to_index; if (ni.reftype2 == NR_VEHICLE && ni.ref2 == from_index) ni.ref2 = to_index; - if (ni.flags & NF_VEHICLE_PARAM0 && ni.params[0].data == from_index) ni.params[0] = to_index; + if (ni.flags & NF_VEHICLE_PARAM0 && std::get(ni.params[0]) == from_index) ni.params[0] = to_index; } } diff --git a/src/news_type.h b/src/news_type.h index cbafbef1ce..a83402f382 100644 --- a/src/news_type.h +++ b/src/news_type.h @@ -139,7 +139,7 @@ struct NewsItem { std::unique_ptr data; ///< Custom data for the news item that will be deallocated (deleted) when the news item has reached its end. - std::vector params; ///< Parameters for string resolving. + std::vector params; ///< Parameters for string resolving. NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data); }; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 8e49af0eed..5abf18157b 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -441,6 +441,38 @@ public: void LoadCheck(CompanyProperties *c) const override { this->Load(c); } }; +class SlAllowListData : public DefaultSaveLoadHandler { +public: + struct KeyWrapper { + std::string key; + }; + + inline static const SaveLoad description[] = { + SLE_SSTR(KeyWrapper, key, SLE_STR), + }; + inline const static SaveLoadCompatTable compat_description = {}; + + void Save(CompanyProperties *cprops) const override + { + SlSetStructListLength(cprops->allow_list.size()); + for (std::string &str : cprops->allow_list) { + SlObject(&str, this->GetDescription()); + } + } + + void Load(CompanyProperties *cprops) const override + { + size_t num_keys = SlGetStructListLength(UINT32_MAX); + cprops->allow_list.clear(); + cprops->allow_list.resize(num_keys); + for (std::string &str : cprops->allow_list) { + SlObject(&str, this->GetLoadDescription()); + } + } + + void LoadCheck(CompanyProperties *cprops) const override { this->Load(cprops); } +}; + /* Save/load of companies */ static const SaveLoad _company_desc[] = { SLE_VAR(CompanyProperties, name_2, SLE_UINT32), @@ -451,7 +483,8 @@ static const SaveLoad _company_desc[] = { SLE_VAR(CompanyProperties, president_name_2, SLE_UINT32), SLE_CONDSSTR(CompanyProperties, president_name, SLE_STR | SLF_ALLOW_CONTROL, SLV_84, SL_MAX_VERSION), - SLE_CONDVECTOR(CompanyProperties, allow_list, SLE_STR, SLV_COMPANY_ALLOW_LIST, SL_MAX_VERSION), + SLE_CONDVECTOR(CompanyProperties, allow_list, SLE_STR, SLV_COMPANY_ALLOW_LIST, SLV_COMPANY_ALLOW_LIST_V2), + SLEG_CONDSTRUCTLIST("allow_list", SlAllowListData, SLV_COMPANY_ALLOW_LIST_V2, SL_MAX_VERSION), SLE_VAR(CompanyProperties, face, SLE_UINT32), diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 81852f7cf8..68019e8dab 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1246,17 +1246,13 @@ public: */ static size_t SlCalcLen(const void *storage, VarType conv, SaveLoadType cmd = SL_VAR) { - assert(cmd == SL_VAR || cmd == SL_REF || cmd == SL_STDSTR); + assert(cmd == SL_VAR || cmd == SL_REF); const SlStorageT *list = static_cast(storage); - size_t type_size = SlGetArrayLength(list->size()); - if constexpr (std::is_same_v, SlStorageT> || std::is_same_v, SlStorageT>) { - return std::accumulate(list->begin(), list->end(), type_size, [](size_t sum, const std::string &str) { return sum + SlCalcStdStringLen(&str); }); - } else { - size_t item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); - return list->size() * item_size + type_size; - } + int type_size = SlGetArrayLength(list->size()); + int item_size = SlCalcConvFileLen(cmd == SL_VAR ? conv : (VarType)SLE_FILE_U32); + return list->size() * item_size + type_size; } static void SlSaveLoadMember(SaveLoadType cmd, Tvar *item, VarType conv) @@ -1368,7 +1364,12 @@ static inline size_t SlCalcDequeLen(const void *deque, VarType conv) case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(deque, conv); case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(deque, conv); case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(deque, conv); - case SLE_VAR_STR: return SlStorageHelper::SlCalcLen(deque, conv, SL_STDSTR); + + case SLE_VAR_STR: + /* Strings are a length-prefixed field type in the savegame table format, + * these may not be directly stored in another length-prefixed container type. */ + NOT_REACHED(); + default: NOT_REACHED(); } } @@ -1390,7 +1391,16 @@ static void SlDeque(void *deque, VarType conv) case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(deque, conv); break; case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(deque, conv); break; case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(deque, conv); break; - case SLE_VAR_STR: SlStorageHelper::SlSaveLoad(deque, conv, SL_STDSTR); break; + + case SLE_VAR_STR: + /* Strings are a length-prefixed field type in the savegame table format, + * these may not be directly stored in another length-prefixed container type. + * This is permitted for load-related actions, because invalid fields of this type are present + * from SLV_COMPANY_ALLOW_LIST up to SLV_COMPANY_ALLOW_LIST_V2. */ + assert(_sl.action != SLA_SAVE); + SlStorageHelper::SlSaveLoad(deque, conv, SL_STDSTR); + break; + default: NOT_REACHED(); } } @@ -1412,7 +1422,12 @@ static inline size_t SlCalcVectorLen(const void *vector, VarType conv) case SLE_VAR_U32: return SlStorageHelper::SlCalcLen(vector, conv); case SLE_VAR_I64: return SlStorageHelper::SlCalcLen(vector, conv); case SLE_VAR_U64: return SlStorageHelper::SlCalcLen(vector, conv); - case SLE_VAR_STR: return SlStorageHelper::SlCalcLen(vector, conv, SL_STDSTR); + + case SLE_VAR_STR: + /* Strings are a length-prefixed field type in the savegame table format, + * these may not be directly stored in another length-prefixed container type. */ + NOT_REACHED(); + default: NOT_REACHED(); } } @@ -1434,7 +1449,16 @@ static void SlVector(void *vector, VarType conv) case SLE_VAR_U32: SlStorageHelper::SlSaveLoad(vector, conv); break; case SLE_VAR_I64: SlStorageHelper::SlSaveLoad(vector, conv); break; case SLE_VAR_U64: SlStorageHelper::SlSaveLoad(vector, conv); break; - case SLE_VAR_STR: SlStorageHelper::SlSaveLoad(vector, conv, SL_STDSTR); break; + + case SLE_VAR_STR: + /* Strings are a length-prefixed field type in the savegame table format, + * these may not be directly stored in another length-prefixed container type. + * This is permitted for load-related actions, because invalid fields of this type are present + * from SLV_COMPANY_ALLOW_LIST up to SLV_COMPANY_ALLOW_LIST_V2. */ + assert(_sl.action != SLA_SAVE); + SlStorageHelper::SlSaveLoad(vector, conv, SL_STDSTR); + break; + default: NOT_REACHED(); } } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index 01cbbda828..d12fb00e02 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -386,6 +386,7 @@ enum SaveLoadVersion : uint16_t { SLV_COMPANY_INAUGURATED_PERIOD, ///< 339 PR#12798 Companies show the period inaugurated in wallclock mode. SLV_ROAD_STOP_TILE_DATA, ///< 340 PR#12883 Move storage of road stop tile data, also save for road waypoints. + SLV_COMPANY_ALLOW_LIST_V2, ///< 341 PR#12908 Fixed savegame format for saving of list of client keys that are allowed to join this company. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/strings.cpp b/src/strings.cpp index ac959f7ddd..61aefacdca 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -76,9 +76,9 @@ void StringParameters::PrepareForNextRun() * Get the next parameter from our parameters. * This updates the offset, so the next time this is called the next parameter * will be read. - * @return The pointer to the next parameter. + * @return The next parameter. */ -StringParameter *StringParameters::GetNextParameterPointer() +const StringParameter &StringParameters::GetNextParameterReference() { assert(this->next_type == 0 || (SCC_CONTROL_START <= this->next_type && this->next_type <= SCC_CONTROL_END)); if (this->offset >= this->parameters.size()) { @@ -92,7 +92,7 @@ StringParameter *StringParameters::GetNextParameterPointer() } param.type = this->next_type; this->next_type = 0; - return ¶m; + return param; } @@ -113,7 +113,7 @@ void SetDParam(size_t n, uint64_t v) */ uint64_t GetDParam(size_t n) { - return _global_string_params.GetParam(n); + return std::get(_global_string_params.GetParam(n)); } /** @@ -156,15 +156,10 @@ void SetDParamMaxDigits(size_t n, uint count, FontSize size) * Copy the parameters from the backup into the global string parameter array. * @param backup The backup to copy from. */ -void CopyInDParam(const std::span backup) +void CopyInDParam(const std::span backup) { for (size_t i = 0; i < backup.size(); i++) { - auto &value = backup[i]; - if (value.string.has_value()) { - _global_string_params.SetParam(i, value.string.value()); - } else { - _global_string_params.SetParam(i, value.data); - } + _global_string_params.SetParam(i, backup[i]); } } @@ -173,16 +168,11 @@ void CopyInDParam(const std::span backup) * @param backup The backup to write to. * @param num Number of string parameters to copy. */ -void CopyOutDParam(std::vector &backup, size_t num) +void CopyOutDParam(std::vector &backup, size_t num) { backup.resize(num); for (size_t i = 0; i < backup.size(); i++) { - const char *str = _global_string_params.GetParamStr(i); - if (str != nullptr) { - backup[i] = str; - } else { - backup[i] = _global_string_params.GetParam(i); - } + backup[i] = _global_string_params.GetParam(i); } } @@ -191,20 +181,12 @@ void CopyOutDParam(std::vector &backup, size_t num) * @param backup The backup to check against. * @return True when the parameters have changed, otherwise false. */ -bool HaveDParamChanged(const std::vector &backup) +bool HaveDParamChanged(const std::span backup) { - bool changed = false; - for (size_t i = 0; !changed && i < backup.size(); i++) { - bool global_has_string = _global_string_params.GetParamStr(i) != nullptr; - if (global_has_string != backup[i].string.has_value()) return true; - - if (global_has_string) { - changed = backup[i].string.value() != _global_string_params.GetParamStr(i); - } else { - changed = backup[i].data != _global_string_params.GetParam(i); - } + for (size_t i = 0; i < backup.size(); i++) { + if (backup[i] != _global_string_params.GetParam(i)) return true; } - return changed; + return false; } static void StationGetSpecialString(StringBuilder &builder, StationFacility x); @@ -271,14 +253,24 @@ void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters switch (tab) { case TEXT_TAB_TOWN: if (index >= 0xC0 && !game_script) { - GetSpecialTownNameString(builder, index - 0xC0, args.GetNextParameter()); + try { + GetSpecialTownNameString(builder, index - 0xC0, args.GetNextParameter()); + } catch (const std::runtime_error &e) { + Debug(misc, 0, "GetStringWithArgs: {}", e.what()); + builder += "(invalid string parameter)"; + } return; } break; case TEXT_TAB_SPECIAL: if (index >= 0xE4 && !game_script) { - GetSpecialNameString(builder, index - 0xE4, args); + try { + GetSpecialNameString(builder, index - 0xE4, args); + } catch (const std::runtime_error &e) { + Debug(misc, 0, "GetStringWithArgs: {}", e.what()); + builder += "(invalid string parameter)"; + } return; } break; @@ -1106,7 +1098,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_PLURAL_LIST: { // {P} int plural_form = *str++; // contains the plural form for this string size_t offset = orig_offset + (uint8_t)*str++; - int64_t v = args.GetParam(offset); // contains the number that determines plural + int64_t v = std::get(args.GetParam(offset)); // contains the number that determines plural str = ParseStringChoice(str, DeterminePluralForm(v, plural_form), builder); break; } diff --git a/src/strings_func.h b/src/strings_func.h index 21a77705d8..3ee91a0af5 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -98,9 +98,9 @@ void SetDParamStr(size_t n, const char *str); void SetDParamStr(size_t n, const std::string &str); void SetDParamStr(size_t n, std::string &&str); -void CopyInDParam(const std::span backup); -void CopyOutDParam(std::vector &backup, size_t num); -bool HaveDParamChanged(const std::vector &backup); +void CopyInDParam(const std::span backup); +void CopyOutDParam(std::vector &backup, size_t num); +bool HaveDParamChanged(const std::span backup); uint64_t GetDParam(size_t n); diff --git a/src/strings_internal.h b/src/strings_internal.h index 3095e33107..4d6b1a5b7e 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -15,8 +15,7 @@ /** The data required to format and validate a single parameter of a string. */ struct StringParameter { - uint64_t data; ///< The data of the parameter. - std::unique_ptr string; ///< Copied string value, if it has any. + StringParameterData data; ///< The data of the parameter. char32_t type; ///< The #StringControlCode to interpret this data with when it's the first parameter, otherwise '\0'. }; @@ -32,7 +31,7 @@ protected: parameters(parameters) {} - StringParameter *GetNextParameterPointer(); + const StringParameter &GetNextParameterReference(); public: /** @@ -92,8 +91,10 @@ public: template T GetNextParameter() { - auto ptr = GetNextParameterPointer(); - return static_cast(ptr->data); + const auto ¶m = GetNextParameterReference(); + const uint64_t *data = std::get_if(¶m.data); + if (data != nullptr) return static_cast(*data); + throw std::runtime_error("Attempt to read string parameter as integer"); } /** @@ -104,8 +105,10 @@ public: */ const char *GetNextParameterString() { - auto ptr = GetNextParameterPointer(); - return ptr->string != nullptr ? ptr->string->c_str() : nullptr; + const auto ¶m = GetNextParameterReference(); + const std::string *data = std::get_if(¶m.data); + if (data != nullptr) return data->c_str(); + throw std::runtime_error("Attempt to read integer parameter as string"); } /** @@ -146,11 +149,16 @@ public: return this->parameters[offset].type; } + void SetParam(size_t n, const StringParameterData &v) + { + assert(n < this->parameters.size()); + this->parameters[n].data = v; + } + void SetParam(size_t n, uint64_t v) { assert(n < this->parameters.size()); this->parameters[n].data = v; - this->parameters[n].string.reset(); } template ::value, int> = 0> @@ -162,8 +170,7 @@ public: void SetParam(size_t n, const char *str) { assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string = std::make_unique(str); + this->parameters[n].data = str; } void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } @@ -171,28 +178,14 @@ public: void SetParam(size_t n, std::string &&str) { assert(n < this->parameters.size()); - this->parameters[n].data = 0; - this->parameters[n].string = std::make_unique(std::move(str)); + this->parameters[n].data = std::move(str); } - uint64_t GetParam(size_t n) const + const StringParameterData &GetParam(size_t n) const { assert(n < this->parameters.size()); - assert(this->parameters[n].string == nullptr); return this->parameters[n].data; } - - /** - * Get the stored string of the parameter, or \c nullptr when there is none. - * @param n The index into the parameters. - * @return The stored string. - */ - const char *GetParamStr(size_t n) const - { - assert(n < this->parameters.size()); - auto ¶m = this->parameters[n]; - return param.string != nullptr ? param.string->c_str() : nullptr; - } }; /** diff --git a/src/strings_type.h b/src/strings_type.h index 5e6d715b63..49a0965d59 100644 --- a/src/strings_type.h +++ b/src/strings_type.h @@ -88,34 +88,6 @@ enum SpecialStrings { SPECSTR_PRESIDENT_NAME = 0x70E7, }; -/** Data that is to be stored when backing up StringParameters. */ -struct StringParameterBackup { - uint64_t data; ///< The data field; valid *when* string has no value. - std::optional string; ///< The string value. - - /** - * Assign the numeric data with the given value, while clearing the stored string. - * @param data The new value of the data field. - * @return This object. - */ - StringParameterBackup &operator=(uint64_t data) - { - this->string.reset(); - this->data = data; - return *this; - } - - /** - * Assign a copy of the given string to the string field, while clearing the data field. - * @param string The new value of the string. - * @return This object. - */ - StringParameterBackup &operator=(const std::string_view string) - { - this->data = 0; - this->string.emplace(string); - return *this; - } -}; +using StringParameterData = std::variant; #endif /* STRINGS_TYPE_H */ diff --git a/src/tests/strings_func.cpp b/src/tests/strings_func.cpp index dd70b0a365..f82cdd92be 100644 --- a/src/tests/strings_func.cpp +++ b/src/tests/strings_func.cpp @@ -18,7 +18,7 @@ TEST_CASE("HaveDParamChanged") SetDParam(0, 0); SetDParamStr(1, "some string"); - std::vector backup; + std::vector backup; CopyOutDParam(backup, 2); CHECK(HaveDParamChanged(backup) == false); diff --git a/src/texteff.cpp b/src/texteff.cpp index 10b276232e..fbec86d04f 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -21,7 +21,7 @@ /** Container for all information about a text effect */ struct TextEffect : public ViewportSign { - std::vector params; ///< Backup of string parameters + std::vector params; ///< Backup of string parameters StringID string_id; ///< String to draw for the text effect, if INVALID_STRING_ID then it's not valid uint8_t duration; ///< How long the text effect should stay, in ticks (applies only when mode == TE_RISING) TextEffectMode mode; ///< Type of text effect