CStringTable: Eliminate file-scope allocations

Eliminates all runtime static initializers, reducing the heap usage of
the application lifetime just a little bit.
This commit is contained in:
Lioncash 2020-06-10 01:06:44 -04:00
parent 0096b28294
commit 583472f2f9
1 changed files with 41 additions and 41 deletions

View File

@ -2,43 +2,54 @@
#include "Core/GameProject/CGameProject.h" #include "Core/GameProject/CGameProject.h"
#include <Common/Math/MathUtil.h> #include <Common/Math/MathUtil.h>
#include <algorithm> #include <algorithm>
#include <iterator> #include <array>
#include <utility>
/** /**
* Listing of supported languages for different engine versions. Note we ignore the "unused" languages. * Listing of supported languages for different engine versions. Note we ignore the "unused" languages.
* This is also the order that languages appear in game STRG assets. * This is also the order that languages appear in game STRG assets.
*/ */
// Supported languages in the original NTSC release of Metroid Prime // Supported languages in the original NTSC release of Metroid Prime
const std::vector<ELanguage> gkSupportedLanguagesMP1 = constexpr std::array gkSupportedLanguagesMP1{
{ ELanguage::English,
ELanguage::English
}; };
// Supported languages in the PAL version of Metroid Prime, and also Metroid Prime 2 // Supported languages in the PAL version of Metroid Prime, and also Metroid Prime 2
const std::vector<ELanguage> gkSupportedLanguagesMP1PAL = constexpr std::array gkSupportedLanguagesMP1PAL{
{ ELanguage::English,
ELanguage::English, ELanguage::French, ELanguage::German, ELanguage::French,
ELanguage::Spanish, ELanguage::Italian, ELanguage::Japanese ELanguage::German,
ELanguage::Spanish,
ELanguage::Italian,
ELanguage::Japanese,
}; };
// Supported languages in Metroid Prime 3 // Supported languages in Metroid Prime 3
const std::vector<ELanguage> gkSupportedLanguagesMP3 = constexpr std::array gkSupportedLanguagesMP3{
{ ELanguage::English,
ELanguage::English, ELanguage::Japanese, ELanguage::German, ELanguage::Japanese,
ELanguage::French, ELanguage::Spanish, ELanguage::Italian ELanguage::German,
ELanguage::French,
ELanguage::Spanish,
ELanguage::Italian,
}; };
// Supported languages in DKCR // Supported languages in DKCR
const std::vector<ELanguage> gkSupportedLanguagesDKCR = constexpr std::array gkSupportedLanguagesDKCR{
{ ELanguage::English,
ELanguage::English, ELanguage::Japanese, ELanguage::German, ELanguage::Japanese,
ELanguage::French, ELanguage::Spanish, ELanguage::Italian, ELanguage::German,
ELanguage::UKEnglish, ELanguage::Korean, ELanguage::French,
ELanguage::NAFrench, ELanguage::NASpanish ELanguage::Spanish,
ELanguage::Italian,
ELanguage::UKEnglish,
ELanguage::Korean,
ELanguage::NAFrench,
ELanguage::NASpanish,
}; };
// Utility function - retrieve the language array for a given game/region // Utility function - retrieve the language array for a given game/region
static const std::vector<ELanguage>& GetSupportedLanguages(EGame Game, ERegion Region) static std::pair<const ELanguage*, size_t> GetSupportedLanguages(EGame Game, ERegion Region)
{ {
switch (Game) switch (Game)
{ {
@ -46,20 +57,20 @@ static const std::vector<ELanguage>& GetSupportedLanguages(EGame Game, ERegion R
case EGame::PrimeDemo: case EGame::PrimeDemo:
case EGame::Prime: case EGame::Prime:
if (Region == ERegion::NTSC) if (Region == ERegion::NTSC)
return gkSupportedLanguagesMP1; return {gkSupportedLanguagesMP1.data(), gkSupportedLanguagesMP1.size()};
else else
return gkSupportedLanguagesMP1PAL; return {gkSupportedLanguagesMP1PAL.data(), gkSupportedLanguagesMP1PAL.size()};
case EGame::EchoesDemo: case EGame::EchoesDemo:
case EGame::Echoes: case EGame::Echoes:
case EGame::CorruptionProto: case EGame::CorruptionProto:
return gkSupportedLanguagesMP1PAL; return {gkSupportedLanguagesMP1PAL.data(), gkSupportedLanguagesMP1PAL.size()};
case EGame::Corruption: case EGame::Corruption:
return gkSupportedLanguagesMP3; return {gkSupportedLanguagesMP3.data(), gkSupportedLanguagesMP3.size()};
case EGame::DKCReturns: case EGame::DKCReturns:
return gkSupportedLanguagesDKCR; return {gkSupportedLanguagesDKCR.data(), gkSupportedLanguagesDKCR.size()};
} }
} }
@ -225,12 +236,12 @@ void CStringTable::InitializeNewResource()
{ {
// Initialize data for whatever languages are supported by our game/region // Initialize data for whatever languages are supported by our game/region
ERegion Region = ( Entry() && Entry()->Project() ? Entry()->Project()->Region() : ERegion::NTSC ); ERegion Region = ( Entry() && Entry()->Project() ? Entry()->Project()->Region() : ERegion::NTSC );
const std::vector<ELanguage>& kLanguageArray = GetSupportedLanguages(Game(), Region); const auto [data, dataSize] = GetSupportedLanguages(Game(), Region);
mLanguages.resize( kLanguageArray.size() ); mLanguages.resize(dataSize);
for (uint i=0; i < kLanguageArray.size(); i++) for (size_t i = 0; i < dataSize; i++)
{ {
mLanguages[i].Language = kLanguageArray[i]; mLanguages[i].Language = data[i];
mLanguages[i].Strings.resize(1); mLanguages[i].Strings.resize(1);
} }
} }
@ -382,17 +393,6 @@ TString CStringTable::StripFormatting(const TString& kInString)
/** Static - Returns whether a given language is supported by the given game/region combination */ /** Static - Returns whether a given language is supported by the given game/region combination */
bool CStringTable::IsLanguageSupported(ELanguage Language, EGame Game, ERegion Region) bool CStringTable::IsLanguageSupported(ELanguage Language, EGame Game, ERegion Region)
{ {
const std::vector<ELanguage>& kLanguageArray = GetSupportedLanguages(Game, Region); const auto [data, dataSize] = GetSupportedLanguages(Game, Region);
return std::any_of(data, data + dataSize, [Language](const auto lang) { return lang == Language; });
// Check if the requested language is in the array.
for (uint LanguageIdx = 0; LanguageIdx < kLanguageArray.size(); LanguageIdx++)
{
if (kLanguageArray[LanguageIdx] == Language)
{
return true;
}
}
// Unsupported
return false;
} }