Restore the shared_ptrs

This commit is contained in:
Henrik Rydgård 2023-04-07 10:20:00 +02:00
parent 87b5a0b107
commit 12bd0ed26d
7 changed files with 81 additions and 86 deletions

View File

@ -7,59 +7,64 @@
#include "Common/StringUtils.h"
I18NRepo i18nrepo;
static const char * const g_categoryNames[(size_t)I18NCat::CATEGORY_COUNT] = {
"Audio",
"Controls",
"CwCheats",
"DesktopUI",
"Developer",
"Dialog",
"Error",
"Game",
"Graphics",
"InstallZip",
"KeyMapping",
"MainMenu",
"MainSettings",
"MappableControls",
"Networking",
"Pause",
"PostShaders",
"PSPCredits",
"MemStick",
"RemoteISO",
"Reporting",
"Savedata",
"Screen",
"Search",
"Store",
"SysInfo",
"System",
"TextureShaders",
"Themes",
"UI Elements",
"Upgrade",
"VR",
};
I18NRepo::~I18NRepo() {
Clear();
}
I18NRepo g_i18nrepo;
std::string I18NRepo::LanguageID() {
return languageID_;
}
I18NRepo::I18NRepo() {
cats_[(size_t)I18NCat::AUDIO].SetName("Audio");
cats_[(size_t)I18NCat::CONTROLS].SetName("Controls");
cats_[(size_t)I18NCat::SYSTEM].SetName("System");
cats_[(size_t)I18NCat::CWCHEATS].SetName("CwCheats");
cats_[(size_t)I18NCat::DESKTOPUI].SetName("DesktopUI");
cats_[(size_t)I18NCat::DEVELOPER].SetName("Developer");
cats_[(size_t)I18NCat::DIALOG].SetName("Dialog");
cats_[(size_t)I18NCat::ERRORS].SetName("Error");
cats_[(size_t)I18NCat::GAME].SetName("Game");
cats_[(size_t)I18NCat::GRAPHICS].SetName("Graphics");
cats_[(size_t)I18NCat::INSTALLZIP].SetName("InstallZip");
cats_[(size_t)I18NCat::KEYMAPPING].SetName("KeyMapping");
cats_[(size_t)I18NCat::MAINMENU].SetName("MainMenu");
cats_[(size_t)I18NCat::MAINSETTINGS].SetName("MainSettings");
cats_[(size_t)I18NCat::MAPPABLECONTROLS].SetName("MappableControls");
cats_[(size_t)I18NCat::NETWORKING].SetName("Networking");
cats_[(size_t)I18NCat::PAUSE].SetName("Pause");
cats_[(size_t)I18NCat::POSTSHADERS].SetName("PostShaders");
cats_[(size_t)I18NCat::PSPCREDITS].SetName("PSPCredits");
cats_[(size_t)I18NCat::MEMSTICK].SetName("MemStick");
cats_[(size_t)I18NCat::REMOTEISO].SetName("RemoteISO");
cats_[(size_t)I18NCat::REPORTING].SetName("Reporting");
cats_[(size_t)I18NCat::SAVEDATA].SetName("Savedata");
cats_[(size_t)I18NCat::SCREEN].SetName("Screen");
cats_[(size_t)I18NCat::SEARCH].SetName("Search");
cats_[(size_t)I18NCat::STORE].SetName("Store");
cats_[(size_t)I18NCat::SYSINFO].SetName("SysInfo");
cats_[(size_t)I18NCat::SYSTEM].SetName("System");
cats_[(size_t)I18NCat::TEXTURESHADERS].SetName("TextureShaders");
cats_[(size_t)I18NCat::THEMES].SetName("Themes");
cats_[(size_t)I18NCat::UI_ELEMENTS].SetName("UI Elements");
cats_[(size_t)I18NCat::UPGRADE].SetName("Upgrade");
cats_[(size_t)I18NCat::VR].SetName("VR");
Clear();
}
void I18NRepo::Clear() {
std::lock_guard<std::mutex> guard(catsLock_);
for (auto &iter : cats_) {
iter.Clear();
// Initialize with empty categories, so that early lookups don't crash.
iter = std::shared_ptr<I18NCategory>(new I18NCategory());
}
}
I18NCategory::I18NCategory(const Section &section) {
std::map<std::string, std::string> sectionMap = section.ToMap();
SetMap(sectionMap);
}
void I18NCategory::Clear() {
map_.clear();
missedKeyLog_.clear();
@ -69,6 +74,7 @@ const char *I18NCategory::T(const char *key, const char *def) {
if (!key) {
return "ERROR";
}
// Replace the \n's with \\n's so that key values with newlines will be found correctly.
std::string modifiedKey = key;
modifiedKey = ReplaceAll(modifiedKey, "\n", "\\n");
@ -95,23 +101,14 @@ void I18NCategory::SetMap(const std::map<std::string, std::string> &m) {
}
}
I18NCategory *I18NRepo::GetCategory(I18NCat category) {
std::shared_ptr<I18NCategory> I18NRepo::GetCategory(I18NCat category) {
std::lock_guard<std::mutex> guard(catsLock_);
if (category != I18NCat::NONE)
return &cats_[(size_t)category];
return cats_[(size_t)category];
else
return nullptr;
}
I18NCategory *I18NRepo::GetCategoryByName(const char *name) {
for (auto &iter : cats_) {
if (!strcmp(iter.GetName(), name)) {
return &iter;
}
}
return nullptr;
}
Path I18NRepo::GetIniPath(const std::string &languageID) const {
return Path("lang") / (languageID + ".ini");
}
@ -144,10 +141,11 @@ bool I18NRepo::LoadIni(const std::string &languageID, const Path &overridePath)
const std::vector<Section> &sections = ini.Sections();
std::lock_guard<std::mutex> guard(catsLock_);
for (auto &iter : sections) {
I18NCategory *cat = GetCategoryByName(iter.name().c_str());
if (cat) {
cat->LoadSection(iter);
for (auto &section : sections) {
for (size_t i = 0; i < (size_t)I18NCat::CATEGORY_COUNT; i++) {
if (!strcmp(section.name().c_str(), g_categoryNames[i])) {
cats_[i].reset(new I18NCategory(section));
}
}
}
@ -157,14 +155,19 @@ bool I18NRepo::LoadIni(const std::string &languageID, const Path &overridePath)
void I18NRepo::LogMissingKeys() const {
std::lock_guard<std::mutex> guard(catsLock_);
for (auto &cat : cats_) {
for (auto &key : cat.Missed()) {
INFO_LOG(SYSTEM, "Missing translation [%s]: %s (%s)", cat.GetName(), key.first.c_str(), key.second.c_str());
for (size_t i = 0; i < (size_t)I18NCat::CATEGORY_COUNT; i++) {
auto &cat = cats_[i];
for (auto &key : cat->Missed()) {
INFO_LOG(SYSTEM, "Missing translation [%s]: %s (%s)", g_categoryNames[i], key.first.c_str(), key.second.c_str());
}
}
}
void I18NCategory::LoadSection(const Section &section) {
std::map<std::string, std::string> sectionMap = section.ToMap();
SetMap(sectionMap);
std::shared_ptr<I18NCategory> GetI18NCategory(I18NCat category) {
if (category == I18NCat::NONE) {
return std::shared_ptr<I18NCategory>();
}
std::shared_ptr<I18NCategory> cat = g_i18nrepo.GetCategory(category);
_dbg_assert_(cat);
return cat;
}

View File

@ -12,6 +12,7 @@
#include <mutex>
#include <string>
#include <vector>
#include <memory>
#include "Common/Common.h"
#include "Common/File/Path.h"
@ -76,8 +77,8 @@ struct I18NCandidate {
class I18NCategory {
public:
I18NCategory() {}
// NOTE: Name must be a global constant string - it is not copied.
explicit I18NCategory(const char *name) : name_(name) {}
explicit I18NCategory(const Section &section);
const char *T(const char *key, const char *def = nullptr);
const char *T(const std::string &key) {
return T(key.c_str(), nullptr);
@ -90,16 +91,11 @@ public:
const std::map<std::string, I18NEntry> &GetMap() { return map_; }
void ClearMissed() { missedKeyLog_.clear(); }
const char *GetName() const { return name_.c_str(); }
void Clear();
private:
I18NCategory(I18NRepo *repo, const char *name) : name_(name) {}
void SetName(const char *name) { name_ = name; }
I18NCategory(I18NRepo *repo, const char *name) {}
void SetMap(const std::map<std::string, std::string> &m);
void LoadSection(const Section &section);
std::string name_;
std::map<std::string, I18NEntry> map_;
mutable std::mutex missedKeyLock_;
@ -112,18 +108,16 @@ private:
class I18NRepo {
public:
I18NRepo();
~I18NRepo();
bool IniExists(const std::string &languageID) const;
bool LoadIni(const std::string &languageID, const Path &overridePath = Path()); // NOT the filename!
std::string LanguageID();
I18NCategory *GetCategory(I18NCat category);
I18NCategory *GetCategoryByName(const char *name);
std::shared_ptr<I18NCategory> GetCategory(I18NCat category);
std::shared_ptr<I18NCategory> GetCategoryByName(const char *name);
const char *T(I18NCat category, const char *key, const char *def = nullptr) {
return cats_[(size_t)category].T(key, def);
return cats_[(size_t)category]->T(key, def);
}
void LogMissingKeys() const;
@ -133,19 +127,17 @@ private:
void Clear();
mutable std::mutex catsLock_;
I18NCategory cats_[(size_t)I18NCat::CATEGORY_COUNT];
std::shared_ptr<I18NCategory> cats_[(size_t)I18NCat::CATEGORY_COUNT];
std::string languageID_;
};
extern I18NRepo i18nrepo;
extern I18NRepo g_i18nrepo;
// These are simply talking to the one global instance of I18NRepo.
inline I18NCategory *GetI18NCategory(I18NCat cat) {
return i18nrepo.GetCategory(cat);
}
std::shared_ptr<I18NCategory> GetI18NCategory(I18NCat cat);
inline const char *T(I18NCat category, const char *key, const char *def = nullptr) {
return i18nrepo.T(category, key, def);
return g_i18nrepo.T(category, key, def);
}

View File

@ -432,7 +432,7 @@ const char *DefaultLangRegion() {
// Unfortunate default. There's no need to use bFirstRun, since this is only a default.
static std::string defaultLangRegion = "en_US";
std::string langRegion = System_GetProperty(SYSPROP_LANGREGION);
if (i18nrepo.IniExists(langRegion)) {
if (g_i18nrepo.IniExists(langRegion)) {
defaultLangRegion = langRegion;
} else if (langRegion.length() >= 3) {
// Don't give up. Let's try a fuzzy match - so nl_BE can match nl_NL.

View File

@ -661,9 +661,9 @@ void NewLanguageScreen::OnCompleted(DialogResult result) {
// If we run into the unlikely case that "lang" is actually a file, just use the built-in translations.
if (!File::Exists(langOverridePath) || !File::IsDirectory(langOverridePath))
iniLoadedSuccessfully = i18nrepo.LoadIni(g_Config.sLanguageIni);
iniLoadedSuccessfully = g_i18nrepo.LoadIni(g_Config.sLanguageIni);
else
iniLoadedSuccessfully = i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath);
iniLoadedSuccessfully = g_i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath);
if (iniLoadedSuccessfully) {
// Dunno what else to do here.

View File

@ -282,9 +282,9 @@ void PostLoadConfig() {
// If we run into the unlikely case that "lang" is actually a file, just use the built-in translations.
if (!File::Exists(langOverridePath) || !File::IsDirectory(langOverridePath))
i18nrepo.LoadIni(g_Config.sLanguageIni);
g_i18nrepo.LoadIni(g_Config.sLanguageIni);
else
i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath);
g_i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath);
#if PPSSPP_PLATFORM(ANDROID)
CreateDirectoriesAndroid();
@ -1381,7 +1381,7 @@ void NativeShutdown() {
INFO_LOG(SYSTEM, "NativeShutdown called");
i18nrepo.LogMissingKeys();
g_i18nrepo.LogMissingKeys();
ShutdownWebServer();

View File

@ -291,7 +291,7 @@ namespace MainWindow {
void TranslateMenus(HWND hWnd, HMENU menu) {
bool changed = false;
const std::string curLanguageID = i18nrepo.LanguageID();
const std::string curLanguageID = g_i18nrepo.LanguageID();
if (curLanguageID != menuLanguageID || KeyMap::HasChanged(menuKeymapGeneration)) {
DoTranslateMenus(hWnd, menu);
menuLanguageID = curLanguageID;

View File

@ -983,7 +983,7 @@ static void check_variables(CoreParameter &coreParam)
g_Config.iLanguage = get_language_auto();
g_Config.sLanguageIni = map_psp_language_to_i18n_locale(g_Config.iLanguage);
i18nrepo.LoadIni(g_Config.sLanguageIni);
g_i18nrepo.LoadIni(g_Config.sLanguageIni);
// Cannot detect refresh rate changes if:
// > Frame skipping is enabled