1
0
Fork 0

Codechange: Use std::array as simple string parameter container.

ArrayStringParameters contains extra state that is used when formatting strings which isn't needed when creating parameter lists.

MakeParameters() now returns a std::array which contains only the parameter data. This simpler container is more widely available than before.
pull/13480/head
Peter Nelson 2024-12-06 22:16:00 +00:00 committed by Peter Nelson
parent fb70a7fe7e
commit be00fd4447
6 changed files with 78 additions and 37 deletions

View File

@ -25,7 +25,7 @@
#include "newgrf_industrytiles.h"
#include "autoslope.h"
#include "water.h"
#include "strings_internal.h"
#include "strings_func.h"
#include "window_func.h"
#include "vehicle_func.h"
#include "sound_func.h"

View File

@ -28,7 +28,7 @@
#include "road_internal.h" /* For drawing catenary/checking road removal */
#include "autoslope.h"
#include "water.h"
#include "strings_internal.h"
#include "strings_func.h"
#include "clear_func.h"
#include "timer/timer_game_calendar.h"
#include "vehicle_func.h"

View File

@ -194,6 +194,22 @@ static bool GetSpecialNameString(StringBuilder &builder, StringID string, String
static void FormatString(StringBuilder &builder, const char *str, StringParameters &args, uint case_index = 0, bool game_script = false, bool dry_run = false);
/**
* Parse most format codes within a string and write the result to a buffer.
* This is a wrapper for a span of StringParameter which creates the StringParameters state and forwards to the regular call.
* @param builder The string builder to write the final string to.
* @param str Pointer to string to format.
* @param params The span of parameters to pass.
* @param case_index The current case index.
* @param game_script True when doing GameScript text processing.
* @param dry_run True when the args' type data is not yet initialized.
*/
static void FormatString(StringBuilder &builder, const char *str, std::span<StringParameter> params, uint case_index = 0, bool game_script = false, bool dry_run = false)
{
StringParameters tmp_params{params};
FormatString(builder, str, tmp_params, case_index, game_script, dry_run);
}
struct LanguagePack : public LanguagePackHeader {
char data[]; // list of strings
};
@ -322,6 +338,19 @@ void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters
FormatString(builder, GetStringPtr(string), args, case_index);
}
/**
* Get a parsed string with most special stringcodes replaced by the string parameters.
* @param builder The builder of the string.
* @param string The ID of the string to parse.
* @param args Span of arguments for the string.
* @param case_index The "case index". This will only be set when FormatString wants to print the string in a different case.
* @param game_script The string is coming directly from a game script.
*/
void GetStringWithArgs(StringBuilder &builder, StringID string, std::span<StringParameter> params, uint case_index, bool game_script)
{
StringParameters tmp_params{params};
GetStringWithArgs(builder, string, tmp_params, case_index, game_script);
}
/**
* Resolve the given StringID into a std::string with all the associated
@ -362,6 +391,14 @@ std::string GetStringWithArgs(StringID string, StringParameters &args)
return result;
}
std::string GetStringWithArgs(StringID string, std::span<StringParameter> args)
{
std::string result;
StringBuilder builder(result);
GetStringWithArgs(builder, string, args);
return result;
}
/**
* This function is used to "bind" a C string to a OpenTTD dparam slot.
* @param n slot of the string
@ -563,8 +600,7 @@ static void FormatGenericCurrency(StringBuilder &builder, const CurrencySpec *sp
if (StrEmpty(separator)) separator = _langpack.langpack->digit_group_separator_currency;
FormatNumber(builder, number, separator);
if (number_str != STR_NULL) {
auto tmp_params = ArrayStringParameters<0>();
FormatString(builder, GetStringPtr(number_str), tmp_params);
FormatString(builder, GetStringPtr(number_str), {});
}
/* Add suffix part, following symbol_pos specification.
@ -1559,8 +1595,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
}
}
auto tmp_params = ArrayStringParameters<0>();
GetStringWithArgs(builder, e->info.string_id, tmp_params);
GetStringWithArgs(builder, e->info.string_id, {});
break;
}
@ -1586,8 +1621,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
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 */
auto tmp_params = ArrayStringParameters<0>();
FormatString(builder, GetStringPtr(GetIndustrySpec(i->type)->name), tmp_params, next_substr_case_index);
FormatString(builder, GetStringPtr(GetIndustrySpec(i->type)->name), {}, next_substr_case_index);
} else if (use_cache) { // Use cached version if first call
AutoRestoreBackup cache_backup(use_cache, false);
builder += i->GetCachedName();
@ -1622,8 +1656,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
/* 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. */
auto tmp_params = ArrayStringParameters<0>();
GetStringWithArgs(builder, STR_UNKNOWN_STATION, tmp_params);
GetStringWithArgs(builder, STR_UNKNOWN_STATION, {});
break;
}
@ -1723,8 +1756,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
auto tmp_params = MakeParameters(si->name);
GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params);
} else {
auto tmp_params = ArrayStringParameters<0>();
GetStringWithArgs(builder, STR_DEFAULT_SIGN_NAME, tmp_params);
GetStringWithArgs(builder, STR_DEFAULT_SIGN_NAME, {});
}
break;
}

