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
|
#pragma once
#include "../coding/reader.hpp"
#include "../coding/multilang_utf8_string.hpp"
#include "../std/map.hpp"
#include "../std/string.hpp"
#include "../std/limits.hpp"
#include "../std/algorithm.hpp"
#include "../std/vector.hpp"
namespace feature
{
class FeatureMetadata
{
typedef map<uint8_t, string> MetadataT;
MetadataT m_metadata;
public:
enum EMetadataType {
FMD_CUISINE = 1,
FMD_OPEN_HOURS = 2,
FMD_PHONE_NUMBER = 3,
FMD_FAX_NUMBER = 4,
FMD_STARS = 5,
FMD_OPERATOR = 6,
FMD_URL = 7,
FMD_WEBSITE = 8,
FMD_INTERNET = 9,
FMD_ELE = 10,
FMD_TURN_LANES = 11,
FMD_TURN_LANES_FORWARD = 12,
FMD_TURN_LANES_BACKWARD = 13,
FMD_EMAIL = 14
};
bool Add(EMetadataType type, string const & s)
{
if (m_metadata[type].empty())
{
m_metadata[type] = s;
}
else
{
m_metadata[type] = m_metadata[type] + ", " + s;
}
return true;
}
string Get(EMetadataType type) const
{
auto it = m_metadata.find(type);
return (it == m_metadata.end()) ? string() : it->second;
}
vector<EMetadataType> GetPresentTypes() const
{
vector<EMetadataType> types;
for (auto item: m_metadata)
types.push_back(static_cast<EMetadataType>(item.first));
return types;
}
void Drop(EMetadataType type)
{
m_metadata.erase(type);
}
inline bool Empty() const { return m_metadata.empty(); }
inline size_t Size() const { return m_metadata.size(); }
template <class ArchiveT> void SerializeToMWM(ArchiveT & ar) const
{
for (auto const & e: m_metadata)
{
uint8_t last_key_mark = (&e == &(*m_metadata.crbegin())) << 7; /// set high bit (0x80) if it last element
uint8_t elem[2] = {static_cast<uint8_t>(e.first | last_key_mark), static_cast<uint8_t>(min(e.second.size(), (size_t)numeric_limits<uint8_t>::max()))};
ar.Write(elem, sizeof(elem));
ar.Write(e.second.data(), elem[1]);
}
}
template <class ArchiveT> void DeserializeFromMWM(ArchiveT & ar)
{
uint8_t header[2] = {0};
char buffer[uint8_t(-1)] = {0};
do
{
ar.Read(header, sizeof(header));
ar.Read(buffer, header[1]);
m_metadata[static_cast<uint8_t>(header[0] & 0x7F)].assign(buffer, header[1]);
} while (!(header[0] & 0x80));
}
template <class ArchiveT> void Serialize(ArchiveT & ar) const
{
uint8_t const metadata_size = m_metadata.size();
WriteToSink(ar, metadata_size);
if (metadata_size)
{
for(auto & it: m_metadata)
{
WriteToSink(ar, static_cast<uint8_t>(it.first));
utils::WriteString(ar, it.second);
}
}
}
template <class ArchiveT> void Deserialize(ArchiveT & ar)
{
uint8_t const metadata_size = ReadPrimitiveFromSource<uint8_t>(ar);
for (size_t i=0; i < metadata_size; ++i)
{
uint8_t const key = ReadPrimitiveFromSource<uint8_t>(ar);
string value;
utils::ReadString(ar, value);
m_metadata.insert(make_pair(key, value));
}
}
};
}
|