mirror of
https://github.com/OpenTTD/OpenTTD
synced 2026-01-31 16:14:29 +01:00
Codechange: Encode case/gender/plural choice lists without null termination, only length prefix. (#13876)
This commit is contained in:
@@ -292,18 +292,14 @@ std::optional<std::string_view> ParseWord(const char **buf)
|
||||
* CommandByte <ARG#> <NUM> {Length of each string} {each string} */
|
||||
static void EmitWordList(Buffer *buffer, const std::vector<std::string> &words)
|
||||
{
|
||||
/* Maximum word length in bytes, excluding trailing NULL. */
|
||||
constexpr size_t MAX_WORD_LENGTH = UINT8_MAX - 2;
|
||||
|
||||
buffer->AppendByte(static_cast<uint8_t>(words.size()));
|
||||
for (size_t i = 0; i < words.size(); i++) {
|
||||
size_t len = words[i].size() + 1;
|
||||
if (len >= UINT8_MAX) StrgenFatal("WordList {}/{} string '{}' too long, max bytes {}", i + 1, words.size(), words[i], MAX_WORD_LENGTH);
|
||||
size_t len = words[i].size();
|
||||
if (len > UINT8_MAX) StrgenFatal("WordList {}/{} string '{}' too long, max bytes {}", i + 1, words.size(), words[i], UINT8_MAX);
|
||||
buffer->AppendByte(static_cast<uint8_t>(len));
|
||||
}
|
||||
for (size_t i = 0; i < words.size(); i++) {
|
||||
buffer->append(words[i]);
|
||||
buffer->AppendByte(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,11 +896,12 @@ void LanguageWriter::WriteLang(const StringData &data)
|
||||
|
||||
_translated = cmdp != &ls->english;
|
||||
|
||||
std::optional<size_t> default_case_pos;
|
||||
if (!ls->translated_cases.empty()) {
|
||||
/* Need to output a case-switch.
|
||||
* It has this format
|
||||
* <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <STRINGDEFAULT>
|
||||
* Each LEN is printed using 2 bytes in big endian order. */
|
||||
* <0x9E> <NUM CASES> <CASE1> <LEN1> <STRING1> <CASE2> <LEN2> <STRING2> <CASE3> <LEN3> <STRING3> <LENDEFAULT> <STRINGDEFAULT>
|
||||
* Each LEN is printed using 2 bytes in little endian order. */
|
||||
buffer.AppendUtf8(SCC_SWITCH_CASE);
|
||||
buffer.AppendByte(static_cast<uint8_t>(ls->translated_cases.size()));
|
||||
|
||||
@@ -917,16 +914,25 @@ void LanguageWriter::WriteLang(const StringData &data)
|
||||
buffer.AppendByte(0);
|
||||
/* Write string */
|
||||
PutCommandString(&buffer, c.string.c_str());
|
||||
buffer.AppendByte(0); // terminate with a zero
|
||||
/* Fill in the length */
|
||||
size_t size = buffer.size() - (pos + 2);
|
||||
buffer[pos + 0] = GB(size, 8, 8);
|
||||
buffer[pos + 1] = GB(size, 0, 8);
|
||||
buffer[pos + 0] = GB(size, 0, 8);
|
||||
buffer[pos + 1] = GB(size, 8, 8);
|
||||
}
|
||||
|
||||
default_case_pos = buffer.size();
|
||||
buffer.AppendByte(0);
|
||||
buffer.AppendByte(0);
|
||||
}
|
||||
|
||||
if (!cmdp->empty()) PutCommandString(&buffer, cmdp->c_str());
|
||||
|
||||
if (default_case_pos.has_value()) {
|
||||
size_t size = buffer.size() - (*default_case_pos + 2);
|
||||
buffer[*default_case_pos + 0] = GB(size, 0, 8);
|
||||
buffer[*default_case_pos + 1] = GB(size, 8, 8);
|
||||
}
|
||||
|
||||
this->WriteLength(buffer.size());
|
||||
this->Write(buffer.data(), buffer.size());
|
||||
buffer.clear();
|
||||
|
||||
Reference in New Issue
Block a user