View File

@ -59,6 +59,7 @@ inline StringID MakeStringID(StringTab tab, StringIndexInTab index)
return (tab << TAB_SIZE_BITS) + index.base();
}
std::string GetStringWithArgs(StringID string, std::span<StringParameter> args);
std::string GetString(StringID string);
const char *GetStringPtr(StringID string);
void AppendStringInPlace(std::string &result, StringID string);
@ -109,6 +110,18 @@ void InitializeLanguagePacks();
const char *GetCurrentLanguageIsoCode();
std::string_view GetListSeparator();
/**
* 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 <typename... Args>
auto MakeParameters(Args &&... args)
{
return std::array<StringParameter, sizeof...(args)>({std::forward<StringParameter>(args)...});
}
/**
* A searcher for missing glyphs.
*/

View File

@ -13,12 +13,6 @@
#include "strings_func.h"
#include "string_func.h"
/** The data required to format and validate a single parameter of a string. */
struct StringParameter {
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'.
};
class StringParameters {
protected:
StringParameters *parent = nullptr; ///< If not nullptr, this instance references data from this parent instance.
@ -27,10 +21,6 @@ protected:
size_t offset = 0; ///< Current offset in the parameters span.
char32_t next_type = 0; ///< The type of the next data that is retrieved.
StringParameters(std::span<StringParameter> parameters = {}) :
parameters(parameters)
{}
const StringParameter &GetNextParameterReference();
public:
@ -43,6 +33,8 @@ public:
parameters(parent.parameters.subspan(parent.offset, size))
{}
StringParameters(std::span<StringParameter> parameters = {}) : parameters(parameters) {}
void PrepareForNextRun();
void SetTypeOfNextParameter(char32_t type) { this->next_type = type; }
@ -225,21 +217,6 @@ public:
ArrayStringParameters& operator=(const ArrayStringParameters &other) = delete;
};
/**
* 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 <typename... Args>
static auto MakeParameters(const Args&... args)
{
ArrayStringParameters<sizeof...(args)> parameters;
size_t index = 0;
(parameters.SetParam(index++, std::forward<const Args&>(args)), ...);
return parameters;
}
/**
* Equivalent to the std::back_insert_iterator in function, with some
* convenience helpers for string concatenation.
@ -339,6 +316,7 @@ public:
};
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index = 0, bool game_script = false);
void GetStringWithArgs(StringBuilder &builder, StringID string, std::span<StringParameter> params, uint case_index = 0, bool game_script = false);
std::string GetStringWithArgs(StringID string, StringParameters &args);
/* Do not leak the StringBuilder to everywhere. */

View File

@ -10,6 +10,7 @@
#ifndef STRINGS_TYPE_H
#define STRINGS_TYPE_H
#include "core/convertible_through_base.hpp"
#include "core/strong_typedef_type.hpp"
/**
@ -73,4 +74,21 @@ static constexpr StringID SPECSTR_PRESIDENT_NAME = 0x70E7; ///< Special string f
using StringParameterData = std::variant<uint64_t, std::string>;
/** The data required to format and validate a single parameter of a string. */
struct StringParameter {
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'.
StringParameter() = default;
inline StringParameter(StringParameterData &&data) : data(std::move(data)), type(0) {}
inline StringParameter(uint64_t data) : data(data), type(0) {}
inline StringParameter(const char *data) : data(std::string{data}), type(0) {}
inline StringParameter(std::string &&data) : data(std::move(data)), type(0) {}
inline StringParameter(const std::string &data) : data(data), type(0) {}
inline StringParameter(const ConvertibleThroughBase auto &data) : data(static_cast<uint64_t>(data.base())), type(0) {}
};
#endif /* STRINGS_TYPE_H */