forked from mapsme/omim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultilang_utf8_string.hpp
138 lines (114 loc) · 3.48 KB
/
multilang_utf8_string.hpp
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#pragma once
#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "coding/writer.hpp"
#include "base/assert.hpp"
#include "std/array.hpp"
#include "std/string.hpp"
namespace utils
{
template <class TSink, bool EnableExceptions = false>
void WriteString(TSink & sink, string const & s)
{
if (EnableExceptions && s.empty())
MYTHROW(Writer::WriteException, ("String is empty"));
else
CHECK(!s.empty(), ());
size_t const sz = s.size();
WriteVarUint(sink, static_cast<uint32_t>(sz - 1));
sink.Write(s.c_str(), sz);
}
template <class TSource, bool EnableExceptions = false>
void ReadString(TSource & src, string & s)
{
uint32_t const sz = ReadVarUint<uint32_t>(src) + 1;
s.resize(sz);
src.Read(&s[0], sz);
if (EnableExceptions && s.empty())
MYTHROW(Reader::ReadException, ("String is empty"));
else
CHECK(!s.empty(), ());
}
} // namespace utils
class StringUtf8Multilang
{
string m_s;
size_t GetNextIndex(size_t i) const;
public:
static int8_t constexpr kUnsupportedLanguageCode = -1;
static int8_t constexpr kDefaultCode = 0;
static int8_t constexpr kEnglishCode = 1;
static int8_t constexpr kInternationalCode = 7;
/// How many languages we support on indexing stage. See full list in cpp file.
/// TODO(AlexZ): Review and replace invalid languages by valid ones.
static int8_t constexpr kMaxSupportedLanguages = 64;
struct Lang
{
/// OSM language code (e.g. for name:en it's "en" part).
char const * m_code;
/// Native language name.
char const * m_name;
/// Transliterator to latin id.
char const * m_transliteratorId;
};
using Languages = array<Lang, kMaxSupportedLanguages>;
static Languages const & GetSupportedLanguages();
/// @returns kUnsupportedLanguageCode if language is not recognized.
static int8_t GetLangIndex(string const & lang);
/// @returns empty string if langCode is invalid.
static char const * GetLangByCode(int8_t langCode);
/// @returns empty string if langCode is invalid.
static char const * GetLangNameByCode(int8_t langCode);
/// @returns empty string if langCode is invalid.
static char const * GetTransliteratorIdByCode(int8_t langCode);
inline bool operator== (StringUtf8Multilang const & rhs) const
{
return (m_s == rhs.m_s);
}
inline bool operator!= (StringUtf8Multilang const & rhs) const
{
return !(*this == rhs);
}
inline void Clear() { m_s.clear(); }
inline bool IsEmpty() const { return m_s.empty(); }
void AddString(int8_t lang, string const & utf8s);
void AddString(string const & lang, string const & utf8s)
{
int8_t const l = GetLangIndex(lang);
if (l >= 0)
AddString(l, utf8s);
}
template <class T>
void ForEach(T && fn) const
{
size_t i = 0;
size_t const sz = m_s.size();
while (i < sz)
{
size_t const next = GetNextIndex(i);
if (!fn((m_s[i] & 0x3F), m_s.substr(i + 1, next - i - 1)))
return;
i = next;
}
}
bool GetString(int8_t lang, string & utf8s) const;
bool GetString(string const & lang, string & utf8s) const
{
int8_t const l = GetLangIndex(lang);
if (l >= 0)
return GetString(l, utf8s);
else
return false;
}
bool HasString(int8_t lang) const;
int8_t FindString(string const & utf8s) const;
template <class TSink> void Write(TSink & sink) const
{
utils::WriteString(sink, m_s);
}
template <class TSource> void Read(TSource & src)
{
utils::ReadString(src, m_s);
}
};
string DebugPrint(StringUtf8Multilang const & s);