mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Pass unformatted strings from GetStringPtr as std::string_view. (#13871)
parent
234c9fb3bd
commit
5aa4ad5135
|
@ -315,10 +315,10 @@ GameStrings *_current_data = nullptr;
|
|||
* @param id The ID of the game string.
|
||||
* @return The encoded string.
|
||||
*/
|
||||
const char *GetGameStringPtr(StringIndexInTab id)
|
||||
std::string_view GetGameStringPtr(StringIndexInTab id)
|
||||
{
|
||||
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].c_str();
|
||||
return _current_data->cur_language->lines[id];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ struct StringParam {
|
|||
using StringParams = std::vector<StringParam>;
|
||||
using StringParamsList = std::vector<StringParams>;
|
||||
|
||||
const char *GetGameStringPtr(StringIndexInTab id);
|
||||
std::string_view GetGameStringPtr(StringIndexInTab id);
|
||||
const StringParams &GetGameStringParams(StringIndexInTab id);
|
||||
const std::string &GetGameStringName(StringIndexInTab id);
|
||||
void RegisterGameTranslation(class Squirrel *engine);
|
||||
|
|
|
@ -84,8 +84,8 @@ void GRFConfig::CopyParams(const GRFConfig &src)
|
|||
*/
|
||||
std::string GRFConfig::GetName() const
|
||||
{
|
||||
const char *name = GetGRFStringFromGRFText(this->name);
|
||||
return StrEmpty(name) ? this->filename : name;
|
||||
auto name = GetGRFStringFromGRFText(this->name);
|
||||
return name.has_value() ? std::string(*name) : this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,9 +94,9 @@ std::string GRFConfig::GetName() const
|
|||
*/
|
||||
std::optional<std::string> GRFConfig::GetDescription() const
|
||||
{
|
||||
const char *str = GetGRFStringFromGRFText(this->info);
|
||||
if (StrEmpty(str)) return std::nullopt;
|
||||
return std::string(str);
|
||||
auto str = GetGRFStringFromGRFText(this->info);
|
||||
if (!str.has_value()) return std::nullopt;
|
||||
return std::string(*str);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,9 +105,9 @@ std::optional<std::string> GRFConfig::GetDescription() const
|
|||
*/
|
||||
std::optional<std::string> GRFConfig::GetURL() const
|
||||
{
|
||||
const char *str = GetGRFStringFromGRFText(this->url);
|
||||
if (StrEmpty(str)) return std::nullopt;
|
||||
return std::string(str);
|
||||
auto str = GetGRFStringFromGRFText(this->url);
|
||||
if (!str.has_value()) return std::nullopt;
|
||||
return std::string(*str);
|
||||
}
|
||||
|
||||
/** Set the default value for all parameters as specified by action14. */
|
||||
|
|
|
@ -232,9 +232,9 @@ struct NewGRFParametersWindow : public Window {
|
|||
Dimension suggestion = {500U - WidgetDimensions::scaled.frametext.Horizontal(), (uint)GetCharacterHeight(FS_NORMAL) * 4 + WidgetDimensions::scaled.frametext.Vertical()};
|
||||
for (const auto &par_info : this->grf_config.param_info) {
|
||||
if (!par_info.has_value()) continue;
|
||||
const char *desc = GetGRFStringFromGRFText(par_info->desc);
|
||||
if (desc == nullptr) continue;
|
||||
Dimension d = GetStringMultiLineBoundingBox(desc, suggestion);
|
||||
auto desc = GetGRFStringFromGRFText(par_info->desc);
|
||||
if (!desc.has_value()) continue;
|
||||
Dimension d = GetStringMultiLineBoundingBox(*desc, suggestion);
|
||||
d.height += WidgetDimensions::scaled.frametext.Vertical();
|
||||
suggestion = maxdim(d, suggestion);
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ struct NewGRFParametersWindow : public Window {
|
|||
|
||||
auto it = std::ranges::lower_bound(par_info.value_names, value, std::less{}, &GRFParameterInfo::ValueName::first);
|
||||
if (it != std::end(par_info.value_names) && it->first == value) {
|
||||
if (const char *label = GetGRFStringFromGRFText(it->second); label != nullptr) return {STR_JUST_RAW_STRING, label};
|
||||
if (auto label = GetGRFStringFromGRFText(it->second); label.has_value()) return {STR_JUST_RAW_STRING, std::string(*label)};
|
||||
}
|
||||
|
||||
return {STR_JUST_INT, value};
|
||||
|
@ -269,10 +269,10 @@ struct NewGRFParametersWindow : public Window {
|
|||
std::string GetSettingString(const GRFParameterInfo &par_info, int i, uint32_t value) const
|
||||
{
|
||||
auto [param1, param2] = this->GetValueParams(par_info, value);
|
||||
const char *name = GetGRFStringFromGRFText(par_info.name);
|
||||
return name == nullptr
|
||||
? GetString(STR_NEWGRF_PARAMETERS_SETTING, STR_NEWGRF_PARAMETERS_DEFAULT_NAME, i + 1, param1, param2)
|
||||
: GetString(STR_NEWGRF_PARAMETERS_SETTING, STR_JUST_RAW_STRING, name, param1, param2);
|
||||
auto name = GetGRFStringFromGRFText(par_info.name);
|
||||
return name.has_value()
|
||||
? GetString(STR_NEWGRF_PARAMETERS_SETTING, STR_JUST_RAW_STRING, std::string(*name), param1, param2)
|
||||
: GetString(STR_NEWGRF_PARAMETERS_SETTING, STR_NEWGRF_PARAMETERS_DEFAULT_NAME, i + 1, param1, param2);
|
||||
}
|
||||
|
||||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
||||
|
@ -280,9 +280,9 @@ struct NewGRFParametersWindow : public Window {
|
|||
if (widget == WID_NP_DESCRIPTION) {
|
||||
if (!this->HasParameterInfo(this->clicked_row)) return;
|
||||
const GRFParameterInfo &par_info = this->GetParameterInfo(this->clicked_row);
|
||||
const char *desc = GetGRFStringFromGRFText(par_info.desc);
|
||||
if (desc == nullptr) return;
|
||||
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), desc, TC_BLACK);
|
||||
auto desc = GetGRFStringFromGRFText(par_info.desc);
|
||||
if (!desc.has_value()) return;
|
||||
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), *desc, TC_BLACK);
|
||||
return;
|
||||
} else if (widget != WID_NP_BACKGROUND) {
|
||||
return;
|
||||
|
@ -385,7 +385,9 @@ struct NewGRFParametersWindow : public Window {
|
|||
|
||||
DropDownList list;
|
||||
for (const auto &[value, name] : par_info.value_names) {
|
||||
list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_RAW_STRING, GetGRFStringFromGRFText(name)), value));
|
||||
auto text = GetGRFStringFromGRFText(name);
|
||||
assert(text.has_value()); // ensured by "complete_labels"
|
||||
list.push_back(MakeDropDownListStringItem(GetString(STR_JUST_RAW_STRING, std::string(*text)), value));
|
||||
}
|
||||
|
||||
ShowDropDownListAt(this, std::move(list), old_val, WID_NP_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
|
||||
|
|
|
@ -184,7 +184,7 @@ struct UnmappedChoiceList {
|
|||
}
|
||||
|
||||
/* "<STRINGDEFAULT>" */
|
||||
dest << this->strings[0].rdbuf() << '\0';
|
||||
dest << this->strings[0].rdbuf();
|
||||
} else {
|
||||
if (this->type == SCC_PLURAL_LIST) {
|
||||
*d++ = lm->plural_form;
|
||||
|
@ -611,18 +611,18 @@ StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid)
|
|||
* current language nullptr is returned.
|
||||
* @param text_list The GRFTextList to get the string from.
|
||||
*/
|
||||
const char *GetGRFStringFromGRFText(const GRFTextList &text_list)
|
||||
std::optional<std::string_view> GetGRFStringFromGRFText(const GRFTextList &text_list)
|
||||
{
|
||||
const char *default_text = nullptr;
|
||||
std::optional<std::string_view> default_text;
|
||||
|
||||
/* Search the list of lang-strings of this stringid for current lang */
|
||||
for (const auto &text : text_list) {
|
||||
if (text.langid == _currentLangID) return text.text.c_str();
|
||||
if (text.langid == _currentLangID) return text.text;
|
||||
|
||||
/* If the current string is English or American, set it as the
|
||||
* fallback language if the specific language isn't available. */
|
||||
if (text.langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text.langid == GRFLX_ENGLISH || text.langid == GRFLX_AMERICAN))) {
|
||||
default_text = text.text.c_str();
|
||||
if (text.langid == GRFLX_UNSPECIFIED || (!default_text.has_value() && (text.langid == GRFLX_ENGLISH || text.langid == GRFLX_AMERICAN))) {
|
||||
default_text = text.text;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,21 +636,21 @@ const char *GetGRFStringFromGRFText(const GRFTextList &text_list)
|
|||
* current language nullptr is returned.
|
||||
* @param text The GRFTextList to get the string from.
|
||||
*/
|
||||
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text)
|
||||
std::optional<std::string_view> GetGRFStringFromGRFText(const GRFTextWrapper &text)
|
||||
{
|
||||
return text ? GetGRFStringFromGRFText(*text) : nullptr;
|
||||
return text ? GetGRFStringFromGRFText(*text) : std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a C-string from a stringid set by a newgrf.
|
||||
*/
|
||||
const char *GetGRFStringPtr(StringIndexInTab stringid)
|
||||
std::string_view GetGRFStringPtr(StringIndexInTab stringid)
|
||||
{
|
||||
assert(stringid.base() < _grf_text.size());
|
||||
assert(_grf_text[stringid].grfid != 0);
|
||||
|
||||
const char *str = GetGRFStringFromGRFText(_grf_text[stringid].textholder);
|
||||
if (str != nullptr) return str;
|
||||
auto str = GetGRFStringFromGRFText(_grf_text[stringid].textholder);
|
||||
if (str.has_value()) return *str;
|
||||
|
||||
/* Use the default string ID if the fallback string isn't available */
|
||||
return GetStringPtr(_grf_text[stringid].def_string);
|
||||
|
@ -758,7 +758,7 @@ struct TextRefStack {
|
|||
}
|
||||
};
|
||||
|
||||
static void HandleNewGRFStringControlCodes(const char *str, TextRefStack &stack, std::vector<StringParameter> ¶ms);
|
||||
static void HandleNewGRFStringControlCodes(std::string_view str, TextRefStack &stack, std::vector<StringParameter> ¶ms);
|
||||
|
||||
/**
|
||||
* Process NewGRF string control code instructions.
|
||||
|
@ -961,11 +961,9 @@ char32_t RemapNewGRFStringControlCode(char32_t scc, const char **str)
|
|||
* @param[in,out] stack Stack to use.
|
||||
* @param[out] params Parameters to fill.
|
||||
*/
|
||||
static void HandleNewGRFStringControlCodes(const char *str, TextRefStack &stack, std::vector<StringParameter> ¶ms)
|
||||
static void HandleNewGRFStringControlCodes(std::string_view str, TextRefStack &stack, std::vector<StringParameter> ¶ms)
|
||||
{
|
||||
if (str == nullptr) return;
|
||||
|
||||
for (const char *p = str; *p != '\0'; /* nothing */) {
|
||||
for (const char *p = str.data(), *end = str.data() + str.size(); p < end; /* nothing */) {
|
||||
char32_t scc;
|
||||
p += Utf8Decode(&scc, p);
|
||||
ProcessNewGRFStringControlCode(scc, p, stack, params);
|
||||
|
@ -983,8 +981,7 @@ std::vector<StringParameter> GetGRFSringTextStackParameters(const GRFFile *grffi
|
|||
{
|
||||
if (stringid == INVALID_STRING_ID) return {};
|
||||
|
||||
const char *str = GetStringPtr(stringid);
|
||||
if (str == nullptr) return {};
|
||||
auto str = GetStringPtr(stringid);
|
||||
|
||||
std::vector<StringParameter> params;
|
||||
params.reserve(20);
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
StringID AddGRFString(uint32_t grfid, GRFStringID stringid, uint8_t langid, bool new_scheme, bool allow_newlines, std::string_view text_to_add, StringID def_string);
|
||||
StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid);
|
||||
const char *GetGRFStringFromGRFText(const GRFTextList &text_list);
|
||||
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text);
|
||||
const char *GetGRFStringPtr(StringIndexInTab stringid);
|
||||
std::optional<std::string_view> GetGRFStringFromGRFText(const GRFTextList &text_list);
|
||||
std::optional<std::string_view> GetGRFStringFromGRFText(const GRFTextWrapper &text);
|
||||
std::string_view 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);
|
||||
|
|
100
src/strings.cpp
100
src/strings.cpp
|
@ -258,7 +258,7 @@ uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
|
|||
static void StationGetSpecialString(StringBuilder &builder, StationFacilities x);
|
||||
static bool GetSpecialNameString(StringBuilder &builder, StringID string, StringParameters &args);
|
||||
|
||||
static void FormatString(StringBuilder &builder, const char *str, StringParameters &args, uint case_index = 0, bool game_script = false, bool dry_run = false);
|
||||
static void FormatString(StringBuilder &builder, std::string_view 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.
|
||||
|
@ -270,7 +270,7 @@ static void FormatString(StringBuilder &builder, const char *str, StringParamete
|
|||
* @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)
|
||||
static void FormatString(StringBuilder &builder, std::string_view 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);
|
||||
|
@ -291,7 +291,7 @@ struct LanguagePackDeleter {
|
|||
struct LoadedLanguagePack {
|
||||
std::unique_ptr<LanguagePack, LanguagePackDeleter> langpack;
|
||||
|
||||
std::vector<char *> offsets;
|
||||
std::vector<std::string_view> strings;
|
||||
|
||||
std::array<uint, TEXT_TAB_END> langtab_num; ///< Offset into langpack offs
|
||||
std::array<uint, TEXT_TAB_END> langtab_start; ///< Offset into langpack offs
|
||||
|
@ -312,7 +312,7 @@ std::string_view GetListSeparator()
|
|||
return _langpack.list_separator;
|
||||
}
|
||||
|
||||
const char *GetStringPtr(StringID string)
|
||||
std::string_view GetStringPtr(StringID string)
|
||||
{
|
||||
switch (GetStringTab(string)) {
|
||||
case TEXT_TAB_GAMESCRIPT_START: return GetGameStringPtr(GetStringIndex(string));
|
||||
|
@ -321,8 +321,8 @@ const char *GetStringPtr(StringID string)
|
|||
case TEXT_TAB_NEWGRF_START: return GetGRFStringPtr(GetStringIndex(string));
|
||||
default: {
|
||||
const size_t offset = _langpack.langtab_start[GetStringTab(string)] + GetStringIndex(string).base();
|
||||
if (offset < _langpack.offsets.size()) return _langpack.offsets[offset];
|
||||
return nullptr;
|
||||
if (offset < _langpack.strings.size()) return _langpack.strings[offset];
|
||||
return "(undefined string)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -780,16 +780,19 @@ static const char *ParseStringChoice(const char *b, uint form, StringBuilder &bu
|
|||
{
|
||||
/* <NUM> {Length of each string} {each string} */
|
||||
uint n = (uint8_t)*b++;
|
||||
uint pos, i, mypos = 0;
|
||||
|
||||
for (i = pos = 0; i != n; i++) {
|
||||
size_t form_offset = 0, form_len = 0, total_len = 0;
|
||||
for (uint i = 0; i != n; i++) {
|
||||
uint len = (uint8_t)*b++;
|
||||
if (i == form) mypos = pos;
|
||||
pos += len;
|
||||
if (i == form) {
|
||||
form_offset = total_len;
|
||||
form_len = len;
|
||||
}
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
builder += b + mypos;
|
||||
return b + pos;
|
||||
assert(form_len > 0); // len includes a null terminator
|
||||
builder += std::string_view(b + form_offset, form_len - 1);
|
||||
return b + total_len;
|
||||
}
|
||||
|
||||
/** Helper for unit conversion. */
|
||||
|
@ -1075,7 +1078,7 @@ static const char *DecodeEncodedString(const char *str, bool game_script, String
|
|||
* @param args Pointer to extra arguments used by various string codes.
|
||||
* @param dry_run True when the args' type data is not yet initialized.
|
||||
*/
|
||||
static void FormatString(StringBuilder &builder, const char *str_arg, StringParameters &args, uint orig_case_index, bool game_script, bool dry_run)
|
||||
static void FormatString(StringBuilder &builder, std::string_view str_arg, StringParameters &args, uint orig_case_index, bool game_script, bool dry_run)
|
||||
{
|
||||
size_t orig_first_param_offset = args.GetOffset();
|
||||
|
||||
|
@ -1094,25 +1097,31 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
|
|||
/* We have to restore the original offset here to to read the correct values. */
|
||||
args.SetOffset(orig_first_param_offset);
|
||||
}
|
||||
char32_t b = '\0';
|
||||
uint next_substr_case_index = 0;
|
||||
struct StrStackItem {
|
||||
const char *str;
|
||||
const char *end;
|
||||
size_t first_param_offset;
|
||||
uint case_index;
|
||||
|
||||
StrStackItem(std::string_view view, size_t first_param_offset, uint case_index)
|
||||
: str(view.data()), end(view.data() + view.size()), first_param_offset(first_param_offset), case_index(case_index)
|
||||
{}
|
||||
};
|
||||
std::stack<StrStackItem, std::vector<StrStackItem>> str_stack;
|
||||
str_stack.emplace(str_arg, orig_first_param_offset, orig_case_index);
|
||||
|
||||
for (;;) {
|
||||
try {
|
||||
while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top().str)) == '\0') {
|
||||
while (!str_stack.empty() && str_stack.top().str >= str_stack.top().end) {
|
||||
str_stack.pop();
|
||||
}
|
||||
if (str_stack.empty()) break;
|
||||
const char *&str = str_stack.top().str;
|
||||
const size_t ref_param_offset = str_stack.top().first_param_offset;
|
||||
const uint case_index = str_stack.top().case_index;
|
||||
char32_t b = Utf8Consume(&str);
|
||||
assert(b != 0);
|
||||
|
||||
if (SCC_NEWGRF_FIRST <= b && b <= SCC_NEWGRF_LAST) {
|
||||
/* We need to pass some stuff as it might be modified. */
|
||||
|
@ -1134,24 +1143,16 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
|
|||
|
||||
case SCC_NEWGRF_STRINL: {
|
||||
StringID substr = Utf8Consume(&str);
|
||||
const char *ptr = GetStringPtr(substr);
|
||||
if (ptr == nullptr) {
|
||||
builder += "(invalid NewGRF string)";
|
||||
} else {
|
||||
str_stack.emplace(ptr, args.GetOffset(), next_substr_case_index); // this may invalidate "str"
|
||||
}
|
||||
std::string_view ptr = GetStringPtr(substr);
|
||||
str_stack.emplace(ptr, args.GetOffset(), next_substr_case_index); // this may invalidate "str"
|
||||
next_substr_case_index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_NEWGRF_PRINT_WORD_STRING_ID: {
|
||||
StringID substr = args.GetNextParameter<StringID>();
|
||||
const char *ptr = GetStringPtr(substr);
|
||||
if (ptr == nullptr) {
|
||||
builder += "(invalid NewGRF string)";
|
||||
} else {
|
||||
str_stack.emplace(ptr, args.GetOffset(), next_substr_case_index); // this may invalidate "str"
|
||||
}
|
||||
std::string_view ptr = GetStringPtr(substr);
|
||||
str_stack.emplace(ptr, args.GetOffset(), next_substr_case_index); // this may invalidate "str"
|
||||
next_substr_case_index = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1226,16 +1227,22 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
|
|||
/* <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
|
||||
* Each LEN is printed using 2 bytes in big endian order. */
|
||||
uint num = (uint8_t)*str++;
|
||||
while (num) {
|
||||
if ((uint8_t)str[0] == case_index) {
|
||||
/* Found the case, adjust str pointer and continue */
|
||||
str += 3;
|
||||
break;
|
||||
std::optional<std::string_view> found;
|
||||
for (; num > 0; --num) {
|
||||
uint8_t index = static_cast<uint8_t>(str[0]);
|
||||
uint16_t len = (static_cast<uint8_t>(str[1]) << 8) + static_cast<uint8_t>(str[2]);
|
||||
assert(len > 0); // len includes a null terminator
|
||||
str += 3;
|
||||
if (index == case_index) {
|
||||
/* Found the case */
|
||||
found.emplace(str, len - 1);
|
||||
}
|
||||
/* Otherwise skip to the next case */
|
||||
str += 3 + (static_cast<uint8_t>(str[1]) << 8) + static_cast<uint8_t>(str[2]);
|
||||
num--;
|
||||
str += len;
|
||||
}
|
||||
const char *end = str_stack.top().end;
|
||||
if (!found.has_value()) found.emplace(str, end - str);
|
||||
str = end;
|
||||
str_stack.emplace(*found, ref_param_offset, case_index); // this may invalidate "str"
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1990,12 +1997,12 @@ bool LanguagePackHeader::IsReasonablyFinished() const
|
|||
bool ReadLanguagePack(const LanguageMetadata *lang)
|
||||
{
|
||||
/* Current language pack */
|
||||
size_t len = 0;
|
||||
std::unique_ptr<LanguagePack, LanguagePackDeleter> lang_pack(reinterpret_cast<LanguagePack *>(ReadFileToMem(FS2OTTD(lang->file), len, 1U << 20).release()));
|
||||
size_t total_len = 0;
|
||||
std::unique_ptr<LanguagePack, LanguagePackDeleter> lang_pack(reinterpret_cast<LanguagePack *>(ReadFileToMem(FS2OTTD(lang->file), total_len, 1U << 20).release()));
|
||||
if (!lang_pack) return false;
|
||||
|
||||
/* End of read data (+ terminating zero added in ReadFileToMem()) */
|
||||
const char *end = (char *)lang_pack.get() + len + 1;
|
||||
const char *end = (char *)lang_pack.get() + total_len + 1;
|
||||
|
||||
/* We need at least one byte of lang_pack->data */
|
||||
if (end <= lang_pack->data || !lang_pack->IsValid()) {
|
||||
|
@ -2015,26 +2022,25 @@ bool ReadLanguagePack(const LanguageMetadata *lang)
|
|||
}
|
||||
|
||||
/* Allocate offsets */
|
||||
std::vector<char *> offs(count);
|
||||
std::vector<std::string_view> strings;
|
||||
|
||||
/* Fill offsets */
|
||||
char *s = lang_pack->data;
|
||||
len = (uint8_t)*s++;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
size_t len = static_cast<uint8_t>(*s++);
|
||||
if (s + len >= end) return false;
|
||||
|
||||
if (len >= 0xC0) {
|
||||
len = ((len & 0x3F) << 8) + (uint8_t)*s++;
|
||||
len = ((len & 0x3F) << 8) + static_cast<uint8_t>(*s++);
|
||||
if (s + len >= end) return false;
|
||||
}
|
||||
offs[i] = s;
|
||||
strings.emplace_back(s, len);
|
||||
s += len;
|
||||
len = (uint8_t)*s;
|
||||
*s++ = '\0'; // zero terminate the string
|
||||
}
|
||||
assert(strings.size() == count);
|
||||
|
||||
_langpack.langpack = std::move(lang_pack);
|
||||
_langpack.offsets = std::move(offs);
|
||||
_langpack.strings = std::move(strings);
|
||||
_langpack.langtab_num = tab_num;
|
||||
_langpack.langtab_start = tab_start;
|
||||
|
||||
|
@ -2298,7 +2304,7 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
|
|||
{
|
||||
if (this->i >= TEXT_TAB_END) return std::nullopt;
|
||||
|
||||
const char *ret = _langpack.offsets[_langpack.langtab_start[this->i] + this->j];
|
||||
std::string_view ret = _langpack.strings[_langpack.langtab_start[this->i] + this->j];
|
||||
|
||||
this->j++;
|
||||
while (this->i < TEXT_TAB_END && this->j >= _langpack.langtab_num[this->i]) {
|
||||
|
|
|
@ -70,7 +70,7 @@ static inline void PrepareArgsForNextRun(std::span<StringParameter> args)
|
|||
|
||||
std::string GetStringWithArgs(StringID string, std::span<StringParameter> args);
|
||||
std::string GetString(StringID string);
|
||||
const char *GetStringPtr(StringID string);
|
||||
std::string_view GetStringPtr(StringID string);
|
||||
void AppendStringInPlace(std::string &result, StringID string);
|
||||
void AppendStringWithArgsInPlace(std::string &result, StringID string, std::span<StringParameter> params);
|
||||
|
||||
|
|
Loading…
Reference in New Issue