1#pragma once
2
3#include <string>
4#include <vector>
5#include <Poco/Exception.h>
6#include <common/StringRef.h>
7#include <common/Types.h>
8#include "GeodataProviders/INamesProvider.h"
9
10
11/** A class that allows you to recognize by region id its text name in one of the supported languages.
12 *
13 * Information about region names loads from text files with the following format names: regions_names_xx.txt,
14 * where xx is one of the two letters of the following supported languages.
15 *
16 * Can on request update the data.
17 */
18class RegionsNames
19{
20/// Language name and fallback language name.
21#define FOR_EACH_LANGUAGE(M) \
22 M(ru, ru, 0) \
23 M(en, ru, 1) \
24 M(ua, ru, 2) \
25 M(uk, ua, 3) \
26 M(by, ru, 4) \
27 M(kz, ru, 5) \
28 M(tr, en, 6) \
29 M(de, en, 7) \
30 M(uz, ru, 8) \
31 M(lv, ru, 9) \
32 M(lt, ru, 10) \
33 M(et, ru, 11) \
34 M(pt, en, 12) \
35 M(he, en, 13) \
36 M(vi, en, 14)
37
38 static constexpr size_t total_languages = 15;
39
40public:
41 enum class Language : size_t
42 {
43 #define M(NAME, FALLBACK, NUM) NAME = NUM,
44 FOR_EACH_LANGUAGE(M)
45 #undef M
46 };
47
48private:
49 static inline constexpr const char * languages[] =
50 {
51 #define M(NAME, FALLBACK, NUM) #NAME,
52 FOR_EACH_LANGUAGE(M)
53 #undef M
54 };
55
56 static inline constexpr Language fallbacks[] =
57 {
58 #define M(NAME, FALLBACK, NUM) Language::FALLBACK,
59 FOR_EACH_LANGUAGE(M)
60 #undef M
61 };
62
63 using NamesSources = std::vector<std::shared_ptr<ILanguageRegionsNamesDataSource>>;
64
65 using Chars = std::vector<char>;
66 using CharsForLanguageID = std::vector<Chars>;
67 using StringRefs = std::vector<StringRef>; /// Lookup table RegionID -> StringRef
68 using StringRefsForLanguageID = std::vector<StringRefs>;
69
70
71 NamesSources names_sources = NamesSources(total_languages);
72
73 /// Bytes of names for each language, laid out in a row, separated by zeros
74 CharsForLanguageID chars = CharsForLanguageID(total_languages);
75
76 /// Mapping for each language from the region id into a pointer to the byte range of the name
77 StringRefsForLanguageID names_refs = StringRefsForLanguageID(total_languages);
78
79 static std::string dumpSupportedLanguagesNames();
80public:
81 RegionsNames(IRegionsNamesDataProviderPtr data_provider);
82
83 StringRef getRegionName(RegionID region_id, Language language) const
84 {
85 size_t language_id = static_cast<size_t>(language);
86
87 if (region_id >= names_refs[language_id].size())
88 return StringRef("", 0);
89
90 StringRef ref = names_refs[language_id][region_id];
91
92 static constexpr size_t root_language = static_cast<size_t>(Language::ru);
93 while (ref.size == 0 && language_id != root_language)
94 {
95 language_id = static_cast<size_t>(fallbacks[language_id]);
96 ref = names_refs[language_id][region_id];
97 }
98
99 return ref;
100 }
101
102 static Language getLanguageEnum(const std::string & language)
103 {
104 #define M(NAME, FALLBACK, NUM) \
105 if (0 == language.compare(#NAME)) \
106 return Language::NAME;
107 FOR_EACH_LANGUAGE(M)
108 #undef M
109 throw Poco::Exception("Unsupported language for region name. Supported languages are: " + dumpSupportedLanguagesNames() + ".");
110 }
111
112 void reload();
113};
114