From 1d70a6e803824f1ad53837ecf5b7ea967775d4ca Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Tue, 17 May 2011 19:28:59 +0200 Subject: [PATCH] Moved language preferences from multilang_utf8_string to framework --- .../multilang_utf8_string_test.cpp | 37 +++++++++++--- coding/multilang_utf8_string.cpp | 50 ------------------- coding/multilang_utf8_string.hpp | 22 +++++--- indexer/feature.cpp | 37 +++++++++++++- indexer/feature.hpp | 14 ++++-- map/framework.cpp | 4 +- map/languages.cpp | 32 +++++++++++- map/languages.hpp | 4 ++ 8 files changed, 128 insertions(+), 72 deletions(-) diff --git a/coding/coding_tests/multilang_utf8_string_test.cpp b/coding/coding_tests/multilang_utf8_string_test.cpp index e32061dcc3..6736e76f21 100644 --- a/coding/coding_tests/multilang_utf8_string_test.cpp +++ b/coding/coding_tests/multilang_utf8_string_test.cpp @@ -41,14 +41,39 @@ namespace } } +lang_string gArr[] = { {"default", "default"}, + {"en", "abcd"}, + {"ru", "\xD0\xA0\xD0\xB0\xD1\x88\xD0\xBA\xD0\xB0"}, + {"be", "\xE2\x82\xAC\xF0\xA4\xAD\xA2"} }; + UNIT_TEST(MultilangString_Smoke) { StringUtf8Multilang s; - lang_string arr[] = { {"default", "default"}, - {"en", "abcd"}, - {"ru", "\xD0\xA0\xD0\xB0\xD1\x88\xD0\xBA\xD0\xB0"}, - {"be", "\xE2\x82\xAC\xF0\xA4\xAD\xA2"} }; - - TestMultilangString(arr, ARRAY_SIZE(arr)); + TestMultilangString(gArr, ARRAY_SIZE(gArr)); +} + +class LangChecker +{ + size_t m_index; + +public: + LangChecker() : m_index(0) {} + bool operator() (char lang, string const & utf8s) + { + TEST_EQUAL(lang, StringUtf8Multilang::GetLangIndex(gArr[m_index].m_lang), ()); + TEST_EQUAL(utf8s, gArr[m_index].m_str, ()); + ++m_index; + return true; + } +}; + +UNIT_TEST(MultilangString_ForEach) +{ + StringUtf8Multilang s; + for (size_t i = 0; i < ARRAY_SIZE(gArr); ++i) + s.AddString(gArr[i].m_lang, gArr[i].m_str); + + LangChecker doClass; + s.ForEachRef(doClass); } diff --git a/coding/multilang_utf8_string.cpp b/coding/multilang_utf8_string.cpp index 0a7a1d844e..fd00d54adb 100644 --- a/coding/multilang_utf8_string.cpp +++ b/coding/multilang_utf8_string.cpp @@ -1,13 +1,5 @@ #include "multilang_utf8_string.hpp" -char StringUtf8Multilang::m_priorities[] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63 -}; - char StringUtf8Multilang::GetLangIndex(string const & lang) { static char const * arr[] = { "default", @@ -81,45 +73,3 @@ bool StringUtf8Multilang::GetString(char lang, string & utf8s) const return false; } - -void StringUtf8Multilang::SetPreferableLanguages(vector const & langCodes) -{ - CHECK_EQUAL(langCodes.size(), 64, ()); - for (size_t i = 0; i < langCodes.size(); ++i) - { - char index = GetLangIndex(langCodes[i]); - if (index >= 0) - m_priorities[static_cast(index)] = i; - else - { - ASSERT(false, ("Invalid language code")); - } - CHECK_GREATER_OR_EQUAL(m_priorities[i], 0, ("Unsupported language", langCodes[i])); - } -} - -void StringUtf8Multilang::GetPreferableString(string & utf8s) const -{ - size_t i = 0; - size_t const sz = m_s.size(); - - int currPriority = 256; - while (i < sz) - { - size_t const next = GetNextIndex(i); - - int p = m_priorities[m_s[i] & 0x3F]; - if (p < currPriority) - { - ++i; - - currPriority = p; - utf8s.assign(m_s.c_str() + i, next - i); - - if (p == 0) - return; - } - - i = next; - } -} diff --git a/coding/multilang_utf8_string.hpp b/coding/multilang_utf8_string.hpp index 7ff829f01c..6ed029d44a 100644 --- a/coding/multilang_utf8_string.hpp +++ b/coding/multilang_utf8_string.hpp @@ -33,11 +33,10 @@ class StringUtf8Multilang string m_s; size_t GetNextIndex(size_t i) const; - static char GetLangIndex(string const & lang); - - static char m_priorities[64]; public: + static char GetLangIndex(string const & lang); + inline bool operator== (StringUtf8Multilang const & rhs) const { return m_s == rhs.m_s; @@ -54,9 +53,20 @@ public: AddString(l, utf8s); } - static void SetPreferableLanguages(vector const & langCodes); - /// Takes language priorities into an account - void GetPreferableString(string & utf8s) const; + template + void ForEachRef(T & functor) const + { + size_t i = 0; + size_t const sz = m_s.size(); + while (i < sz) + { + size_t const next = GetNextIndex(i); + if (!functor((m_s[i] & 0x3F), m_s.substr(i + 1, next - i - 1))) + return; + i = next; + } + } + bool GetString(char lang, string & utf8s) const; bool GetString(string const & lang, string & utf8s) const { diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 03666861de..5b6e58d3af 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -901,7 +901,34 @@ FeatureType::geom_stat_t FeatureType::GetTrianglesSize(int scale) const return geom_stat_t(sz, m_Triangles.size()); } -string FeatureType::GetPreferredDrawableName() const +class BestMatchedLangName +{ + char const * m_priorities; + string & m_result; + int m_minPriority; + +public: + + BestMatchedLangName(char const * priorities, string & result) + : m_priorities(priorities), m_result(result), m_minPriority(256) {} + bool operator() (char lang, string const & utf8s) + { + int const priority = m_priorities[lang]; + if (priority == 0) + { + m_result = utf8s; + return false; // stop foreach + } + if (priority < m_minPriority) + { + m_minPriority = priority; + m_result = utf8s; + } + return true; + } +}; + +string FeatureType::GetPreferredDrawableName(char const * priorities) const { uint8_t const h = Header(); string res; @@ -911,7 +938,13 @@ string FeatureType::GetPreferredDrawableName() const if (!m_bCommonParsed) ParseCommon(); - GetName(res); + if (priorities) + { + BestMatchedLangName matcher(priorities, res); + ForEachNameRef(matcher); + } + else + m_Params.name.GetString(0, res); if (res.empty() && GetFeatureType() == GEOM_AREA) res = m_Params.house.Get(); diff --git a/indexer/feature.hpp b/indexer/feature.hpp index 137775cdf2..6849a5e1ab 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -202,13 +202,15 @@ public: return m_Params.layer; } - inline void GetName(string & utf8s) const + template + inline bool ForEachNameRef(T & functor) const { if (!(Header() & feature::HEADER_HAS_NAME)) - return;// false; + return false; if (!m_bCommonParsed) ParseCommon(); - m_Params.name.GetPreferableString(utf8s); + m_Params.name.ForEachRef(functor); + return true; } inline m2::RectD GetLimitRect() const @@ -314,6 +316,10 @@ public: FeatureType() {} FeatureType(read_source_t & src); + /// @param priorities optional array of languages priorities + /// if NULL, default (0) lang will be used + string GetPreferredDrawableName(char const * priorities = NULL) const; + void Deserialize(read_source_t & src); /// @name Geometry. @@ -372,8 +378,6 @@ public: /// For test cases only. string DebugString(int scale) const; - string GetPreferredDrawableName() const; - uint8_t GetRank() const { return m_Params.rank; } /// @name Statistic functions. diff --git a/map/framework.cpp b/map/framework.cpp index 966c04158c..c5e13ea773 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -158,7 +158,9 @@ namespace fwork m_renderState->m_isEmptyModelCurrent = false; - shared_ptr ptr(new di::DrawInfo(f.GetPreferredDrawableName(), f.GetRank())); + shared_ptr ptr( + new di::DrawInfo(f.GetPreferredDrawableName(languages::GetCurrentPriorities()), + f.GetRank())); DrawerYG * pDrawer = GetDrawer(); diff --git a/map/languages.cpp b/map/languages.cpp index 4b2dcca235..920019cc49 100644 --- a/map/languages.cpp +++ b/map/languages.cpp @@ -14,13 +14,41 @@ #include "../std/sstream.hpp" #define DEFAULT_LANGUAGES "default" -#define MAX_SUPPORTED_LANGUAGES 64 #define LANGUAGES_FILE "languages.txt" #define LANG_DELIMETER "|" #define SETTING_LANG_KEY "languages_priority" namespace languages { + static char gDefaultPriorities[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63 + }; + + char const * GetCurrentPriorities() + { + return gDefaultPriorities; + } + + static void SetPreferableLanguages(vector const & langCodes) + { + CHECK_EQUAL(langCodes.size(), 64, ()); + for (size_t i = 0; i < langCodes.size(); ++i) + { + char const index = StringUtf8Multilang::GetLangIndex(langCodes[i]); + if (index >= 0) + gDefaultPriorities[static_cast(index)] = i; + else + { + ASSERT(false, ("Invalid language code")); + } + CHECK_GREATER_OR_EQUAL(gDefaultPriorities[i], 0, ("Unsupported language", langCodes[i])); + } + } + /// sorts outLanguages according to langCodes order static void Sort(vector const & langCodes, CodesAndNamesT & outLanguages) { @@ -85,7 +113,7 @@ namespace languages Settings::Set(SETTING_LANG_KEY, saveString); // apply new settings - StringUtf8Multilang::SetPreferableLanguages(langs); + SetPreferableLanguages(langs); } bool GetSupportedLanguages(CodesAndNamesT & outLanguages) diff --git a/map/languages.hpp b/map/languages.hpp index 871698231d..5e928238a5 100644 --- a/map/languages.hpp +++ b/map/languages.hpp @@ -6,9 +6,13 @@ namespace languages { + static int const MAX_SUPPORTED_LANGUAGES = 64; + typedef vector > CodesAndNamesT; typedef vector CodesT; + /// @return pointer to an array[MAX_SUPPORTED_LANGUAGES] + char const * GetCurrentPriorities(); void GetCurrentSettings(CodesT & outLangCodes); void GetCurrentSettings(CodesAndNamesT & outLanguages); void SaveSettings(CodesT const & langs);