Merge pull request #3824 from myk002/myk_translate

protect against bad values in TranslateName
develop
Myk 2023-09-28 20:55:27 -07:00 committed by GitHub
commit b3c45941fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 28 deletions

@ -57,6 +57,7 @@ Template for new versions:
## Fixes ## Fixes
- `autolabor`: now unconditionally re-enables vanilla work details when the fort or the plugin is unloaded - `autolabor`: now unconditionally re-enables vanilla work details when the fort or the plugin is unloaded
- ``dfhack.TranslateName()``: fixed crash on certain invalid names, which affected `warn-starving`
## Misc Improvements ## Misc Improvements
- `dig`: `digtype` command now has options to choose between designating only visible tiles or hidden tiles, as well as "auto" dig mode. Z-level options adjusted to allow choosing z-levels above, below, or the same as the cursor. - `dig`: `digtype` command now has options to choose between designating only visible tiles or hidden tiles, as well as "auto" dig mode. Z-level options adjusted to allow choosing z-levels above, below, or the same as the cursor.

@ -131,6 +131,37 @@ void Translation::setNickname(df::language_name *name, std::string nick)
} }
} }
static string translate_word(const df::language_name * name, size_t word_idx) {
CHECK_NULL_POINTER(name);
auto translation = vector_get(world->raws.language.translations, name->language);
if (!translation)
return "";
auto word = vector_get(translation->words, word_idx);
if (!word)
return "";
return *word;
}
static string translate_english_word(const df::language_name * name, size_t part_idx) {
CHECK_NULL_POINTER(name);
if (part_idx >= 7)
return "";
auto words = vector_get(world->raws.language.words, name->words[part_idx]);
if (!words)
return "";
df::part_of_speech part = name->parts_of_speech[part_idx];
if (part < df::part_of_speech::Noun || part > df::part_of_speech::VerbGerund)
return "";
return words->forms[part];
}
string Translation::TranslateName(const df::language_name * name, bool inEnglish, bool onlyLastPart) string Translation::TranslateName(const df::language_name * name, bool inEnglish, bool onlyLastPart)
{ {
CHECK_NULL_POINTER(name); CHECK_NULL_POINTER(name);
@ -166,20 +197,20 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
{ {
word.clear(); word.clear();
if (name->words[0] >= 0) if (name->words[0] >= 0)
word.append(*world->raws.language.translations[name->language]->words[name->words[0]]); word.append(translate_word(name, name->words[0]));
if (name->words[1] >= 0) if (name->words[1] >= 0)
word.append(*world->raws.language.translations[name->language]->words[name->words[1]]); word.append(translate_word(name, name->words[1]));
addNameWord(out, word); addNameWord(out, word);
} }
word.clear(); word.clear();
for (int i = 2; i <= 5; i++) for (int i = 2; i <= 5; i++)
if (name->words[i] >= 0) if (name->words[i] >= 0)
word.append(*world->raws.language.translations[name->language]->words[name->words[i]]); word.append(translate_word(name, name->words[i]));
addNameWord(out, word); addNameWord(out, word);
if (name->words[6] >= 0) if (name->words[6] >= 0)
{ {
word.clear(); word.clear();
word.append(*world->raws.language.translations[name->language]->words[name->words[6]]); word.append(translate_word(name, name->words[6]));
addNameWord(out, word); addNameWord(out, word);
} }
} }
@ -189,9 +220,9 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
{ {
word.clear(); word.clear();
if (name->words[0] >= 0) if (name->words[0] >= 0)
word.append(world->raws.language.words[name->words[0]]->forms[name->parts_of_speech[0]]); word.append(translate_english_word(name, 0));
if (name->words[1] >= 0) if (name->words[1] >= 0)
word.append(world->raws.language.words[name->words[1]]->forms[name->parts_of_speech[1]]); word.append(translate_english_word(name, 1));
addNameWord(out, word); addNameWord(out, word);
} }
if (name->words[2] >= 0 || name->words[3] >= 0 || name->words[4] >= 0 || name->words[5] >= 0) if (name->words[2] >= 0 || name->words[3] >= 0 || name->words[4] >= 0 || name->words[5] >= 0)
@ -201,10 +232,10 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
else else
out.append("The"); out.append("The");
} }
for (int i = 2; i <= 5; i++) for (size_t i = 2; i <= 5; i++)
{ {
if (name->words[i] >= 0) if (name->words[i] >= 0)
addNameWord(out, world->raws.language.words[name->words[i]]->forms[name->parts_of_speech[i]]); addNameWord(out, translate_english_word(name, i));
} }
if (name->words[6] >= 0) if (name->words[6] >= 0)
{ {
@ -213,7 +244,7 @@ string Translation::TranslateName(const df::language_name * name, bool inEnglish
else else
out.append("Of"); out.append("Of");
addNameWord(out, world->raws.language.words[name->words[6]]->forms[name->parts_of_speech[6]]); addNameWord(out, translate_english_word(name, 6));
} }
} }

@ -151,24 +151,6 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out)
return CR_OK; return CR_OK;
} }
// Name functions taken from manipulator.cpp
static std::string get_first_name(df::unit *unit)
{
return Translation::capitalize(unit->name.first_name);
}
static std::string get_last_name(df::unit *unit)
{
df::language_name name = unit->name;
std::string ret = "";
for (int i = 0; i < 2; i++)
{
if (name.words[i] >= 0)
ret += *world->raws.language.translations[name.language]->words[name.words[i]];
}
return Translation::capitalize(ret);
}
// Queue up a single order to engrave the slab for the given unit // Queue up a single order to engrave the slab for the given unit
static void createSlabJob(df::unit *unit) static void createSlabJob(df::unit *unit)
{ {
@ -212,7 +194,7 @@ static void checkslabs(color_ostream &out)
) )
{ {
createSlabJob(ghost); createSlabJob(ghost);
auto fullName = get_first_name(ghost) + " " + get_last_name(ghost); auto fullName = Translation::TranslateName(&ghost->name, false);
out.print("Added slab order for ghost %s\n", fullName.c_str()); out.print("Added slab order for ghost %s\n", fullName.c_str());
} }
} }