pokeplatinum/src/string_template.c

665 lines
22 KiB
C

#include "string_template.h"
#include <nitro.h>
#include <string.h>
#include "constants/charcode.h"
#include "constants/heap.h"
#include "constants/narc.h"
#include "constants/pokemon.h"
#include "generated/abilities.h"
#include "generated/genders.h"
#include "generated/moves.h"
#include "generated/text_banks.h"
#include "struct_decls/struct_020797DC_decl.h"
#include "struct_defs/trainer.h"
#include "charcode.h"
#include "enums.h"
#include "heap.h"
#include "message.h"
#include "pokemon.h"
#include "record_mixed_rng.h"
#include "save_player.h"
#include "savedata.h"
#include "savedata_misc.h"
#include "strbuf.h"
#include "trainer_info.h"
#include "unk_02014D38.h"
#include "unk_02017038.h"
#include "unk_020797C8.h"
#include "unk_020996D0.h"
#include "res/text/bank/common_strings.h"
#include "res/text/bank/common_strings_2.h"
#include "res/text/bank/mystery_gift_event_names.h"
#include "res/text/bank/special_met_location_names.h"
static void InitStringTemplateArgHeader(StringTemplateArgHeader *header);
static void SetStringTemplateArg(StringTemplate *template, u32 idx, const Strbuf *argVal, const StringTemplateArgHeader *newHeader);
StringTemplate *StringTemplate_Default(u32 heapID)
{
return StringTemplate_New(STRING_TEMPLATE_DEFAULT_MAX_ARGS, STRING_TEMPLATE_DEFAULT_MAX_LENGTH, heapID);
}
StringTemplate *StringTemplate_New(u32 maxArgs, u32 maxLen, u32 heapID)
{
StringTemplate *template = NULL;
GF_ASSERT(maxArgs);
GF_ASSERT(maxLen);
StringTemplate *tmp = Heap_AllocFromHeapAtEnd(heapID, sizeof(StringTemplate));
if (tmp == NULL) {
goto cleanup;
}
tmp->maxArgs = maxArgs;
tmp->heapID = heapID;
tmp->templateBuf = Strbuf_Init(maxLen, heapID);
if (tmp->templateBuf == NULL) {
goto cleanup;
}
tmp->args = Heap_AllocFromHeapAtEnd(heapID, sizeof(StringTemplateArg) * maxArgs);
if (tmp->args == NULL) {
goto cleanup;
}
u32 arg;
for (arg = 0; arg < maxArgs; arg++) {
InitStringTemplateArgHeader(&tmp->args[arg].header);
tmp->args[arg].strbuf = Strbuf_Init(maxLen, heapID);
if (tmp->args[arg].strbuf == NULL) {
break;
}
}
if (arg == maxArgs) {
return tmp;
}
cleanup:
if (template) {
StringTemplate_Free(template);
}
return NULL;
}
void StringTemplate_Free(StringTemplate *template)
{
GF_ASSERT(template->maxArgs);
if (template->args) {
for (u32 i = 0; i < template->maxArgs; i++) {
if (template->args[i].strbuf) {
Strbuf_Free(template->args[i].strbuf);
} else {
break;
}
}
Heap_FreeToHeap(template->args);
}
if (template->templateBuf) {
Strbuf_Free(template->templateBuf);
}
template->maxArgs = 0;
Heap_FreeToHeap(template);
}
static void InitStringTemplateArgHeader(StringTemplateArgHeader *header)
{
return;
}
static void SetStringTemplateArg(StringTemplate *template, u32 idx, const Strbuf *argVal, const StringTemplateArgHeader *newHeader)
{
GF_ASSERT(idx < template->maxArgs);
if (idx < template->maxArgs) {
if (newHeader != NULL) {
template->args[idx].header = *newHeader;
}
Strbuf_Copy(template->args[idx].strbuf, argVal);
}
}
static inline MessageLoader *InitMessageLoader(u32 bankID, u32 heapID)
{
return MessageLoader_Init(MESSAGE_LOADER_NARC_HANDLE, NARC_INDEX_MSGDATA__PL_MSG, bankID, heapID);
}
void StringTemplate_SetStrbuf(StringTemplate *template, u32 idx, const Strbuf *argVal, u32 unused3, BOOL unused4, u32 unused5)
{
SetStringTemplateArg(template, idx, argVal, NULL);
}
void StringTemplate_SetPlayerName(StringTemplate *template, u32 idx, const TrainerInfo *playerInfo)
{
Strbuf_CopyChars(template->templateBuf, TrainerInfo_Name(playerInfo));
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetRivalName(StringTemplate *template, u32 idx, const SaveData *save)
{
Strbuf_CopyChars(template->templateBuf, MiscSaveBlock_RivalName(SaveData_MiscSaveBlockConst(save)));
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetCounterpartName(StringTemplate *template, u32 idx, const SaveData *save)
{
const TrainerInfo *playerInfo = SaveData_GetTrainerInfo((SaveData *)save);
MessageLoader *loader = InitMessageLoader(TEXT_BANK_COUNTERPART_NAMES, template->heapID);
if (TrainerInfo_Gender(playerInfo) == GENDER_MALE) {
MessageLoader_GetStrbuf(loader, GENDER_FEMALE, template->templateBuf);
} else {
MessageLoader_GetStrbuf(loader, GENDER_MALE, template->templateBuf);
}
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetSpeciesName(StringTemplate *template, u32 idx, BoxPokemon *boxMon)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_SPECIES_NAMES, template->heapID);
u32 species = BoxPokemon_GetValue(boxMon, MON_DATA_SPECIES, NULL);
MessageLoader_GetStrbuf(loader, species, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetSpeciesNameWithArticle(StringTemplate *template, u32 idx, BoxPokemon *boxMon)
{
StringTemplate_SetSpeciesNameWithArticleByID(template, idx, BoxPokemon_GetValue(boxMon, MON_DATA_SPECIES, NULL));
}
void StringTemplate_SetSpeciesNameWithArticleByID(StringTemplate *template, u32 idx, u32 species)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_SPECIES_NAMES_WITH_ARTICLES, template->heapID);
MessageLoader_GetStrbuf(loader, species, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetNickname(StringTemplate *template, u32 idx, BoxPokemon *boxMon)
{
BoxPokemon_GetValue(boxMon, MON_DATA_NICKNAME_STRBUF, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetOTName(StringTemplate *template, u32 idx, BoxPokemon *boxMon)
{
BoxPokemon_GetValue(boxMon, MON_DATA_OTNAME_STRBUF, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetNumber(StringTemplate *template, u32 idx, int num, u32 maxDigits, enum PaddingMode paddingMode, enum CharsetMode charsetMode)
{
Strbuf_FormatInt(template->templateBuf, num, maxDigits, paddingMode, charsetMode);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
static inline void SetArgFromArchive(StringTemplate *template, u32 idx, u32 argVal, u32 bankID)
{
MessageLoader *loader = InitMessageLoader(bankID, template->heapID);
if (loader) {
MessageLoader_GetStrbuf(loader, argVal, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
}
void StringTemplate_SetMoveName(StringTemplate *template, u32 idx, enum Move move)
{
SetArgFromArchive(template, idx, move, TEXT_BANK_MOVE_NAMES);
}
void StringTemplate_SetRibbonName(StringTemplate *template, u32 idx, u32 ribbon)
{
SetArgFromArchive(template, idx, ribbon, TEXT_BANK_RIBBON_NAMES);
}
void StringTemplate_SetAbilityName(StringTemplate *template, u32 idx, enum Ability ability)
{
SetArgFromArchive(template, idx, ability, TEXT_BANK_ABILITY_NAMES);
}
void StringTemplate_SetNatureName(StringTemplate *template, u32 idx, u32 nature)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_NATURE_NAMES, template->heapID);
MessageLoader_GetStrbuf(loader, nature, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetItemName(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_ITEM_NAMES);
}
void StringTemplate_SetItemNameWithArticle(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_ITEM_NAMES_WITH_ARTICLES);
}
void StringTemplate_SetItemNamePlural(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_ITEM_NAMES_PLURAL);
}
void StringTemplate_SetBagPocketName(StringTemplate *template, u32 idx, u32 pocket)
{
SetArgFromArchive(template, idx, pocket, TEXT_BANK_BAG_POCKET_NAMES_WITH_ICONS);
}
void StringTemplate_SetPokemonTypeName(StringTemplate *template, u32 idx, u32 type)
{
SetArgFromArchive(template, idx, type, TEXT_BANK_POKEMON_TYPE_NAMES);
}
void StringTemplate_SetPokemonStatName(StringTemplate *template, u32 idx, u32 stat)
{
SetArgFromArchive(template, idx, stat, TEXT_BANK_POKEMON_STAT_NAMES);
}
void StringTemplate_SetStatusConditionName(StringTemplate *template, u32 idx, u32 status)
{
SetArgFromArchive(template, idx, status, TEXT_BANK_STATUS_CONDITION_NAMES);
}
void StringTemplate_SetFlavorName(StringTemplate *template, u32 idx, u32 flavor)
{
SetArgFromArchive(template, idx, flavor, TEXT_BANK_FLAVOR_NAMES);
}
void StringTemplate_SetLocationName(StringTemplate *template, u32 idx, u32 location)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_LOCATION_NAMES, template->heapID);
if (loader) {
if (location == 0 || location >= MessageLoader_MessageCount(loader)) {
MessageLoader_Free(loader);
loader = InitMessageLoader(TEXT_BANK_MYSTERY_GIFT_EVENT_NAMES, template->heapID);
location = pl_msg_00000434_00002;
}
MessageLoader_GetStrbuf(loader, location, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
}
void StringTemplate_SetPoketchAppName(StringTemplate *template, u32 idx, u32 app)
{
SetArgFromArchive(template, idx, app, TEXT_BANK_POKETCH_APP_NAMES);
}
void StringTemplate_SetTrainerClassName(StringTemplate *template, u32 idx, u32 trainerClass)
{
SetArgFromArchive(template, idx, trainerClass, TEXT_BANK_TRAINER_CLASS_NAMES);
}
void StringTemplate_SetTrainerClassNameWithArticle(StringTemplate *template, u32 idx, u32 trainerClass)
{
SetArgFromArchive(template, idx, trainerClass, TEXT_BANK_TRAINER_CLASS_NAMES_WITH_ARTICLES);
}
void StringTemplate_SetTrainerClassNameBattle(StringTemplate *template, u32 idx, Trainer *trainer)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_TRAINER_CLASS_NAMES, template->heapID);
if (loader) {
MessageLoader_GetStrbuf(loader, trainer->header.trainerType, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
}
void StringTemplate_SetTrainerName(StringTemplate *template, u32 idx, u32 trainerID)
{
SetArgFromArchive(template, idx, trainerID, TEXT_BANK_NPC_TRAINER_NAMES);
}
void StringTemplate_SetFrontierTrainerName(StringTemplate *template, u32 idx, u32 trainerID)
{
SetArgFromArchive(template, idx, trainerID, TEXT_BANK_FRONTIER_TRAINER_NAMES);
}
void StringTemplate_SetTrainerNameBattle(StringTemplate *template, u32 idx, Trainer *trainer)
{
Strbuf_CopyChars(template->templateBuf, trainer->name);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetUndergroundItemName(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_UNDERGROUND_ITEM_NAMES);
}
void StringTemplate_SetUndergroundItemNameWithArticle(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_UNDERGROUND_ITEM_NAMES_WITH_ARTICLES);
}
void StringTemplate_SetUndergroundTrapName(StringTemplate *template, u32 idx, u32 trap)
{
SetArgFromArchive(template, idx, trap, TEXT_BANK_UNDERGROUND_TRAP_NAMES);
}
void StringTemplate_SetUndergroundTrapNameWithArticle(StringTemplate *template, u32 idx, u32 trap)
{
SetArgFromArchive(template, idx, trap, TEXT_BANK_UNDERGROUND_TRAP_NAMES_WITH_ARTICLES);
}
void StringTemplate_SetContestJudgeName(StringTemplate *template, u32 idx, u32 judge)
{
SetArgFromArchive(template, idx, judge, TEXT_BANK_CONTEST_JUDGE_NAMES);
}
void StringTemplate_SetContestRankName(StringTemplate *template, u32 idx, u32 rank)
{
SetArgFromArchive(template, idx, rank, TEXT_BANK_CONTEST_TEXT);
}
void StringTemplate_SetContestTypeName(StringTemplate *template, u32 idx, u32 type)
{
SetArgFromArchive(template, idx, type, TEXT_BANK_CONTEST_TEXT);
}
void StringTemplate_SetUndergroundQuestion(StringTemplate *template, u32 idx, u32 question)
{
SetArgFromArchive(template, idx, question, TEXT_BANK_UNDERGROUND_QUESTIONS);
}
void StringTemplate_SetUndergroundAnswer(StringTemplate *template, u32 idx, u32 answer)
{
SetArgFromArchive(template, idx, answer, TEXT_BANK_UNDERGROUND_ANSWERS);
}
void StringTemplate_SetUndergroundGoodsName(StringTemplate *template, u32 idx, u32 goods)
{
SetArgFromArchive(template, idx, goods, TEXT_BANK_UNDERGROUND_GOODS);
}
void StringTemplate_SetUndergroundGoodsNameWithArticle(StringTemplate *template, u32 idx, u32 goods)
{
SetArgFromArchive(template, idx, goods, TEXT_BANK_UNDERGROUND_GOODS_WITH_ARTICLES);
}
void StringTemplate_SetGenderMarker(StringTemplate *template, u32 idx, enum Gender gender)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_COMMON_STRINGS, template->heapID);
switch (gender) {
case GENDER_MALE:
MessageLoader_GetStrbuf(loader, pl_msg_00000213_00068, template->templateBuf);
break;
case GENDER_FEMALE:
MessageLoader_GetStrbuf(loader, pl_msg_00000213_00069, template->templateBuf);
break;
default:
Strbuf_Clear(template->templateBuf);
}
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetPCBoxName(StringTemplate *template, u32 idx, const PCBoxes *boxes, u32 boxIdx)
{
sub_02079AF4(boxes, boxIdx, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetGymName(StringTemplate *template, u32 idx, u32 gym)
{
SetArgFromArchive(template, idx, gym, TEXT_BANK_GYM_NAMES);
}
void StringTemplate_SetTimeOfDay(StringTemplate *template, u32 idx, u32 timeOfDay)
{
SetArgFromArchive(template, idx, timeOfDay, TEXT_BANK_TIMES_OF_DAY);
}
void StringTemplate_SetCountryName(StringTemplate *template, u32 idx, u32 country)
{
SetArgFromArchive(template, idx, country, TEXT_BANK_COUNTRY_NAMES);
}
void StringTemplate_SetCityName(StringTemplate *template, u32 idx, u32 country, u32 city)
{
u32 bankID = sub_02099720(country);
if (bankID && city) {
SetArgFromArchive(template, idx, city, bankID);
}
}
void StringTemplate_SetCustomMessageWord(StringTemplate *template, u32 idx, u16 customMessageWord)
{
sub_02014DB8(customMessageWord, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
}
void StringTemplate_SetBallSealName(StringTemplate *template, u32 idx, u32 ballSeal)
{
SetArgFromArchive(template, idx, ballSeal, TEXT_BANK_BALL_SEAL_NAMES);
}
void StringTemplate_SetBallSealNamePlural(StringTemplate *template, u32 idx, u32 ballSeal)
{
SetArgFromArchive(template, idx, ballSeal, TEXT_BANK_BALL_SEAL_NAMES_PLURAL);
}
void StringTemplate_SetMetLocationName(StringTemplate *template, u32 idx, u32 location)
{
static const u16 sMetLocationBanks[] = {
TEXT_BANK_LOCATION_NAMES,
TEXT_BANK_SPECIAL_MET_LOCATION_NAMES,
TEXT_BANK_MYSTERY_GIFT_EVENT_NAMES,
};
int metLocationType = sub_02017038(location);
int metLocationID = sub_02017058(location);
MessageLoader *loader = InitMessageLoader(sMetLocationBanks[metLocationType], template->heapID);
if (loader) {
if (metLocationID < MessageLoader_MessageCount(loader)
&& (!(metLocationType == 0 && metLocationID == 0))) {
MessageLoader_GetStrbuf(loader, metLocationID, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
} else {
MessageLoader_Free(loader);
u32 bankID, msgID;
if (metLocationType == 0 && metLocationID == 0) {
bankID = sMetLocationBanks[1];
msgID = pl_msg_00000435_00012;
} else {
bankID = sMetLocationBanks[2];
msgID = pl_msg_00000434_00002;
}
SetArgFromArchive(template, idx, msgID, bankID);
}
}
}
void StringTemplate_SetPoffinName(StringTemplate *template, u32 idx, u32 poffin)
{
SetArgFromArchive(template, idx, poffin, TEXT_BANK_POFFIN_NAMES);
}
void StringTemplate_SetContestAccessoryName(StringTemplate *template, u32 idx, u32 accessory)
{
SetArgFromArchive(template, idx, accessory, TEXT_BANK_CONTEST_ACCESSORY_NAMES);
}
void StringTemplate_SetContestAccessoryNameWithArticle(StringTemplate *template, u32 idx, u32 accessory)
{
SetArgFromArchive(template, idx, accessory, TEXT_BANK_CONTEST_ACCESSORY_NAMES_WITH_ARTICLES);
}
void StringTemplate_SetContestBackdropName(StringTemplate *template, u32 idx, u32 backdrop)
{
SetArgFromArchive(template, idx, backdrop, TEXT_BANK_CONTEST_BACKDROP_NAMES);
}
void StringTemplate_SetUnionGroupName(StringTemplate *template, SaveData *save, int groupID, int idx, int nameType)
{
int gender, countryCode;
Strbuf *groupName;
RecordMixedRNG *group = SaveData_GetRecordMixedRNG(save);
gender = RecordMixedRNG_GetEntryGender(group, groupID);
countryCode = RecordMixedRNG_GetEntryCountryCode(group, groupID);
groupName = Strbuf_Init(64, HEAP_ID_FIELD);
Strbuf_CopyChars(groupName, RecordMixedRNG_GetEntryName(group, groupID, nameType));
StringTemplate_SetStrbuf(template, idx, groupName, gender, 1, countryCode);
Strbuf_Free(groupName);
}
void StringTemplate_SetPlazaMinigameName(StringTemplate *template, u32 idx, enum PlazaMinigame minigame)
{
SetArgFromArchive(template, idx, minigame, TEXT_BANK_PLAZA_MINIGAME_NAMES);
}
void StringTemplate_SetPlazaEventName(StringTemplate *template, u32 idx, int event)
{
SetArgFromArchive(template, idx, event, TEXT_BANK_PLAZA_EVENT_NAMES);
}
void StringTemplate_SetPlazaItemName(StringTemplate *template, u32 idx, u32 item)
{
SetArgFromArchive(template, idx, item, TEXT_BANK_PLAZA_ITEM_NAMES);
}
void StringTemplate_SetJPGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_JP);
}
void StringTemplate_SetENGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_EN);
}
void StringTemplate_SetFRGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_FR);
}
void StringTemplate_SetITGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_IT);
}
void StringTemplate_SetDEGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_DE);
}
void StringTemplate_SetESGreeting(StringTemplate *template, u32 idx, u32 greeting)
{
SetArgFromArchive(template, idx, greeting, TEXT_BANK_GREETINGS_ES);
}
void StringTemplate_SetFurniture(StringTemplate *template, u32 idx, u32 furniture)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_FURNITURE_NAMES, template->heapID);
MessageLoader_GetStrbuf(loader, furniture, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
void StringTemplate_SetMonthName(StringTemplate *template, u32 idx, u32 month)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_MONTH_NAMES, template->heapID);
if (loader) {
if (month < 1 || month > 12) {
month = 1;
}
MessageLoader_GetStrbuf(loader, month - 1, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
}
void StringTemplate_CapitalizeArgAtIndex(StringTemplate *template, u32 idx)
{
Strbuf_UpperChar(template->args[idx].strbuf, 0);
}
void StringTemplate_SetDepartmentStoreFloor(StringTemplate *template, u32 idx, u32 floor)
{
MessageLoader *loader = InitMessageLoader(TEXT_BANK_COMMON_STRINGS_2, template->heapID);
GF_ASSERT(floor <= 5);
if (loader) {
if (floor == pl_msg_00000361_00000) {
floor = pl_msg_00000361_00121;
} else {
floor += pl_msg_00000361_00115;
}
MessageLoader_GetStrbuf(loader, floor, template->templateBuf);
SetStringTemplateArg(template, idx, template->templateBuf, NULL);
MessageLoader_Free(loader);
}
}
void StringTemplate_Format(const StringTemplate *template, Strbuf *dst, const Strbuf *fmtString)
{
const charcode_t *c = Strbuf_GetData(fmtString);
Strbuf_Clear(dst);
while (*c != CHAR_EOS) {
if (*c == CHAR_FORMAT_ARG) {
if (CharCode_IsFormatArg(c)) {
u32 idx = CharCode_FormatArgParam(c, 0);
GF_ASSERT(idx < template->maxArgs);
Strbuf_ConcatTrainerName(dst, template->args[idx].strbuf);
c = CharCode_SkipFormatArg(c);
} else {
const charcode_t *tmp = c;
c = CharCode_SkipFormatArg(c);
while (tmp < c) {
Strbuf_AppendChar(dst, *tmp++);
}
}
} else {
Strbuf_AppendChar(dst, *c++);
}
}
}
void StringTemplate_ClearArgs(StringTemplate *template)
{
for (u32 i = 0; i < template->maxArgs; i++) {
Strbuf_Clear(template->args[i].strbuf);
}
}