1
0
Fork 0

Codechange: Use std::string and std::string_view instead of C strings.

pull/13884/head
frosch 2025-03-24 19:30:00 +01:00
parent c75d4cc4a0
commit 05a68d12c9
9 changed files with 95 additions and 107 deletions

View File

@ -22,9 +22,9 @@ struct StringParam {
ParamType type; ParamType type;
uint8_t consumes; uint8_t consumes;
const char *cmd; std::string_view cmd;
StringParam(ParamType type, uint8_t consumes, const char *cmd) : type(type), consumes(consumes), cmd(cmd) {} StringParam(ParamType type, uint8_t consumes, std::string_view cmd) : type(type), consumes(consumes), cmd(cmd) {}
}; };
using StringParams = std::vector<StringParam>; using StringParams = std::vector<StringParam>;
using StringParamsList = std::vector<StringParams>; using StringParamsList = std::vector<StringParams>;

View File

@ -65,10 +65,10 @@ struct LanguagePackHeader {
* @param gender_str The string representation of the gender. * @param gender_str The string representation of the gender.
* @return The index of the gender, or MAX_NUM_GENDERS when the gender is unknown. * @return The index of the gender, or MAX_NUM_GENDERS when the gender is unknown.
*/ */
uint8_t GetGenderIndex(const char *gender_str) const uint8_t GetGenderIndex(std::string_view gender_str) const
{ {
for (uint8_t i = 0; i < MAX_NUM_GENDERS; i++) { for (uint8_t i = 0; i < MAX_NUM_GENDERS; i++) {
if (strcmp(gender_str, this->genders[i]) == 0) return i; if (gender_str.compare(this->genders[i]) == 0) return i;
} }
return MAX_NUM_GENDERS; return MAX_NUM_GENDERS;
} }
@ -78,10 +78,10 @@ struct LanguagePackHeader {
* @param case_str The string representation of the case. * @param case_str The string representation of the case.
* @return The index of the case, or MAX_NUM_CASES when the case is unknown. * @return The index of the case, or MAX_NUM_CASES when the case is unknown.
*/ */
uint8_t GetCaseIndex(const char *case_str) const uint8_t GetCaseIndex(std::string_view case_str) const
{ {
for (uint8_t i = 0; i < MAX_NUM_CASES; i++) { for (uint8_t i = 0; i < MAX_NUM_CASES; i++) {
if (strcmp(case_str, this->cases[i]) == 0) return i; if (case_str.compare(this->cases[i]) == 0) return i;
} }
return MAX_NUM_CASES; return MAX_NUM_CASES;
} }

View File

@ -302,14 +302,14 @@ static ChangeInfoResult GlobalVarChangeInfo(uint first, uint last, int prop, Byt
LanguageMap::Mapping map; LanguageMap::Mapping map;
map.newgrf_id = newgrf_id; map.newgrf_id = newgrf_id;
if (prop == 0x13) { if (prop == 0x13) {
map.openttd_id = lang->GetGenderIndex(name.data()); map.openttd_id = lang->GetGenderIndex(name);
if (map.openttd_id >= MAX_NUM_GENDERS) { if (map.openttd_id >= MAX_NUM_GENDERS) {
GrfMsg(1, "GlobalVarChangeInfo: Gender name {} is not known, ignoring", StrMakeValid(name)); GrfMsg(1, "GlobalVarChangeInfo: Gender name {} is not known, ignoring", StrMakeValid(name));
} else { } else {
_cur.grffile->language_map[curidx].gender_map.push_back(map); _cur.grffile->language_map[curidx].gender_map.push_back(map);
} }
} else { } else {
map.openttd_id = lang->GetCaseIndex(name.data()); map.openttd_id = lang->GetCaseIndex(name);
if (map.openttd_id >= MAX_NUM_CASES) { if (map.openttd_id >= MAX_NUM_CASES) {
GrfMsg(1, "GlobalVarChangeInfo: Case name {} is not known, ignoring", StrMakeValid(name)); GrfMsg(1, "GlobalVarChangeInfo: Case name {} is not known, ignoring", StrMakeValid(name));
} else { } else {

View File

@ -193,9 +193,9 @@ void ScriptText::_FillParamList(ParamList &params, ScriptTextList &seen_texts)
} }
} }
void ScriptText::ParamCheck::Encode(std::back_insert_iterator<std::string> &output, const char *cmd) void ScriptText::ParamCheck::Encode(std::back_insert_iterator<std::string> &output, std::string_view cmd)
{ {
if (this->cmd == nullptr) this->cmd = cmd; if (this->cmd.empty()) this->cmd = cmd;
if (this->used) return; if (this->used) return;
struct visitor { struct visitor {
@ -286,7 +286,7 @@ void ScriptText::_GetEncodedText(std::back_insert_iterator<std::string> &output,
default: default:
for (int i = 0; i < cur_param.consumes; i++) { for (int i = 0; i < cur_param.consumes; i++) {
ParamCheck &p = *get_next_arg(); ParamCheck &p = *get_next_arg();
p.Encode(output, i == 0 ? cur_param.cmd : nullptr); p.Encode(output, i == 0 ? cur_param.cmd : "");
if (i == 0 && p.cmd != cur_param.cmd) throw 1; if (i == 0 && p.cmd != cur_param.cmd) throw 1;
if (!std::holds_alternative<SQInteger>(*p.param)) ScriptLog::Error(fmt::format("{}({}): {{{}}} expects an integer", name, param_count + i + 1, cur_param.cmd)); if (!std::holds_alternative<SQInteger>(*p.param)) ScriptLog::Error(fmt::format("{}({}): {{{}}} expects an integer", name, param_count + i + 1, cur_param.cmd));
} }

View File

@ -137,11 +137,11 @@ private:
int idx; int idx;
Param *param; Param *param;
bool used = false; bool used = false;
const char *cmd = nullptr; std::string_view cmd;
ParamCheck(StringIndexInTab 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<std::string> &output, const char *cmd); void Encode(std::back_insert_iterator<std::string> &output, std::string_view cmd);
}; };
using ParamList = std::vector<ParamCheck>; using ParamList = std::vector<ParamCheck>;

View File

@ -146,26 +146,26 @@ void FileStringReader::HandlePragma(char *str)
_lang.newgrflangid = static_cast<uint8_t>(langid); _lang.newgrflangid = static_cast<uint8_t>(langid);
} else if (!memcmp(str, "gender ", 7)) { } else if (!memcmp(str, "gender ", 7)) {
if (this->master) FatalError("Genders are not allowed in the base translation."); if (this->master) FatalError("Genders are not allowed in the base translation.");
char *buf = str + 7; const char *buf = str + 7;
for (;;) { for (;;) {
const char *s = ParseWord(&buf); auto s = ParseWord(&buf);
if (s == nullptr) break; if (!s.has_value()) break;
if (_lang.num_genders >= MAX_NUM_GENDERS) FatalError("Too many genders, max {}", MAX_NUM_GENDERS); if (_lang.num_genders >= MAX_NUM_GENDERS) FatalError("Too many genders, max {}", MAX_NUM_GENDERS);
strecpy(_lang.genders[_lang.num_genders], s); s->copy(_lang.genders[_lang.num_genders], CASE_GENDER_LEN - 1);
_lang.num_genders++; _lang.num_genders++;
} }
} else if (!memcmp(str, "case ", 5)) { } else if (!memcmp(str, "case ", 5)) {
if (this->master) FatalError("Cases are not allowed in the base translation."); if (this->master) FatalError("Cases are not allowed in the base translation.");
char *buf = str + 5; const char *buf = str + 5;
for (;;) { for (;;) {
const char *s = ParseWord(&buf); auto s = ParseWord(&buf);
if (s == nullptr) break; if (!s.has_value()) break;
if (_lang.num_cases >= MAX_NUM_CASES) FatalError("Too many cases, max {}", MAX_NUM_CASES); if (_lang.num_cases >= MAX_NUM_CASES) FatalError("Too many cases, max {}", MAX_NUM_CASES);
strecpy(_lang.cases[_lang.num_cases], s); s->copy(_lang.cases[_lang.num_cases], CASE_GENDER_LEN - 1);
_lang.num_cases++; _lang.num_cases++;
} }
} else { } else {
@ -344,7 +344,7 @@ int CDECL main(int argc, char *argv[])
} else { } else {
flags = '0'; // Command needs no parameters flags = '0'; // Command needs no parameters
} }
fmt::print("{}\t{:c}\t\"{}\"\t\"{}\"\n", cs.consumes, flags, cs.cmd, strstr(cs.cmd, "STRING") ? "STRING" : cs.cmd); fmt::print("{}\t{:c}\t\"{}\"\t\"{}\"\n", cs.consumes, flags, cs.cmd, cs.cmd.find("STRING") != std::string::npos ? "STRING" : cs.cmd);
} }
return 0; return 0;

View File

@ -152,7 +152,7 @@ void StrgenErrorI(const std::string &msg);
#define StrgenWarning(format_string, ...) StrgenWarningI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__)) #define StrgenWarning(format_string, ...) StrgenWarningI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__))
#define StrgenError(format_string, ...) StrgenErrorI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__)) #define StrgenError(format_string, ...) StrgenErrorI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__))
#define StrgenFatal(format_string, ...) StrgenFatalI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__)) #define StrgenFatal(format_string, ...) StrgenFatalI(fmt::format(FMT_STRING(format_string) __VA_OPT__(,) __VA_ARGS__))
char *ParseWord(char **buf); std::optional<std::string_view> ParseWord(const char **buf);
extern const char *_file; extern const char *_file;
extern size_t _cur_line; extern size_t _cur_line;

View File

@ -118,10 +118,10 @@ LangString *StringData::Find(const std::string &s)
* @param s The string hash. * @param s The string hash.
* @return The new hash. * @return The new hash.
*/ */
static uint32_t VersionHashStr(uint32_t hash, const char *s) static uint32_t VersionHashStr(uint32_t hash, std::string_view s)
{ {
for (; *s != '\0'; s++) { for (auto c : s) {
hash = std::rotl(hash, 3) ^ *s; hash = std::rotl(hash, 3) ^ c;
hash = (hash & 1 ? hash >> 1 ^ 0xDEADBEEF : hash >> 1); hash = (hash & 1 ? hash >> 1 ^ 0xDEADBEEF : hash >> 1);
} }
return hash; return hash;
@ -139,12 +139,11 @@ uint32_t StringData::Version() const
const LangString *ls = this->strings[i].get(); const LangString *ls = this->strings[i].get();
if (ls != nullptr) { if (ls != nullptr) {
const char *s = ls->name.c_str();
hash ^= i * 0x717239; hash ^= i * 0x717239;
hash = (hash & 1 ? hash >> 1 ^ 0xDEADBEEF : hash >> 1); hash = (hash & 1 ? hash >> 1 ^ 0xDEADBEEF : hash >> 1);
hash = VersionHashStr(hash, s + 1); hash = VersionHashStr(hash, ls->name);
s = ls->english.c_str(); const char *s = ls->english.c_str();
ParsedCommandString cs; ParsedCommandString cs;
while ((cs = ParseCommandString(&s)).cmd != nullptr) { while ((cs = ParseCommandString(&s)).cmd != nullptr) {
if (cs.cmd->flags.Test(CmdFlag::DontCount)) continue; if (cs.cmd->flags.Test(CmdFlag::DontCount)) continue;
@ -230,7 +229,7 @@ static size_t Utf8Validate(const char *s)
return 0; return 0;
} }
void EmitSingleChar(Buffer *buffer, char *buf, char32_t value) void EmitSingleChar(Buffer *buffer, const char *buf, char32_t value)
{ {
if (*buf != '\0') StrgenWarning("Ignoring trailing letters in command"); if (*buf != '\0') StrgenWarning("Ignoring trailing letters in command");
buffer->AppendUtf8(value); buffer->AppendUtf8(value);
@ -238,7 +237,7 @@ void EmitSingleChar(Buffer *buffer, char *buf, char32_t value)
/* The plural specifier looks like /* The plural specifier looks like
* {NUM} {PLURAL <ARG#> passenger passengers} then it picks either passenger/passengers depending on the count in NUM */ * {NUM} {PLURAL <ARG#> passenger passengers} then it picks either passenger/passengers depending on the count in NUM */
static std::pair<std::optional<size_t>, std::optional<size_t>> ParseRelNum(char **buf) static std::pair<std::optional<size_t>, std::optional<size_t>> ParseRelNum(const char **buf)
{ {
const char *s = *buf; const char *s = *buf;
char *end; char *end;
@ -258,65 +257,58 @@ static std::pair<std::optional<size_t>, std::optional<size_t>> ParseRelNum(char
} }
/* Parse out the next word, or nullptr */ /* Parse out the next word, or nullptr */
char *ParseWord(char **buf) std::optional<std::string_view> ParseWord(const char **buf)
{ {
char *s = *buf, *r; const char *s = *buf;
while (*s == ' ' || *s == '\t') s++; while (*s == ' ' || *s == '\t') s++;
if (*s == '\0') return nullptr; if (*s == '\0') return {};
if (*s == '"') { if (*s == '"') {
r = ++s; const char *begin = ++s;
/* parse until next " or NUL */ /* parse until next " or NUL */
for (;;) { for (;;) {
if (*s == '\0') break; if (*s == '\0') StrgenFatal("Unterminated quotes");
if (*s == '"') { if (*s == '"') {
*s++ = '\0'; *buf = s + 1;
break; return std::string_view(begin, s - begin);
} }
s++; s++;
} }
} else { } else {
/* proceed until whitespace or NUL */ /* proceed until whitespace or NUL */
r = s; const char *begin = s;
for (;;) { for (;;) {
if (*s == '\0') break; if (*s == '\0' || *s == ' ' || *s == '\t') {
if (*s == ' ' || *s == '\t') { *buf = s;
*s++ = '\0'; return std::string_view(begin, s - begin);
break;
} }
s++; s++;
} }
} }
*buf = s;
return r;
} }
/* This is encoded like /* This is encoded like
* CommandByte <ARG#> <NUM> {Length of each string} {each string} */ * CommandByte <ARG#> <NUM> {Length of each string} {each string} */
static void EmitWordList(Buffer *buffer, const std::vector<const char *> &words, size_t nw) static void EmitWordList(Buffer *buffer, const std::vector<std::string> &words)
{ {
/* Maximum word length in bytes, excluding trailing NULL. */ /* Maximum word length in bytes, excluding trailing NULL. */
constexpr size_t MAX_WORD_LENGTH = UINT8_MAX - 2; constexpr size_t MAX_WORD_LENGTH = UINT8_MAX - 2;
buffer->AppendByte(static_cast<uint8_t>(nw)); buffer->AppendByte(static_cast<uint8_t>(words.size()));
for (size_t i = 0; i < nw; i++) { for (size_t i = 0; i < words.size(); i++) {
size_t len = strlen(words[i]) + 1; size_t len = words[i].size() + 1;
if (len >= UINT8_MAX) StrgenFatal("WordList {}/{} string '{}' too long, max bytes {}", i + 1, nw, words[i], MAX_WORD_LENGTH); if (len >= UINT8_MAX) StrgenFatal("WordList {}/{} string '{}' too long, max bytes {}", i + 1, words.size(), words[i], MAX_WORD_LENGTH);
buffer->AppendByte(static_cast<uint8_t>(len)); buffer->AppendByte(static_cast<uint8_t>(len));
} }
for (size_t i = 0; i < nw; i++) { for (size_t i = 0; i < words.size(); i++) {
buffer->append(words[i]); buffer->append(words[i]);
buffer->AppendByte(0); buffer->AppendByte(0);
} }
} }
void EmitPlural(Buffer *buffer, char *buf, char32_t) void EmitPlural(Buffer *buffer, const char *buf, char32_t)
{ {
size_t expected = _plural_forms[_lang.plural_form].plural_count;
std::vector<const char *> words(std::max(expected, MAX_PLURALS), nullptr);
size_t nw = 0;
/* Parse out the number, if one exists. Otherwise default to prev arg. */ /* Parse out the number, if one exists. Otherwise default to prev arg. */
auto [argidx, offset] = ParseRelNum(&buf); auto [argidx, offset] = ParseRelNum(&buf);
if (!argidx.has_value()) { if (!argidx.has_value()) {
@ -334,26 +326,29 @@ void EmitPlural(Buffer *buffer, char *buf, char32_t)
} }
/* Parse each string */ /* Parse each string */
for (nw = 0; nw < MAX_PLURALS; nw++) { std::vector<std::string> words;
words[nw] = ParseWord(&buf); for (;;) {
if (words[nw] == nullptr) break; auto word = ParseWord(&buf);
if (!word.has_value()) break;
words.emplace_back(*word);
} }
if (nw == 0) { if (words.empty()) {
StrgenFatal("{}: No plural words", _cur_ident); StrgenFatal("{}: No plural words", _cur_ident);
} }
if (expected != nw) { size_t expected = _plural_forms[_lang.plural_form].plural_count;
if (expected != words.size()) {
if (_translated) { if (_translated) {
StrgenFatal("{}: Invalid number of plural forms. Expecting {}, found {}.", _cur_ident, StrgenFatal("{}: Invalid number of plural forms. Expecting {}, found {}.", _cur_ident,
expected, nw); expected, words.size());
} else { } else {
if (_show_warnings) StrgenWarning("'{}' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident); if (_show_warnings) StrgenWarning("'{}' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident);
if (nw > expected) { if (words.size() > expected) {
nw = expected; words.resize(expected);
} else { } else {
for (; nw < expected; nw++) { while (words.size() < expected) {
words[nw] = words[nw - 1]; words.push_back(words.back());
} }
} }
} }
@ -362,24 +357,22 @@ void EmitPlural(Buffer *buffer, char *buf, char32_t)
buffer->AppendUtf8(SCC_PLURAL_LIST); buffer->AppendUtf8(SCC_PLURAL_LIST);
buffer->AppendByte(_lang.plural_form); buffer->AppendByte(_lang.plural_form);
buffer->AppendByte(static_cast<uint8_t>(TranslateArgumentIdx(*argidx, *offset))); buffer->AppendByte(static_cast<uint8_t>(TranslateArgumentIdx(*argidx, *offset)));
EmitWordList(buffer, words, nw); EmitWordList(buffer, words);
} }
void EmitGender(Buffer *buffer, char *buf, char32_t) void EmitGender(Buffer *buffer, const char *buf, char32_t)
{ {
if (buf[0] == '=') { if (buf[0] == '=') {
buf++; buf++;
/* This is a {G=DER} command */ /* This is a {G=DER} command */
uint nw = _lang.GetGenderIndex(buf); auto nw = _lang.GetGenderIndex(buf);
if (nw >= MAX_NUM_GENDERS) StrgenFatal("G argument '{}' invalid", buf); if (nw >= MAX_NUM_GENDERS) StrgenFatal("G argument '{}' invalid", buf);
/* now nw contains the gender index */ /* now nw contains the gender index */
buffer->AppendUtf8(SCC_GENDER_INDEX); buffer->AppendUtf8(SCC_GENDER_INDEX);
buffer->AppendByte(nw); buffer->AppendByte(nw);
} else { } else {
std::vector<const char *> words(MAX_NUM_GENDERS, nullptr);
/* This is a {G 0 foo bar two} command. /* This is a {G 0 foo bar two} command.
* If no relative number exists, default to +0 */ * If no relative number exists, default to +0 */
auto [argidx, offset] = ParseRelNum(&buf); auto [argidx, offset] = ParseRelNum(&buf);
@ -391,38 +384,33 @@ void EmitGender(Buffer *buffer, char *buf, char32_t)
StrgenFatal("Command '{}' can't have a gender", cmd == nullptr ? "<empty>" : cmd->cmd); StrgenFatal("Command '{}' can't have a gender", cmd == nullptr ? "<empty>" : cmd->cmd);
} }
size_t nw; std::vector<std::string> words;
for (nw = 0; nw < MAX_NUM_GENDERS; nw++) { for (;;) {
words[nw] = ParseWord(&buf); auto word = ParseWord(&buf);
if (words[nw] == nullptr) break; if (!word.has_value()) break;
words.emplace_back(*word);
} }
if (nw != _lang.num_genders) StrgenFatal("Bad # of arguments for gender command"); if (words.size() != _lang.num_genders) StrgenFatal("Bad # of arguments for gender command");
assert(IsInsideBS(cmd->value, SCC_CONTROL_START, UINT8_MAX)); assert(IsInsideBS(cmd->value, SCC_CONTROL_START, UINT8_MAX));
buffer->AppendUtf8(SCC_GENDER_LIST); buffer->AppendUtf8(SCC_GENDER_LIST);
buffer->AppendByte(static_cast<uint8_t>(TranslateArgumentIdx(*argidx, *offset))); buffer->AppendByte(static_cast<uint8_t>(TranslateArgumentIdx(*argidx, *offset)));
EmitWordList(buffer, words, nw); EmitWordList(buffer, words);
} }
} }
static const CmdStruct *FindCmd(const char *s, size_t len) static const CmdStruct *FindCmd(std::string_view s)
{ {
for (const auto &cs : _cmd_structs) { for (const auto &cs : _cmd_structs) {
if (strncmp(cs.cmd, s, len) == 0 && cs.cmd[len] == '\0') return &cs; if (cs.cmd == s) return &cs;
} }
return nullptr; return nullptr;
} }
static uint ResolveCaseName(const char *str, size_t len) static uint ResolveCaseName(std::string_view str)
{ {
/* First get a clean copy of only the case name, then resolve it. */ uint case_idx = _lang.GetCaseIndex(str);
char case_str[CASE_GENDER_LEN]; if (case_idx >= MAX_NUM_CASES) StrgenFatal("Invalid case-name '{}'", str);
len = std::min(lengthof(case_str) - 1, len);
memcpy(case_str, str, len);
case_str[len] = '\0';
uint case_idx = _lang.GetCaseIndex(case_str);
if (case_idx >= MAX_NUM_CASES) StrgenFatal("Invalid case-name '{}'", case_str);
return case_idx + 1; return case_idx + 1;
} }
@ -453,9 +441,9 @@ static ParsedCommandString ParseCommandString(const char **str)
c = *s++; c = *s++;
} while (c != '}' && c != ' ' && c != '=' && c != '.' && c != 0); } while (c != '}' && c != ' ' && c != '=' && c != '.' && c != 0);
result.cmd = FindCmd(start, s - start - 1); std::string_view command(start, s - start - 1);
result.cmd = FindCmd(command);
if (result.cmd == nullptr) { if (result.cmd == nullptr) {
std::string command(start, s - start - 1);
StrgenError("Undefined command '{}'", command); StrgenError("Undefined command '{}'", command);
return {}; return {};
} }
@ -470,7 +458,7 @@ static ParsedCommandString ParseCommandString(const char **str)
do { do {
c = *s++; c = *s++;
} while (c != '}' && c != ' ' && c != '\0'); } while (c != '}' && c != ' ' && c != '\0');
result.casei = ResolveCaseName(casep, s - casep - 1); result.casei = ResolveCaseName(std::string_view(casep, s - casep - 1));
} }
if (c == '\0') { if (c == '\0') {
@ -542,15 +530,15 @@ const CmdStruct *TranslateCmdForCompare(const CmdStruct *a)
{ {
if (a == nullptr) return nullptr; if (a == nullptr) return nullptr;
if (strcmp(a->cmd, "STRING1") == 0 || if (a->cmd == "STRING1" ||
strcmp(a->cmd, "STRING2") == 0 || a->cmd == "STRING2" ||
strcmp(a->cmd, "STRING3") == 0 || a->cmd == "STRING3" ||
strcmp(a->cmd, "STRING4") == 0 || a->cmd == "STRING4" ||
strcmp(a->cmd, "STRING5") == 0 || a->cmd == "STRING5" ||
strcmp(a->cmd, "STRING6") == 0 || a->cmd == "STRING6" ||
strcmp(a->cmd, "STRING7") == 0 || a->cmd == "STRING7" ||
strcmp(a->cmd, "RAW_STRING") == 0) { a->cmd == "RAW_STRING") {
return FindCmd("STRING", 6); return FindCmd("STRING");
} }
return a; return a;
@ -689,7 +677,7 @@ void StringReader::HandleString(char *str)
if (!CheckCommandsMatch(s, ent->english.c_str(), str)) return; if (!CheckCommandsMatch(s, ent->english.c_str(), str)) return;
if (casep != nullptr) { if (casep != nullptr) {
ent->translated_cases.emplace_back(ResolveCaseName(casep, strlen(casep)), s); ent->translated_cases.emplace_back(ResolveCaseName(casep), s);
} else { } else {
ent->translated = s; ent->translated = s;
/* If the string was translated, use the line from the /* If the string was translated, use the line from the
@ -827,7 +815,7 @@ static void PutCommandString(Buffer *buffer, const char *str)
} }
} }
cmd->proc(buffer, cs.param.data(), cmd->value); cmd->proc(buffer, cs.param.c_str(), cmd->value);
} }
} }

View File

@ -17,10 +17,10 @@ enum class CmdFlag : uint8_t {
using CmdFlags = EnumBitSet<CmdFlag, uint8_t>; using CmdFlags = EnumBitSet<CmdFlag, uint8_t>;
struct Buffer; struct Buffer;
typedef void (*ParseCmdProc)(Buffer *buffer, char *buf, char32_t value); typedef void (*ParseCmdProc)(Buffer *buffer, const char *buf, char32_t value);
struct CmdStruct { struct CmdStruct {
const char *cmd; std::string_view cmd;
ParseCmdProc proc; ParseCmdProc proc;
char32_t value; char32_t value;
uint8_t consumes; uint8_t consumes;
@ -28,9 +28,9 @@ struct CmdStruct {
CmdFlags flags; CmdFlags flags;
}; };
extern void EmitSingleChar(Buffer *buffer, char *buf, char32_t value); extern void EmitSingleChar(Buffer *buffer, const char *buf, char32_t value);
extern void EmitPlural(Buffer *buffer, char *buf, char32_t value); extern void EmitPlural(Buffer *buffer, const char *buf, char32_t value);
extern void EmitGender(Buffer *buffer, char *buf, char32_t value); extern void EmitGender(Buffer *buffer, const char *buf, char32_t value);
static const CmdStruct _cmd_structs[] = { static const CmdStruct _cmd_structs[] = {
/* Font size */ /* Font size */