diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2431,8 +2431,7 @@ void Industry::RecomputeProductionMultip void Industry::FillCachedName() const { - int64 args_array[] = { this->index }; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(this->index); this->cached_name = GetStringWithArgs(STR_INDUSTRY_NAME, tmp_params); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -461,8 +461,7 @@ void UpdateAllStationVirtCoords() void BaseStation::FillCachedName() const { - int64 args_array[] = { this->index }; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(this->index); this->cached_name = GetStringWithArgs(Waypoint::IsExpected(this) ? STR_WAYPOINT_NAME : STR_STATION_NAME, tmp_params); } diff --git a/src/strings.cpp b/src/strings.cpp --- a/src/strings.cpp +++ b/src/strings.cpp @@ -339,7 +339,7 @@ std::string GetStringWithArgs(StringID s */ void SetDParamStr(size_t n, const char *str) { - SetDParam(n, (uint64)(size_t)str); + _global_string_params.SetParam(n, str); } /** @@ -350,7 +350,7 @@ void SetDParamStr(size_t n, const char * */ void SetDParamStr(size_t n, const std::string &str) { - SetDParamStr(n, str.c_str()); + _global_string_params.SetParam(n, str); } /** @@ -461,8 +461,7 @@ static void FormatYmdString(StringBuilde TimerGameCalendar::YearMonthDay ymd; TimerGameCalendar::ConvertDateToYMD(date, &ymd); - int64 args[] = {ymd.day + STR_DAY_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.month, ymd.year}; - StringParameters tmp_params(args); + auto tmp_params = MakeParameters(ymd.day + STR_DAY_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.month, ymd.year); FormatString(builder, GetStringPtr(STR_FORMAT_DATE_LONG), tmp_params, case_index); } @@ -471,8 +470,7 @@ static void FormatMonthAndYear(StringBui TimerGameCalendar::YearMonthDay ymd; TimerGameCalendar::ConvertDateToYMD(date, &ymd); - int64 args[] = {STR_MONTH_JAN + ymd.month, ymd.year}; - StringParameters tmp_params(args); + auto tmp_params = MakeParameters(STR_MONTH_JAN + ymd.month, ymd.year); FormatString(builder, GetStringPtr(STR_FORMAT_DATE_SHORT), tmp_params, case_index); } @@ -482,8 +480,7 @@ static void FormatTinyOrISODate(StringBu TimerGameCalendar::ConvertDateToYMD(date, &ymd); /* Day and month are zero-padded with ZEROFILL_NUM, hence the two 2s. */ - int64 args[] = {ymd.day, 2, ymd.month + 1, 2, ymd.year}; - StringParameters tmp_params(args); + auto tmp_params = MakeParameters(ymd.day, 2, ymd.month + 1, 2, ymd.year); FormatString(builder, GetStringPtr(str), tmp_params); } @@ -1213,16 +1210,14 @@ static void FormatString(StringBuilder & switch (cargo_str) { case STR_TONS: { assert(_settings_game.locale.units_weight < lengthof(_units_weight)); - int64 args_array[] = {_units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetInt64())}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(_units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetInt64())); FormatString(builder, GetStringPtr(_units_weight[_settings_game.locale.units_weight].l), tmp_params); break; } case STR_LITERS: { assert(_settings_game.locale.units_volume < lengthof(_units_volume)); - int64 args_array[] = {_units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetInt64())}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(_units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetInt64())); FormatString(builder, GetStringPtr(_units_volume[_settings_game.locale.units_volume].l), tmp_params); break; } @@ -1300,8 +1295,7 @@ static void FormatString(StringBuilder & case SCC_FORCE: { // {FORCE} assert(_settings_game.locale.units_force < lengthof(_units_force)); const auto &x = _units_force[_settings_game.locale.units_force]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1309,8 +1303,7 @@ static void FormatString(StringBuilder & case SCC_HEIGHT: { // {HEIGHT} assert(_settings_game.locale.units_height < lengthof(_units_height)); const auto &x = _units_height[_settings_game.locale.units_height]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1318,8 +1311,7 @@ static void FormatString(StringBuilder & case SCC_POWER: { // {POWER} assert(_settings_game.locale.units_power < lengthof(_units_power)); const auto &x = _units_power[_settings_game.locale.units_power]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1328,8 +1320,7 @@ static void FormatString(StringBuilder & auto setting = _settings_game.locale.units_power * 3u + _settings_game.locale.units_weight; assert(setting < lengthof(_units_power_to_weight)); const auto &x = _units_power_to_weight[setting]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1341,8 +1332,7 @@ static void FormatString(StringBuilder & byte units = GetVelocityUnits(vt); assert(units < lengthof(_units_velocity)); const auto &x = _units_velocity[units]; - int64 args_array[] = {ConvertKmhishSpeedToDisplaySpeed(GB(arg, 0, 56), vt), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(ConvertKmhishSpeedToDisplaySpeed(GB(arg, 0, 56), vt), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1350,8 +1340,7 @@ static void FormatString(StringBuilder & case SCC_VOLUME_SHORT: { // {VOLUME_SHORT} assert(_settings_game.locale.units_volume < lengthof(_units_volume)); const auto &x = _units_volume[_settings_game.locale.units_volume]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1359,8 +1348,7 @@ static void FormatString(StringBuilder & case SCC_VOLUME_LONG: { // {VOLUME_LONG} assert(_settings_game.locale.units_volume < lengthof(_units_volume)); const auto &x = _units_volume[_settings_game.locale.units_volume]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.l), tmp_params); break; } @@ -1368,8 +1356,7 @@ static void FormatString(StringBuilder & case SCC_WEIGHT_SHORT: { // {WEIGHT_SHORT} assert(_settings_game.locale.units_weight < lengthof(_units_weight)); const auto &x = _units_weight[_settings_game.locale.units_weight]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1377,8 +1364,7 @@ static void FormatString(StringBuilder & case SCC_WEIGHT_LONG: { // {WEIGHT_LONG} assert(_settings_game.locale.units_weight < lengthof(_units_weight)); const auto &x = _units_weight[_settings_game.locale.units_weight]; - int64 args_array[] = {x.c.ToDisplay(args.GetInt64()), x.decimal_places}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); FormatString(builder, GetStringPtr(x.l), tmp_params); break; } @@ -1388,12 +1374,10 @@ static void FormatString(StringBuilder & if (c == nullptr) break; if (!c->name.empty()) { - int64 args_array[] = {(int64)(size_t)c->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(c->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - int64 args_array[] = {c->name_2}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(c->name_2); GetStringWithArgs(builder, c->name_1, tmp_params); } break; @@ -1404,8 +1388,7 @@ static void FormatString(StringBuilder & /* Nothing is added for AI or inactive companies */ if (Company::IsValidHumanID(company)) { - int64 args_array[] = {company + 1}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(company + 1); GetStringWithArgs(builder, STR_FORMAT_COMPANY_NUM, tmp_params); } break; @@ -1423,12 +1406,10 @@ static void FormatString(StringBuilder & const Depot *d = Depot::Get(args.GetInt32()); if (!d->name.empty()) { - int64 args_array[] = {(int64)(size_t)d->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(d->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - int64 args_array[] = {d->town->index, d->town_cn + 1}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(d->town->index, d->town_cn + 1); GetStringWithArgs(builder, STR_FORMAT_DEPOT_NAME_TRAIN + 2 * vt + (d->town_cn == 0 ? 0 : 1), tmp_params); } break; @@ -1440,10 +1421,8 @@ static void FormatString(StringBuilder & if (e == nullptr) break; if (!e->name.empty() && e->IsEnabled()) { - int64 args_array[] = {(int64)(size_t)e->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(e->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); - break; } @@ -1465,7 +1444,7 @@ static void FormatString(StringBuilder & } } - StringParameters tmp_params(nullptr, 0, nullptr); + auto tmp_params = AllocatedStringParameters(); GetStringWithArgs(builder, e->info.string_id, tmp_params); break; } @@ -1475,13 +1454,10 @@ static void FormatString(StringBuilder & if (g == nullptr) break; if (!g->name.empty()) { - int64 args_array[] = {(int64)(size_t)g->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(g->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - int64 args_array[] = {g->index}; - StringParameters tmp_params(args_array); - + auto tmp_params = MakeParameters(g->index); GetStringWithArgs(builder, STR_FORMAT_GROUP_NAME, tmp_params); } break; @@ -1498,13 +1474,11 @@ static void FormatString(StringBuilder & } else if (_scan_for_gender_data) { /* Gender is defined by the industry type. * STR_FORMAT_INDUSTRY_NAME may have the town first, so it would result in the gender of the town name */ - StringParameters tmp_params(nullptr, 0, nullptr); + auto tmp_params = AllocatedStringParameters(); FormatString(builder, GetStringPtr(GetIndustrySpec(i->type)->name), tmp_params, next_substr_case_index); } else { /* First print the town name and the industry type name. */ - int64 args_array[2] = {i->town->index, GetIndustrySpec(i->type)->name}; - StringParameters tmp_params(args_array); - + auto tmp_params = MakeParameters(i->town->index, GetIndustrySpec(i->type)->name); FormatString(builder, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), tmp_params, next_substr_case_index); } next_substr_case_index = 0; @@ -1516,12 +1490,10 @@ static void FormatString(StringBuilder & if (c == nullptr) break; if (!c->president_name.empty()) { - int64 args_array[] = {(int64)(size_t)c->president_name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(c->president_name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - int64 args_array[] = {c->president_name_2}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(c->president_name_2); GetStringWithArgs(builder, c->president_name_1, tmp_params); } break; @@ -1535,7 +1507,7 @@ static void FormatString(StringBuilder & /* The station doesn't exist anymore. The only place where we might * be "drawing" an invalid station is in the case of cargo that is * in transit. */ - StringParameters tmp_params(nullptr, 0, nullptr); + auto tmp_params = AllocatedStringParameters(); GetStringWithArgs(builder, STR_UNKNOWN_STATION, tmp_params); break; } @@ -1545,8 +1517,7 @@ static void FormatString(StringBuilder & AutoRestoreBackup cache_backup(use_cache, false); builder += st->GetCachedName(); } else if (!st->name.empty()) { - int64 args_array[] = {(int64)(size_t)st->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(st->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { StringID string_id = st->string_id; @@ -1579,8 +1550,7 @@ static void FormatString(StringBuilder & AutoRestoreBackup cache_backup(use_cache, false); builder += t->GetCachedName(); } else if (!t->name.empty()) { - int64 args_array[] = {(int64)(size_t)t->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(t->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { GetTownName(builder, t); @@ -1593,12 +1563,10 @@ static void FormatString(StringBuilder & if (wp == nullptr) break; if (!wp->name.empty()) { - int64 args_array[] = {(int64)(size_t)wp->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(wp->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - int64 args_array[] = {wp->town->index, wp->town_cn + 1}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(wp->town->index, wp->town_cn + 1); StringID string_id = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME); if (wp->town_cn != 0) string_id++; GetStringWithArgs(builder, string_id, tmp_params); @@ -1611,17 +1579,14 @@ static void FormatString(StringBuilder & if (v == nullptr) break; if (!v->name.empty()) { - int64 args_array[] = {(int64)(size_t)v->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(v->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else if (v->group_id != DEFAULT_GROUP) { /* The vehicle has no name, but is member of a group, so print group name */ - int64 args_array[] = {v->group_id, v->unitnumber}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(v->group_id, v->unitnumber); GetStringWithArgs(builder, STR_FORMAT_GROUP_VEHICLE_NAME, tmp_params); } else { - int64 args_array[] = {v->unitnumber}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(v->unitnumber); StringID string_id; switch (v->type) { @@ -1642,11 +1607,10 @@ static void FormatString(StringBuilder & if (si == nullptr) break; if (!si->name.empty()) { - int64 args_array[] = {(int64)(size_t)si->name.c_str()}; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(si->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); } else { - StringParameters tmp_params(nullptr, 0, nullptr); + auto tmp_params = AllocatedStringParameters(); GetStringWithArgs(builder, STR_DEFAULT_SIGN_NAME, tmp_params); } break; diff --git a/src/strings_internal.h b/src/strings_internal.h --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -14,6 +14,7 @@ #include "string_func.h" class StringParameters { +protected: StringParameters *parent; ///< If not nullptr, this instance references data from this parent instance. uint64 *data; ///< Array with the actual data. WChar *type; ///< Array with type information about the data. Can be nullptr when no type information is needed. See #StringControlCode. @@ -31,18 +32,6 @@ public: num_param(num_param) { } - /** Create a new StringParameters instance. */ - template - StringParameters(int64 (&data)[Tnum_param]) : - parent(nullptr), - data((uint64 *)data), - type(nullptr), - offset(0), - num_param(Tnum_param) - { - static_assert(sizeof(data[0]) == sizeof(uint64)); - } - /** * Create a new StringParameters instance that can reference part of the data of * the given partent instance. @@ -136,6 +125,10 @@ public: this->data[n] = v; } + void SetParam(size_t n, const char *str) { this->SetParam(n, (uint64_t)(size_t)str); } + void SetParam(size_t n, const std::string &str) { this->SetParam(n, str.c_str()); } + void SetParam(size_t n, std::string &&str) = delete; // block passing temporaries to SetDParam + uint64 GetParam(size_t n) const { assert(n < this->num_param); @@ -144,6 +137,35 @@ public: }; /** + * Extension of StringParameters with its own statically allocated buffer for + * the parameters. + */ +class AllocatedStringParameters : public StringParameters { + std::vector params; ///< The actual parameters + +public: + AllocatedStringParameters(size_t parameters = 0) : StringParameters(nullptr, parameters, nullptr), params(parameters) + { + this->data = params.data(); + } +}; + +/** + * Helper to create the StringParameters with its own buffer with the given + * parameter values. + * @param args The parameters to set for the to be created StringParameters. + * @return The constructed StringParameters. + */ +template +static auto MakeParameters(const Args&... args) +{ + AllocatedStringParameters parameters(sizeof...(args)); + size_t index = 0; + (parameters.SetParam(index++, std::forward(args)), ...); + return parameters; +} + +/** * Equivalent to the std::back_insert_iterator in function, with some * convenience helpers for string concatenation. */ diff --git a/src/townname.cpp b/src/townname.cpp --- a/src/townname.cpp +++ b/src/townname.cpp @@ -48,8 +48,7 @@ TownNameParams::TownNameParams(const Tow static void GetTownName(StringBuilder &builder, const TownNameParams *par, uint32 townnameparts) { if (par->grfid == 0) { - int64 args_array[1] = { townnameparts }; - StringParameters tmp_params(args_array); + auto tmp_params = MakeParameters(townnameparts); GetStringWithArgs(builder, par->type, tmp_params); return; }