From 01ce09183b1fa2ba215e4da6af2726df55a6caae Mon Sep 17 00:00:00 2001 From: lynxnb Date: Thu, 23 Sep 2021 11:32:42 +0200 Subject: [PATCH] Rework common languages Swapped out the usages of frozen constexpr unordered maps for switch statements, which are very likely to be turned into jump tables given the nature of the enums used, resulting in better performance than a map --- app/src/main/cpp/skyline/common/languages.h | 170 +++++++++----------- app/src/main/cpp/skyline/common/macros.h | 23 ++- app/src/main/cpp/skyline/vfs/nacp.h | 4 +- 3 files changed, 95 insertions(+), 102 deletions(-) diff --git a/app/src/main/cpp/skyline/common/languages.h b/app/src/main/cpp/skyline/common/languages.h index 3cbca3ad..56c7c51c 100644 --- a/app/src/main/cpp/skyline/common/languages.h +++ b/app/src/main/cpp/skyline/common/languages.h @@ -5,6 +5,7 @@ #include #include +#include namespace skyline { namespace constant { @@ -13,121 +14,94 @@ namespace skyline { } namespace languages { + /** + * @brief The list of all languages. Entries parameters are language, language code, system language index, application language index and map which holds a macro used for filtering some application languages that don't have a direct corresponding system language + * @example #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) func(lang, code, sysIndex, appIndex, map)
LANGUAGES
#undef LANG_ENTRY + */ + #define LANGUAGES \ + LANG_ENTRY(Japanese, ja, 0, 2, MAP) \ + LANG_ENTRY(AmericanEnglish, en-us, 1, 0, MAP) \ + LANG_ENTRY(French, fr, 2, 3, MAP) \ + LANG_ENTRY(German, de, 3, 4, MAP) \ + LANG_ENTRY(Italian, it, 4, 7, MAP) \ + LANG_ENTRY(Spanish, es, 5, 6, MAP) \ + LANG_ENTRY(Chinese, zh-CN, 6, 14, DONT_MAP) \ + LANG_ENTRY(Korean, ko, 7, 12, MAP) \ + LANG_ENTRY(Dutch, nl, 8, 8, MAP) \ + LANG_ENTRY(Portuguese, pt, 9, 10, MAP) \ + LANG_ENTRY(Russian, ru, 10, 11, MAP) \ + LANG_ENTRY(Taiwanese, zh-TW, 11, 13, DONT_MAP) \ + LANG_ENTRY(BritishEnglish, en-GB, 12, 1, MAP) \ + LANG_ENTRY(CanadianFrench, fr-CA, 13, 9, MAP) \ + LANG_ENTRY(LatinAmericanSpanish, es-419, 14, 5, MAP) \ + LANG_ENTRY(SimplifiedChinese, zh-Hans, 15, 14, MAP) \ + LANG_ENTRY(TraditionalChinese, zh-Hant, 16, 13, MAP) \ + LANG_ENTRY(BrazilianPortuguese, pt-BR, 17, 10, DONT_MAP) + + /** + * @brief Enumeration of system languages + * @url https://switchbrew.org/wiki/Settings_services#Language + */ enum class SystemLanguage : u32 { - Japanese = 0, - AmericanEnglish, - French, - German, - Italian, - Spanish, - Chinese, - Korean, - Dutch, - Portuguese, - Russian, - Taiwanese, - BritishEnglish, - CanadianFrench, - LatinAmericanSpanish, - SimplifiedChinese, - TraditionalChinese, - BrazilianPortuguese, + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) lang = sysIndex, + LANGUAGES + #undef LANG_ENTRY }; + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) ENUM_CASE(lang); + ENUM_STRING(SystemLanguage, LANGUAGES) + #undef LANG_ENTRY + + /** + * @brief Enumeration of application languages + * @url https://switchbrew.org/wiki/NACP#ApplicationTitle + */ enum class ApplicationLanguage : u32 { - AmericanEnglish = 0, - BritishEnglish, - Japanese, - French, - German, - LatinAmericanSpanish, - Spanish, - Italian, - Dutch, - CanadianFrench, - Portuguese, - Russian, - Korean, - TraditionalChinese, - SimplifiedChinese, + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) lang = appIndex, + LANGUAGES + #undef LANG_ENTRY }; + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) map(lang); + #define MAP(key) ENUM_CASE(key) + #define DONT_MAP(key) + ENUM_STRING(ApplicationLanguage, LANGUAGES) + #undef LANG_ENTRY + #undef MAP + #undef DONT_MAP + constexpr std::array LanguageCodeList{ - util::MakeMagic("ja"), - util::MakeMagic("en-US"), - util::MakeMagic("fr"), - util::MakeMagic("de"), - util::MakeMagic("it"), - util::MakeMagic("es"), - util::MakeMagic("zh-CN"), - util::MakeMagic("ko"), - util::MakeMagic("nl"), - util::MakeMagic("pt"), - util::MakeMagic("ru"), - util::MakeMagic("zh-TW"), - util::MakeMagic("en-GB"), - util::MakeMagic("fr-CA"), - util::MakeMagic("es-419"), - util::MakeMagic("zh-Hans"), - util::MakeMagic("zh-Hant"), - util::MakeMagic("pt-BR"), + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) util::MakeMagic(#code), + LANGUAGES + #undef LANG_ENTRY }; constexpr u64 GetLanguageCode(SystemLanguage language) { return LanguageCodeList.at(static_cast(language)); } - #define LANG_MAP_ENTRY(lang) {SystemLanguage::lang, ApplicationLanguage::lang} - #define LANG_MAP_ENTRY_CST(sysLang, appLang) {SystemLanguage::sysLang, ApplicationLanguage::appLang} - constexpr frz::unordered_map SystemToAppMap{ - LANG_MAP_ENTRY(Japanese), - LANG_MAP_ENTRY(AmericanEnglish), - LANG_MAP_ENTRY(French), - LANG_MAP_ENTRY(German), - LANG_MAP_ENTRY(Italian), - LANG_MAP_ENTRY(Spanish), - LANG_MAP_ENTRY_CST(Chinese, SimplifiedChinese), - LANG_MAP_ENTRY(Korean), - LANG_MAP_ENTRY(Dutch), - LANG_MAP_ENTRY(Portuguese), - LANG_MAP_ENTRY(Russian), - LANG_MAP_ENTRY_CST(Taiwanese, TraditionalChinese), - LANG_MAP_ENTRY(BritishEnglish), - LANG_MAP_ENTRY(CanadianFrench), - LANG_MAP_ENTRY(LatinAmericanSpanish), - LANG_MAP_ENTRY(SimplifiedChinese), - LANG_MAP_ENTRY(TraditionalChinese), - LANG_MAP_ENTRY_CST(BrazilianPortuguese, Portuguese), - }; - #undef LANG_MAP_ENTRY - #undef LANG_MAP_ENTRY_CST - + /** + * @brief Maps a system language to its corresponding application language + */ constexpr ApplicationLanguage GetApplicationLanguage(SystemLanguage systemLanguage) { - return SystemToAppMap.at(systemLanguage); + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) ENUM_CASE_PAIR(lang, ApplicationLanguage::lang); + ENUM_SWITCH(SystemLanguage, systemLanguage, LANGUAGES, ApplicationLanguage::AmericanEnglish) + #undef LANG_ENTRY } - #define LANG_MAP_ENTRY_REVERSE(lang) {ApplicationLanguage::lang, SystemLanguage::lang} - constexpr frz::unordered_map AppToSystemMap{ - LANG_MAP_ENTRY_REVERSE(Japanese), - LANG_MAP_ENTRY_REVERSE(AmericanEnglish), - LANG_MAP_ENTRY_REVERSE(French), - LANG_MAP_ENTRY_REVERSE(German), - LANG_MAP_ENTRY_REVERSE(Italian), - LANG_MAP_ENTRY_REVERSE(Spanish), - LANG_MAP_ENTRY_REVERSE(Korean), - LANG_MAP_ENTRY_REVERSE(Dutch), - LANG_MAP_ENTRY_REVERSE(Portuguese), - LANG_MAP_ENTRY_REVERSE(Russian), - LANG_MAP_ENTRY_REVERSE(BritishEnglish), - LANG_MAP_ENTRY_REVERSE(CanadianFrench), - LANG_MAP_ENTRY_REVERSE(LatinAmericanSpanish), - LANG_MAP_ENTRY_REVERSE(SimplifiedChinese), - LANG_MAP_ENTRY_REVERSE(TraditionalChinese), - }; - #undef LANG_MAP_ENTRY_REVERSE - + /** + * @brief Maps an application language to its corresponding system language + */ constexpr SystemLanguage GetSystemLanguage(ApplicationLanguage applicationLanguage) { - return AppToSystemMap.at(applicationLanguage); + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) map(lang, SystemLanguage::lang); + #define MAP(key, value) ENUM_CASE_PAIR(key, value) + #define DONT_MAP(key, value) + ENUM_SWITCH(ApplicationLanguage, applicationLanguage, LANGUAGES, SystemLanguage::AmericanEnglish) + #undef LANG_ENTRY + #undef MAP + #undef DONT_MAP } + + #undef LANGUAGES } } \ No newline at end of file diff --git a/app/src/main/cpp/skyline/common/macros.h b/app/src/main/cpp/skyline/common/macros.h index 4a6c4dd0..51c55336 100644 --- a/app/src/main/cpp/skyline/common/macros.h +++ b/app/src/main/cpp/skyline/common/macros.h @@ -21,5 +21,24 @@ cases \ default: \ return "Unknown"; \ - }; \ - }; + } \ + } + +/** + * @brief A case statement for an enumerant value to use alongside ENUM_SWITCH + */ +#define ENUM_CASE_PAIR(key, value) \ + case ENUM_TYPE::key: \ + return value + +/** + * @brief Creates a switch case statement to convert an enumerant to the given values + * @example ENUM_SWITCH(Example, value, { ENUM_CASE_PAIR(keyA, valueA); ENUM_CASE_PAIR(keyB, valueB); }, defaultValue) + */ +#define ENUM_SWITCH(name, value, cases, defaultValue) \ + using ENUM_TYPE = name; \ + switch (value) { \ + cases \ + default: \ + return defaultValue; \ + } \ No newline at end of file diff --git a/app/src/main/cpp/skyline/vfs/nacp.h b/app/src/main/cpp/skyline/vfs/nacp.h index 2bc3c9f5..08521f6b 100644 --- a/app/src/main/cpp/skyline/vfs/nacp.h +++ b/app/src/main/cpp/skyline/vfs/nacp.h @@ -35,6 +35,8 @@ namespace skyline::vfs { } nacpContents{}; static_assert(sizeof(NacpData) == 0x4000); + u32 supportedTitleLanguages{0}; // &backing); languages::ApplicationLanguage GetFirstSupportedTitleLanguage(); @@ -44,7 +46,5 @@ namespace skyline::vfs { std::string GetApplicationName(languages::ApplicationLanguage language); std::string GetApplicationPublisher(languages::ApplicationLanguage language); - - u32 supportedTitleLanguages{0}; }; }