Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/kml
diff options
context:
space:
mode:
authorRoman Kuznetsov <r.kuznetsow@gmail.com>2018-03-27 16:22:29 +0300
committerDaria Volvenkova <d.volvenkova@corp.mail.ru>2018-03-27 16:22:29 +0300
commitc945ce89d964c6cae62378a26e938b46c7d2ec15 (patch)
tree0acf119f7d4663a1891deafe8b7fb23aafa7363f /kml
parentd9d795a2e781360ef4f1c9917eefb20fde9abe8c (diff)
Added new data in extended KML format (#8388)
Added new data in extended KML format
Diffstat (limited to 'kml')
-rw-r--r--kml/kml_tests/serdes_tests.cpp126
-rw-r--r--kml/serdes.cpp139
-rw-r--r--kml/serdes.hpp4
-rw-r--r--kml/type_utils.hpp5
-rw-r--r--kml/types.hpp48
-rw-r--r--kml/visitors.hpp81
6 files changed, 314 insertions, 89 deletions
diff --git a/kml/kml_tests/serdes_tests.cpp b/kml/kml_tests/serdes_tests.cpp
index dff0f6f0ac..880d47262e 100644
--- a/kml/kml_tests/serdes_tests.cpp
+++ b/kml/kml_tests/serdes_tests.cpp
@@ -123,41 +123,42 @@ char const * kTextKml =
"</kml>";
std::vector<uint8_t> const kBinKml = {
- 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x2C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0xAB, 0xEB, 0x96, 0xE2, 0xFE, 0x83, 0xD4, 0x11,
- 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xC2, 0xFB, 0xF9, 0x01, 0x9E, 0xD0, 0xC7, 0x95,
- 0x9B, 0x9D, 0xBD, 0xAB, 0x12, 0x00, 0x02, 0x01, 0x00, 0x04, 0x01, 0x00, 0x05, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xBC,
- 0xED, 0xA7, 0x03, 0xEA, 0xA4, 0xD0, 0x9C, 0xD9, 0xA7, 0xBE, 0x9A, 0x19, 0x00, 0x02, 0x01, 0x00,
- 0x06, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xE4, 0xAF, 0xA7, 0xC1, 0xEB, 0xA6, 0xBE, 0x9A, 0x19, 0x00, 0x02, 0x01,
- 0x00, 0x07, 0x01, 0x00, 0x08, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0x0E, 0x08, 0x1B, 0x1A, 0x41, 0x0C, 0x11, 0x25, 0x3F, 0x00, 0x02, 0x00, 0x01, 0x08, 0x03, 0x02,
- 0x06, 0x01, 0x03, 0x06, 0x40, 0x05, 0x07, 0x8D, 0x01, 0x06, 0x05, 0x02, 0x07, 0x07, 0x71, 0x09,
- 0x05, 0x05, 0x0A, 0x07, 0x12, 0x0B, 0x06, 0x5E, 0x0D, 0x06, 0xBA, 0x01, 0x0E, 0x05, 0x04, 0x0F,
- 0x05, 0x75, 0x11, 0x05, 0x0D, 0x12, 0x06, 0x09, 0x13, 0x07, 0x4E, 0x15, 0x06, 0x91, 0x01, 0x16,
- 0x06, 0x0B, 0x17, 0x06, 0x73, 0x19, 0x05, 0x06, 0x1A, 0x08, 0x1C, 0x1B, 0x07, 0x63, 0x1D, 0x06,
- 0xC0, 0x01, 0x1E, 0x05, 0x07, 0x1F, 0x06, 0x77, 0x21, 0x06, 0x0A, 0x22, 0x07, 0x08, 0x23, 0x07,
- 0x49, 0x25, 0x07, 0x90, 0x01, 0x27, 0x06, 0x72, 0x2A, 0x08, 0x14, 0x2B, 0x06, 0x62, 0x2D, 0x06,
- 0xBD, 0x01, 0x32, 0x06, 0x0C, 0x33, 0x06, 0x57, 0x35, 0x07, 0xA1, 0x01, 0x36, 0x06, 0x0F, 0x37,
- 0x07, 0x76, 0x3A, 0x08, 0x31, 0x3B, 0x06, 0x68, 0x3D, 0x06, 0xD1, 0x01, 0x3F, 0x06, 0x79, 0x41,
- 0x07, 0xB8, 0x01, 0x45, 0x07, 0x8F, 0x01, 0x47, 0x07, 0x74, 0x4A, 0x07, 0x13, 0x53, 0x07, 0x59,
- 0x5A, 0x07, 0x29, 0x5B, 0x07, 0x6D, 0x62, 0x08, 0x10, 0x63, 0x07, 0x4B, 0x65, 0x07, 0x96, 0x01,
- 0x6A, 0x08, 0x18, 0x75, 0x07, 0xB7, 0x01, 0x77, 0x07, 0x8A, 0x01, 0x7A, 0x08, 0x3F, 0x81, 0x01,
- 0x08, 0x0E, 0x9A, 0x01, 0x08, 0x25, 0xAA, 0x01, 0x08, 0x17, 0xBA, 0x01, 0x08, 0x3E, 0xE2, 0x01,
- 0x08, 0x11, 0xEA, 0x01, 0x08, 0x19, 0xFA, 0x01, 0x08, 0x41, 0xB0, 0x01, 0xD7, 0x64, 0xD6, 0x6E,
- 0x37, 0x46, 0x07, 0x3D, 0xA1, 0xA8, 0x65, 0x2F, 0x34, 0x01, 0x83, 0xBE, 0x2E, 0x87, 0x3C, 0x64,
- 0x71, 0x6E, 0xA3, 0xE7, 0xCC, 0xB7, 0x8E, 0x6D, 0xA7, 0xE2, 0xFD, 0x13, 0xBC, 0x9A, 0x51, 0x7D,
- 0xF2, 0xE9, 0x17, 0x8F, 0x33, 0x91, 0x28, 0xDB, 0xA1, 0x22, 0x5F, 0xB3, 0x14, 0x65, 0xE9, 0x57,
- 0x92, 0xAC, 0x33, 0xC5, 0xF8, 0x3E, 0x37, 0x35, 0x00, 0x88, 0x1C, 0x96, 0x62, 0x97, 0x17, 0x09,
- 0xA5, 0x3F, 0x42, 0x18, 0x98, 0xD5, 0x45, 0x96, 0x1D, 0x0A, 0x46, 0x2C, 0xB9, 0x94, 0xFE, 0x35,
- 0xF7, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xD0, 0xA2, 0xD9, 0x95, 0x6B, 0xDC, 0x69,
- 0xEA, 0x2D, 0x52, 0xB0, 0x43, 0xA8, 0x7C, 0xA9, 0x32, 0x0E, 0x01, 0x00, 0x09,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3A, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE2, 0xAB, 0xEB, 0x96, 0xE2, 0xFE, 0x83, 0xD4, 0x11, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00,
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0xC2, 0xFB, 0xF9, 0x01, 0x9E, 0xD0, 0xC7, 0x95, 0x9B, 0x9D, 0xBD, 0xAB, 0x12,
+ 0x00, 0x03, 0x01, 0x00, 0x04, 0x01, 0x00, 0x05, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xBC, 0xED, 0xA7, 0x03, 0xEA,
+ 0xA4, 0xD0, 0x9C, 0xD9, 0xA7, 0xBE, 0x9A, 0x19, 0x00, 0x03, 0x01, 0x00, 0x06, 0x00, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE4, 0xAF, 0xA7, 0xC1, 0xEB, 0xA6, 0xBE, 0x9A, 0x19, 0x00, 0x03, 0x01, 0x00, 0x07, 0x01,
+ 0x00, 0x08, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0E, 0x08,
+ 0x1B, 0x1A, 0x41, 0x0C, 0x11, 0x25, 0x3F, 0x00, 0x02, 0x00, 0x01, 0x08, 0x03, 0x02, 0x06, 0x01,
+ 0x03, 0x06, 0x40, 0x05, 0x07, 0x8D, 0x01, 0x06, 0x05, 0x02, 0x07, 0x07, 0x71, 0x09, 0x05, 0x05,
+ 0x0A, 0x07, 0x12, 0x0B, 0x06, 0x5E, 0x0D, 0x06, 0xBA, 0x01, 0x0E, 0x05, 0x04, 0x0F, 0x05, 0x75,
+ 0x11, 0x05, 0x0D, 0x12, 0x06, 0x09, 0x13, 0x07, 0x4E, 0x15, 0x06, 0x91, 0x01, 0x16, 0x06, 0x0B,
+ 0x17, 0x06, 0x73, 0x19, 0x05, 0x06, 0x1A, 0x08, 0x1C, 0x1B, 0x07, 0x63, 0x1D, 0x06, 0xC0, 0x01,
+ 0x1E, 0x05, 0x07, 0x1F, 0x06, 0x77, 0x21, 0x06, 0x0A, 0x22, 0x07, 0x08, 0x23, 0x07, 0x49, 0x25,
+ 0x07, 0x90, 0x01, 0x27, 0x06, 0x72, 0x2A, 0x08, 0x14, 0x2B, 0x06, 0x62, 0x2D, 0x06, 0xBD, 0x01,
+ 0x32, 0x06, 0x0C, 0x33, 0x06, 0x57, 0x35, 0x07, 0xA1, 0x01, 0x36, 0x06, 0x0F, 0x37, 0x07, 0x76,
+ 0x3A, 0x08, 0x31, 0x3B, 0x06, 0x68, 0x3D, 0x06, 0xD1, 0x01, 0x3F, 0x06, 0x79, 0x41, 0x07, 0xB8,
+ 0x01, 0x45, 0x07, 0x8F, 0x01, 0x47, 0x07, 0x74, 0x4A, 0x07, 0x13, 0x53, 0x07, 0x59, 0x5A, 0x07,
+ 0x29, 0x5B, 0x07, 0x6D, 0x62, 0x08, 0x10, 0x63, 0x07, 0x4B, 0x65, 0x07, 0x96, 0x01, 0x6A, 0x08,
+ 0x18, 0x75, 0x07, 0xB7, 0x01, 0x77, 0x07, 0x8A, 0x01, 0x7A, 0x08, 0x3F, 0x81, 0x01, 0x08, 0x0E,
+ 0x9A, 0x01, 0x08, 0x25, 0xAA, 0x01, 0x08, 0x17, 0xBA, 0x01, 0x08, 0x3E, 0xE2, 0x01, 0x08, 0x11,
+ 0xEA, 0x01, 0x08, 0x19, 0xFA, 0x01, 0x08, 0x41, 0xB0, 0x01, 0xD7, 0x64, 0xD6, 0x6E, 0x37, 0x46,
+ 0x07, 0x3D, 0xA1, 0xA8, 0x65, 0x2F, 0x34, 0x01, 0x83, 0xBE, 0x2E, 0x87, 0x3C, 0x64, 0x71, 0x6E,
+ 0xA3, 0xE7, 0xCC, 0xB7, 0x8E, 0x6D, 0xA7, 0xE2, 0xFD, 0x13, 0xBC, 0x9A, 0x51, 0x7D, 0xF2, 0xE9,
+ 0x17, 0x8F, 0x33, 0x91, 0x28, 0xDB, 0xA1, 0x22, 0x5F, 0xB3, 0x14, 0x65, 0xE9, 0x57, 0x92, 0xAC,
+ 0x33, 0xC5, 0xF8, 0x3E, 0x37, 0x35, 0x00, 0x88, 0x1C, 0x96, 0x62, 0x97, 0x17, 0x09, 0xA5, 0x3F,
+ 0x42, 0x18, 0x98, 0xD5, 0x45, 0x96, 0x1D, 0x0A, 0x46, 0x2C, 0xB9, 0x94, 0xFE, 0x35, 0xF7, 0x00,
+ 0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x1A, 0xD0, 0xA2, 0xD9, 0x95, 0x6B, 0xDC, 0x69, 0xEA, 0x2D,
+ 0x52, 0xB0, 0x43, 0xA8, 0x7C, 0xA9, 0x32, 0x0E, 0x01, 0x00, 0x09,
};
// This function can be used to generate textual representation of vector<uint8_t> like you see above.
@@ -174,6 +175,7 @@ std::string FormatBytesFromBuffer(std::vector<uint8_t> const & buffer)
}
auto const kDefaultLang = StringUtf8Multilang::kDefaultCode;
+auto const kEnLang = StringUtf8Multilang::kEnglishCode;
auto const kRuLang = static_cast<int8_t>(8);
kml::FileData GenerateKmlFileData()
@@ -184,22 +186,29 @@ kml::FileData GenerateKmlFileData()
result.m_categoryData.m_name[kRuLang] = "Тестовая категория";
result.m_categoryData.m_description[kDefaultLang] = "Test description";
result.m_categoryData.m_description[kRuLang] = "Тестовое описание";
+ result.m_categoryData.m_annotation[kDefaultLang] = "Test annotation";
+ result.m_categoryData.m_annotation[kEnLang] = "Test annotation";
+ result.m_categoryData.m_imageUrl = "https://localhost/123.png";
result.m_categoryData.m_visible = true;
result.m_categoryData.m_authorName = "Maps.Me";
result.m_categoryData.m_authorId = "12345";
+ result.m_categoryData.m_rating = 8.9;
+ result.m_categoryData.m_reviewsNumber = 567;
result.m_categoryData.m_lastModified = std::chrono::system_clock::from_time_t(1000);
result.m_categoryData.m_accessRules = kml::AccessRules::Public;
result.m_categoryData.m_tags = {"mountains", "ski", "snowboard"};
- result.m_categoryData.m_toponyms = {"Georgia", "Gudauri"};
+ result.m_categoryData.m_cities = {m2::PointD(35.0, 56.0), m2::PointD(20.0, 68.0)};
result.m_categoryData.m_languageCodes = {1, 2, 8};
+ result.m_categoryData.m_properties = {{"property1", "value1"}, {"property2", "value2"}};
kml::BookmarkData bookmarkData;
- bookmarkData.m_id = 10;
bookmarkData.m_name[kDefaultLang] = "Test bookmark";
bookmarkData.m_name[kRuLang] = "Тестовая метка";
bookmarkData.m_description[kDefaultLang] = "Test bookmark description";
bookmarkData.m_description[kRuLang] = "Тестовое описание метки";
- bookmarkData.m_types = {8, 13, 34, 565};
+ bookmarkData.m_featureTypes = {8, 13, 34, 565};
+ bookmarkData.m_featureName[kDefaultLang] = "Гостиница Москва";
+ bookmarkData.m_featureName[kEnLang] = "Moscow Inn Hotel";
bookmarkData.m_color = {kml::PredefinedColor::Blue, 0};
bookmarkData.m_icon = kml::BookmarkIcon::None;
bookmarkData.m_viewportScale = 15;
@@ -209,7 +218,6 @@ kml::FileData GenerateKmlFileData()
result.m_bookmarksData.emplace_back(std::move(bookmarkData));
kml::TrackData trackData;
- trackData.m_id = 121;
trackData.m_localId = 0;
trackData.m_name[kDefaultLang] = "Test track";
trackData.m_name[kRuLang] = "Тестовый трек";
@@ -292,26 +300,37 @@ char const * kGeneratedKml =
" <mwm:name>\n"
" <mwm:lang code=\"ru\">Тестовая категория</mwm:lang>\n"
" </mwm:name>\n"
+ " <mwm:annotation>\n"
+ " <mwm:lang code=\"en\">Test annotation</mwm:lang>\n"
+ " <mwm:lang code=\"default\">Test annotation</mwm:lang>\n"
+ " </mwm:annotation>\n"
" <mwm:description>\n"
" <mwm:lang code=\"ru\">Тестовое описание</mwm:lang>\n"
" </mwm:description>\n"
+ " <mwm:imageUrl>https://localhost/123.png</mwm:imageUrl>\n"
" <mwm:author id=\"12345\">Maps.Me</mwm:author>\n"
" <mwm:lastModified>1970-01-01T00:16:40Z</mwm:lastModified>\n"
+ " <mwm:rating>8.9</mwm:rating>\n"
+ " <mwm:reviewsNumber>567</mwm:reviewsNumber>\n"
" <mwm:accessRules>Public</mwm:accessRules>\n"
" <mwm:tags>\n"
" <mwm:value>mountains</mwm:value>\n"
" <mwm:value>ski</mwm:value>\n"
" <mwm:value>snowboard</mwm:value>\n"
" </mwm:tags>\n"
- " <mwm:toponyms>\n"
- " <mwm:value>Georgia</mwm:value>\n"
- " <mwm:value>Gudauri</mwm:value>\n"
- " </mwm:toponyms>\n"
+ " <mwm:cities>\n"
+ " <mwm:value>35,48.757959</mwm:value>\n"
+ " <mwm:value>20,56.056771</mwm:value>\n"
+ " </mwm:cities>\n"
" <mwm:languageCodes>\n"
" <mwm:value>en</mwm:value>\n"
" <mwm:value>ja</mwm:value>\n"
" <mwm:value>ru</mwm:value>\n"
" </mwm:languageCodes>\n"
+ " <mwm:properties>\n"
+ " <mwm:value key=\"property1\">value1</mwm:value>\n"
+ " <mwm:value key=\"property2\">value2</mwm:value>\n"
+ " </mwm:properties>\n"
" </ExtendedData>\n"
" <Placemark>\n"
" <name>Test bookmark</name>\n"
@@ -326,12 +345,16 @@ char const * kGeneratedKml =
" <mwm:description>\n"
" <mwm:lang code=\"ru\">Тестовое описание метки</mwm:lang>\n"
" </mwm:description>\n"
- " <mwm:types>\n"
+ " <mwm:featureTypes>\n"
" <mwm:value>8</mwm:value>\n"
" <mwm:value>13</mwm:value>\n"
" <mwm:value>34</mwm:value>\n"
" <mwm:value>565</mwm:value>\n"
- " </mwm:types>\n"
+ " </mwm:featureTypes>\n"
+ " <mwm:featureName>\n"
+ " <mwm:lang code=\"en\">Moscow Inn Hotel</mwm:lang>\n"
+ " <mwm:lang code=\"default\">Гостиница Москва</mwm:lang>\n"
+ " </mwm:featureName>\n"
" <mwm:scale>15</mwm:scale>\n"
" <mwm:boundTracks>\n"
" <mwm:value>0</mwm:value>\n"
@@ -593,6 +616,15 @@ UNIT_TEST(Kml_Serialization_Text_File)
TEST(false, ("Exception raised", exc.what()));
}
+// TODO: uncomment to output KML to the log.
+// std::string buffer;
+// {
+// kml::SerializerKml ser(data);
+// MemWriter<decltype(buffer)> sink(buffer);
+// ser.Serialize(sink);
+// }
+// LOG(LINFO, (buffer));
+
kml::FileData dataFromFile;
try
{
@@ -604,6 +636,7 @@ UNIT_TEST(Kml_Serialization_Text_File)
{
TEST(false, ("Exception raised", exc.what()));
}
+ TEST_EQUAL(dataFromFile, data, ());
kml::FileData dataFromMemory;
{
@@ -611,6 +644,5 @@ UNIT_TEST(Kml_Serialization_Text_File)
MemReader reader(kGeneratedKml, strlen(kGeneratedKml));
des.Deserialize(reader);
}
-
- TEST_EQUAL(dataFromFile, dataFromMemory, ());
+ TEST_EQUAL(dataFromMemory, data, ());
}
diff --git a/kml/serdes.cpp b/kml/serdes.cpp
index 99f9c33667..82a37367cd 100644
--- a/kml/serdes.cpp
+++ b/kml/serdes.cpp
@@ -130,6 +130,9 @@ uint32_t ToRGBA(Channel red, Channel green, Channel blue, Channel alpha)
void SaveStringWithCDATA(KmlWriter::WriterWrapper & writer, std::string const & s)
{
+ if (s.empty())
+ return;
+
// According to kml/xml spec, we need to escape special symbols with CDATA.
if (s.find_first_of("<&") != std::string::npos)
writer << "<![CDATA[" << s << "]]>";
@@ -177,7 +180,7 @@ void SaveLocalizableString(KmlWriter::WriterWrapper & writer, LocalizableString
writer << offsetStr << "<mwm:" << tagName << ">\n";
for (auto const & s : str)
{
- if (s.first == kDefaultLang)
+ if (s.first == kDefaultLang && (tagName == "name" || tagName == "description"))
continue;
writer << offsetStr << kIndent2 << "<mwm:lang code=\""
@@ -205,26 +208,84 @@ void SaveStringsArray(KmlWriter::WriterWrapper & writer,
writer << offsetStr << "</mwm:" << tagName << ">\n";
}
+void SavePointsArray(KmlWriter::WriterWrapper & writer,
+ std::vector<m2::PointD> const & pointsArray,
+ std::string const & tagName, std::string const & offsetStr)
+{
+ if (pointsArray.empty())
+ return;
+
+ writer << offsetStr << "<mwm:" << tagName << ">\n";
+ for (auto const & p : pointsArray)
+ {
+ writer << offsetStr << kIndent2 << "<mwm:value>";
+ writer << PointToString(p);
+ writer << "</mwm:value>\n";
+ }
+ writer << offsetStr << "</mwm:" << tagName << ">\n";
+}
+
+void SaveStringsMap(KmlWriter::WriterWrapper & writer,
+ std::map<std::string, std::string> const & stringsMap,
+ std::string const & tagName, std::string const & offsetStr)
+{
+ if (stringsMap.empty())
+ return;
+
+ writer << offsetStr << "<mwm:" << tagName << ">\n";
+ for (auto const & p : stringsMap)
+ {
+ writer << offsetStr << kIndent2 << "<mwm:value key=\"" << p.first << "\">";
+ SaveStringWithCDATA(writer, p.second);
+ writer << "</mwm:value>\n";
+ }
+ writer << offsetStr << "</mwm:" << tagName << ">\n";
+}
+
void SaveCategoryExtendedData(KmlWriter::WriterWrapper & writer, CategoryData const & categoryData)
{
writer << kIndent2 << kExtendedDataHeader;
+
SaveLocalizableString(writer, categoryData.m_name, "name", kIndent4);
+ SaveLocalizableString(writer, categoryData.m_annotation, "annotation", kIndent4);
SaveLocalizableString(writer, categoryData.m_description, "description", kIndent4);
+
+ if (!categoryData.m_imageUrl.empty())
+ writer << kIndent4 << "<mwm:imageUrl>" << categoryData.m_imageUrl << "</mwm:imageUrl>\n";
+
if (!categoryData.m_authorId.empty() || !categoryData.m_authorName.empty())
{
writer << kIndent4 << "<mwm:author id=\"" << categoryData.m_authorId << "\">";
SaveStringWithCDATA(writer, categoryData.m_authorName);
writer << "</mwm:author>\n";
}
+
if (categoryData.m_lastModified != Timestamp())
{
writer << kIndent4 << "<mwm:lastModified>" << TimestampToString(categoryData.m_lastModified)
<< "</mwm:lastModified>\n";
}
+
+ double constexpr kEps = 1e-5;
+ if (fabs(categoryData.m_rating) > kEps)
+ {
+ writer << kIndent4 << "<mwm:rating>" << strings::to_string(categoryData.m_rating)
+ << "</mwm:rating>\n";
+ }
+
+ if (categoryData.m_reviewsNumber > 0)
+ {
+ writer << kIndent4 << "<mwm:reviewsNumber>"
+ << strings::to_string(categoryData.m_reviewsNumber) << "</mwm:reviewsNumber>\n";
+ }
+
writer << kIndent4 << "<mwm:accessRules>" << DebugPrint(categoryData.m_accessRules)
<< "</mwm:accessRules>\n";
+
SaveStringsArray(writer, categoryData.m_tags, "tags", kIndent4);
- SaveStringsArray(writer, categoryData.m_toponyms, "toponyms", kIndent4);
+
+ SavePointsArray(writer, categoryData.m_cities, "cities", kIndent4);
+
std::vector<std::string> languageCodes;
languageCodes.reserve(categoryData.m_languageCodes.size());
for (auto const & lang : categoryData.m_languageCodes)
@@ -234,6 +295,9 @@ void SaveCategoryExtendedData(KmlWriter::WriterWrapper & writer, CategoryData co
languageCodes.push_back(std::move(str));
}
SaveStringsArray(writer, languageCodes, "languageCodes", kIndent4);
+
+ SaveStringsMap(writer, categoryData.m_properties, "properties", kIndent4);
+
writer << kIndent2 << kExtendedDataFooter;
}
@@ -261,8 +325,9 @@ void SaveCategoryData(KmlWriter::WriterWrapper & writer, CategoryData const & ca
void SaveBookmarkExtendedData(KmlWriter::WriterWrapper & writer, BookmarkData const & bookmarkData)
{
if (bookmarkData.m_name.size() < 2 && bookmarkData.m_description.size() < 2 &&
- bookmarkData.m_viewportScale == 0 && bookmarkData.m_icon == BookmarkIcon::None &&
- bookmarkData.m_types.empty() && bookmarkData.m_boundTracks.empty())
+ bookmarkData.m_featureName.empty() && bookmarkData.m_viewportScale == 0 &&
+ bookmarkData.m_icon == BookmarkIcon::None && bookmarkData.m_featureTypes.empty() &&
+ bookmarkData.m_boundTracks.empty())
{
return;
}
@@ -272,10 +337,13 @@ void SaveBookmarkExtendedData(KmlWriter::WriterWrapper & writer, BookmarkData co
SaveLocalizableString(writer, bookmarkData.m_description, "description", kIndent6);
std::vector<std::string> types;
- types.reserve(bookmarkData.m_types.size());
- for (auto const & t : bookmarkData.m_types)
+ types.reserve(bookmarkData.m_featureTypes.size());
+ for (auto const & t : bookmarkData.m_featureTypes)
types.push_back(strings::to_string(t));
- SaveStringsArray(writer, types, "types", kIndent6);
+ SaveStringsArray(writer, types, "featureTypes", kIndent6);
+
+ if (!bookmarkData.m_featureName.empty())
+ SaveLocalizableString(writer, bookmarkData.m_featureName, "featureName", kIndent6);
if (bookmarkData.m_viewportScale != 0)
{
@@ -442,7 +510,8 @@ void KmlParser::ResetPoint()
m_mapStyleId.clear();
m_styleUrlKey.clear();
- m_types.clear();
+ m_featureTypes.clear();
+ m_featureName.clear();
m_boundTracks.clear();
m_localId = 0;
m_trackLayers.clear();
@@ -571,6 +640,8 @@ void KmlParser::AddAttr(std::string const & attr, std::string const & value)
m_attrCode = StringUtf8Multilang::GetLangIndex(value);
else if (attrInLowerCase == "id")
m_attrId = value;
+ else if (attrInLowerCase == "key")
+ m_attrKey = value;
}
bool KmlParser::IsValidAttribute(std::string const & type, std::string const & value,
@@ -596,15 +667,16 @@ void KmlParser::Pop(std::string const & tag)
if (GEOMETRY_TYPE_POINT == m_geometryType)
{
BookmarkData data;
- data.m_name = m_name;
- data.m_description = m_description;
+ data.m_name = std::move(m_name);
+ data.m_description = std::move(m_description);
data.m_color.m_predefinedColor = m_predefinedColor;
data.m_color.m_rgba = m_color;
data.m_icon = m_icon;
data.m_viewportScale = m_viewportScale;
data.m_timestamp = m_timestamp;
data.m_point = m_org;
- data.m_types = std::move(m_types);
+ data.m_featureTypes = std::move(m_featureTypes);
+ data.m_featureName = std::move(m_featureName);
data.m_boundTracks = std::move(m_boundTracks);
m_data.m_bookmarksData.push_back(std::move(data));
}
@@ -612,8 +684,8 @@ void KmlParser::Pop(std::string const & tag)
{
TrackData data;
data.m_localId = m_localId;
- data.m_name = m_name;
- data.m_description = m_description;
+ data.m_name = std::move(m_name);
+ data.m_description = std::move(m_description);
data.m_layers = std::move(m_trackLayers);
data.m_timestamp = m_timestamp;
data.m_points = m_points;
@@ -688,13 +760,29 @@ void KmlParser::CharData(std::string value)
if (value == "Public")
m_data.m_categoryData.m_accessRules = AccessRules::Public;
}
+ else if (currTag == "mwm:imageUrl")
+ {
+ m_data.m_categoryData.m_imageUrl = value;
+ }
+ else if (currTag == "mwm:rating")
+ {
+ if (!strings::to_double(value, m_data.m_categoryData.m_rating))
+ m_data.m_categoryData.m_rating = 0.0;
+ }
+ else if (currTag == "mwm:reviewsNumber")
+ {
+ if (!strings::to_uint(value, m_data.m_categoryData.m_reviewsNumber))
+ m_data.m_categoryData.m_reviewsNumber = 0;
+ }
}
else if (pppTag == kDocument && ppTag == kExtendedData && currTag == "mwm:lang")
{
- if (prevTag == "mwm:name" && m_attrCode > 0)
+ if (prevTag == "mwm:name" && m_attrCode >= 0)
m_data.m_categoryData.m_name[m_attrCode] = value;
- else if (prevTag == "mwm:description" && m_attrCode > 0)
+ else if (prevTag == "mwm:description" && m_attrCode >= 0)
m_data.m_categoryData.m_description[m_attrCode] = value;
+ else if (prevTag == "mwm:annotation" && m_attrCode >= 0)
+ m_data.m_categoryData.m_annotation[m_attrCode] = value;
m_attrCode = StringUtf8Multilang::kUnsupportedLanguageCode;
}
else if (pppTag == kDocument && ppTag == kExtendedData && currTag == "mwm:value")
@@ -703,9 +791,11 @@ void KmlParser::CharData(std::string value)
{
m_data.m_categoryData.m_tags.push_back(value);
}
- else if (prevTag == "mwm:toponyms")
+ else if (prevTag == "mwm:cities")
{
- m_data.m_categoryData.m_toponyms.push_back(value);
+ m2::PointD pt;
+ if (ParsePoint(value, ", \n\r\t", pt))
+ m_data.m_categoryData.m_cities.push_back(pt);
}
else if (prevTag == "mwm:languageCodes")
{
@@ -713,6 +803,11 @@ void KmlParser::CharData(std::string value)
if (lang != StringUtf8Multilang::kUnsupportedLanguageCode)
m_data.m_categoryData.m_languageCodes.push_back(lang);
}
+ else if (prevTag == "mwm:properties" && !m_attrKey.empty())
+ {
+ m_data.m_categoryData.m_properties[m_attrKey] = value;
+ m_attrKey.clear();
+ }
}
else if (prevTag == kPlacemark)
{
@@ -845,17 +940,19 @@ void KmlParser::CharData(std::string value)
{
if (currTag == "mwm:lang")
{
- if (prevTag == "mwm:name" && m_attrCode > 0)
+ if (prevTag == "mwm:name" && m_attrCode >= 0)
m_name[m_attrCode] = value;
- else if (prevTag == "mwm:description" && m_attrCode > 0)
+ else if (prevTag == "mwm:description" && m_attrCode >= 0)
m_description[m_attrCode] = value;
+ else if (prevTag == "mwm:featureName" && m_attrCode >= 0)
+ m_featureName[m_attrCode] = value;
m_attrCode = StringUtf8Multilang::kUnsupportedLanguageCode;
}
else if (currTag == "mwm:value")
{
uint32_t i;
- if (prevTag == "mwm:types" && strings::to_uint(value, i))
- m_types.push_back(i);
+ if (prevTag == "mwm:featureTypes" && strings::to_uint(value, i))
+ m_featureTypes.push_back(i);
else if (prevTag == "mwm:boundTracks" && strings::to_uint(value, i))
m_boundTracks.push_back(static_cast<LocalId>(i));
}
diff --git a/kml/serdes.hpp b/kml/serdes.hpp
index 7aea2c7de4..cbe4a63f64 100644
--- a/kml/serdes.hpp
+++ b/kml/serdes.hpp
@@ -102,6 +102,7 @@ private:
int8_t m_attrCode;
std::string m_attrId;
+ std::string m_attrKey;
LocalizableString m_name;
LocalizableString m_description;
@@ -109,7 +110,8 @@ private:
Timestamp m_timestamp;
m2::PointD m_org;
uint8_t m_viewportScale;
- std::vector<uint32_t> m_types;
+ std::vector<uint32_t> m_featureTypes;
+ LocalizableString m_featureName;
std::vector<LocalId> m_boundTracks;
LocalId m_localId;
BookmarkIcon m_icon;
diff --git a/kml/type_utils.hpp b/kml/type_utils.hpp
index 3388388779..85782b16e8 100644
--- a/kml/type_utils.hpp
+++ b/kml/type_utils.hpp
@@ -16,6 +16,7 @@ using Timestamp = std::chrono::time_point<std::chrono::system_clock>;
using LocalizableString = std::unordered_map<int8_t, std::string>;
using LocalizableStringSubIndex = std::map<int8_t, uint32_t>;
using LocalizableStringIndex = std::vector<LocalizableStringSubIndex>;
+using Properties = std::map<std::string, std::string>;
using CategoryId = uint64_t;
using BookmarkId = uint64_t;
using TrackId = uint64_t;
@@ -60,6 +61,10 @@ inline bool IsEqual(Timestamp const & ts1, Timestamp const & ts2)
uint32_t constexpr kEmptyStringId = 0;
double constexpr kMinLineWidth = 0.0;
double constexpr kMaxLineWidth = 100.0;
+uint32_t constexpr kLineWidthBits = 30;
+double constexpr kMinRating = 0.0;
+double constexpr kMaxRating = 10.0;
+uint32_t constexpr kRatingBits = 30;
#define DECLARE_COLLECTABLE(IndexType, ...) \
IndexType m_collectionIndex; \
diff --git a/kml/types.hpp b/kml/types.hpp
index 5b6b4711a8..2389b08c3c 100644
--- a/kml/types.hpp
+++ b/kml/types.hpp
@@ -102,7 +102,8 @@ struct BookmarkData
DECLARE_VISITOR_AND_DEBUG_PRINT(BookmarkData, visitor(m_id, "id"),
visitor(m_name, "name"),
visitor(m_description, "description"),
- visitor(m_types, "types"),
+ visitor(m_featureTypes, "featureTypes"),
+ visitor(m_featureName, "featureName"),
visitor(m_color, "color"),
visitor(m_icon, "icon"),
visitor(m_viewportScale, "viewportScale"),
@@ -111,7 +112,7 @@ struct BookmarkData
visitor(m_boundTracks, "boundTracks"),
VISITOR_COLLECTABLE)
- DECLARE_COLLECTABLE(LocalizableStringIndex, m_name, m_description)
+ DECLARE_COLLECTABLE(LocalizableStringIndex, m_name, m_description, m_featureName)
bool operator==(BookmarkData const & data) const
{
@@ -121,7 +122,9 @@ struct BookmarkData
m_color == data.m_color && m_icon == data.m_icon &&
m_viewportScale == data.m_viewportScale &&
IsEqual(m_timestamp, data.m_timestamp) &&
- m_point.EqualDxDy(data.m_point, kEps) && m_types == data.m_types &&
+ m_point.EqualDxDy(data.m_point, kEps) &&
+ m_featureTypes == data.m_featureTypes &&
+ m_featureName == data.m_featureName &&
m_boundTracks == data.m_boundTracks;
}
@@ -133,8 +136,10 @@ struct BookmarkData
LocalizableString m_name;
// Bookmark's description.
LocalizableString m_description;
- // Bookmark's types.
- std::vector<uint32_t> m_types;
+ // Bound feature's types.
+ std::vector<uint32_t> m_featureTypes;
+ // Bound feature's name.
+ LocalizableString m_featureName;
// Bookmark's color.
ColorData m_color;
// Bookmark's icon.
@@ -210,27 +215,36 @@ struct CategoryData
{
DECLARE_VISITOR_AND_DEBUG_PRINT(CategoryData, visitor(m_id, "id"),
visitor(m_name, "name"),
+ visitor(m_imageUrl, "imageUrl"),
+ visitor(m_annotation, "annotation"),
visitor(m_description, "description"),
visitor(m_visible, "visible"),
visitor(m_authorName, "authorName"),
visitor(m_authorId, "authorId"),
+ visitor(m_rating, "rating"),
+ visitor(m_reviewsNumber, "reviewsNumber"),
visitor(m_lastModified, "lastModified"),
visitor(m_accessRules, "accessRules"),
visitor(m_tags, "tags"),
- visitor(m_toponyms, "toponyms"),
+ visitor(m_cities, "cities"),
visitor(m_languageCodes, "languageCodes"),
+ visitor(m_properties, "properties"),
VISITOR_COLLECTABLE)
- DECLARE_COLLECTABLE(LocalizableStringIndex, m_name, m_description,
- m_authorName, m_authorId, m_tags, m_toponyms)
+ DECLARE_COLLECTABLE(LocalizableStringIndex, m_name, m_annotation, m_description,
+ m_imageUrl, m_authorName, m_authorId, m_tags, m_properties)
bool operator==(CategoryData const & data) const
{
- return m_id == data.m_id && m_name == data.m_name && m_description == data.m_description &&
+ double constexpr kEps = 1e-5;
+ return m_id == data.m_id && m_name == data.m_name && m_imageUrl == data.m_imageUrl &&
+ m_annotation == data.m_annotation && m_description == data.m_description &&
m_visible == data.m_visible && m_accessRules == data.m_accessRules &&
m_authorName == data.m_authorName && m_authorId == data.m_authorId &&
+ fabs(m_rating - data.m_rating) < kEps && m_reviewsNumber == data.m_reviewsNumber &&
IsEqual(m_lastModified, data.m_lastModified) && m_tags == data.m_tags &&
- m_toponyms == data.m_toponyms && m_languageCodes == data.m_languageCodes;
+ IsEqual(m_cities, data.m_cities) && m_languageCodes == data.m_languageCodes &&
+ m_properties == data.m_properties;
}
bool operator!=(CategoryData const & data) const { return !operator==(data); }
@@ -239,6 +253,10 @@ struct CategoryData
CategoryId m_id = kInvalidCategoryId;
// Category's name.
LocalizableString m_name;
+ // Image URL.
+ std::string m_imageUrl;
+ // Category's description.
+ LocalizableString m_annotation;
// Category's description.
LocalizableString m_description;
// Collection visibility.
@@ -249,14 +267,20 @@ struct CategoryData
std::string m_authorId;
// Last modification timestamp.
Timestamp m_lastModified;
+ // Rating.
+ double m_rating = 0.0;
+ // Number of reviews.
+ uint32_t m_reviewsNumber = 0;
// Access rules.
AccessRules m_accessRules = AccessRules::Private;
// Collection of tags.
std::vector<std::string> m_tags;
- // Collection of toponyms.
- std::vector<std::string> m_toponyms;
+ // Collection of cities coordinates.
+ std::vector<m2::PointD> m_cities;
// Language codes.
std::vector<int8_t> m_languageCodes;
+ // Key-value properties.
+ Properties m_properties;
};
struct FileData
diff --git a/kml/visitors.hpp b/kml/visitors.hpp
index 76ea7a6ec5..28ecb51bb6 100644
--- a/kml/visitors.hpp
+++ b/kml/visitors.hpp
@@ -131,6 +131,24 @@ public:
Collect(index, args...);
}
+ template <typename... OtherStrings>
+ void Collect(LocalizableStringIndex & index, Properties const & properties,
+ OtherStrings const & ... args)
+ {
+ index.emplace_back(LocalizableStringSubIndex());
+ auto constexpr kMaxSize = std::numeric_limits<int8_t>::max() - 1;
+ int8_t counter = 0;
+ for (auto const & p : properties)
+ {
+ if (counter >= kMaxSize)
+ break;
+ CollectString(index.back(), counter++, p.first);
+ CollectString(index.back(), counter++, p.second);
+ }
+
+ Collect(index, args...);
+ }
+
template <typename...>
void Collect(LocalizableStringIndex & index) {}
@@ -201,6 +219,18 @@ public:
WriteVarUint(m_sink, ToSecondsSinceEpoch(t));
}
+ void operator()(double d, char const * /* name */ = nullptr)
+ {
+ uint64_t const encoded = DoubleToUint32(d, kMinRating, kMaxRating, kRatingBits);
+ WriteVarUint(m_sink, encoded);
+ }
+
+ void operator()(m2::PointD const & pt, char const * /* name */ = nullptr)
+ {
+ uint64_t const encoded = bits::ZigZagEncode(PointToInt64(pt, POINT_COORD_BITS));
+ WriteVarUint(m_sink, encoded);
+ }
+
template <typename T>
void operator()(std::vector<T> const & vs, char const * /* name */ = nullptr)
{
@@ -227,6 +257,7 @@ public:
SKIP_VISITING(LocalizableString const &)
SKIP_VISITING(std::string const &)
SKIP_VISITING(std::vector<std::string> const &)
+ SKIP_VISITING(Properties const &)
SKIP_VISITING(std::vector<BookmarkData> const &)
SKIP_VISITING(std::vector<TrackData> const &)
@@ -260,7 +291,7 @@ public:
void operator()(double d, char const * /* name */ = nullptr)
{
- uint64_t const encoded = DoubleToUint32(d, kMinLineWidth, kMaxLineWidth, 30 /* coordBits */);
+ uint64_t const encoded = DoubleToUint32(d, kMinLineWidth, kMaxLineWidth, kLineWidthBits);
WriteVarUint(m_sink, encoded);
}
@@ -305,6 +336,7 @@ public:
SKIP_VISITING(LocalizableString const &)
SKIP_VISITING(std::string const &)
SKIP_VISITING(std::vector<std::string> const &)
+ SKIP_VISITING(Properties const &)
private:
Sink & m_sink;
@@ -357,6 +389,18 @@ public:
t = FromSecondsSinceEpoch(v);
}
+ void operator()(double & d, char const * /* name */ = nullptr)
+ {
+ auto const v = ReadVarUint<uint32_t, Source>(m_source);
+ d = Uint32ToDouble(v, kMinRating, kMaxRating, kRatingBits);
+ }
+
+ void operator()(m2::PointD & pt, char const * /* name */ = nullptr)
+ {
+ auto const v = ReadVarUint<uint64_t, Source>(m_source);
+ pt = Int64ToPoint(bits::ZigZagDecode(v), POINT_COORD_BITS);
+ }
+
template <typename T>
void operator()(std::vector<T> & vs, char const * /* name */ = nullptr)
{
@@ -387,6 +431,7 @@ public:
SKIP_VISITING(LocalizableString &)
SKIP_VISITING(std::string &)
SKIP_VISITING(std::vector<std::string> &)
+ SKIP_VISITING(Properties &)
SKIP_VISITING(std::vector<BookmarkData> &)
SKIP_VISITING(std::vector<TrackData> &)
@@ -421,7 +466,7 @@ public:
void operator()(double & d, char const * /* name */ = nullptr)
{
auto const v = ReadVarUint<uint32_t, Source>(m_source);
- d = Uint32ToDouble(v, kMinLineWidth, kMaxLineWidth, 30 /* coordBits */);
+ d = Uint32ToDouble(v, kMinLineWidth, kMaxLineWidth, kLineWidthBits);
}
void operator()(Timestamp & t, char const * /* name */ = nullptr)
@@ -475,6 +520,7 @@ public:
SKIP_VISITING(LocalizableString &)
SKIP_VISITING(std::string &)
SKIP_VISITING(std::vector<std::string> &)
+ SKIP_VISITING(Properties &)
private:
Source & m_source;
@@ -497,7 +543,7 @@ public:
auto subIndex = index[m_counter];
for (auto const & p : subIndex)
- str[p.first] = ExtractString(subIndex, p.second);
+ str[p.first] = ExtractString(p.second);
m_counter++;
Collect(index, args...);
@@ -512,7 +558,7 @@ public:
auto subIndex = index[m_counter];
if (!subIndex.empty())
- str = ExtractString(subIndex, subIndex.begin()->second);
+ str = ExtractString(subIndex.begin()->second);
else
str = {};
@@ -521,7 +567,8 @@ public:
}
template <typename... OtherStrings>
- void Collect(LocalizableStringIndex & index, std::vector<std::string> & stringsArray,
+ void Collect(LocalizableStringIndex & index,
+ std::vector<std::string> & stringsArray,
OtherStrings & ... args)
{
if (!SwitchSubIndexIfNeeded(index))
@@ -530,7 +577,26 @@ public:
auto subIndex = index[m_counter];
stringsArray.reserve(subIndex.size());
for (auto const & p : subIndex)
- stringsArray.emplace_back(ExtractString(subIndex, p.second));
+ stringsArray.emplace_back(ExtractString(p.second));
+
+ m_counter++;
+ Collect(index, args...);
+ }
+
+ template <typename... OtherStrings>
+ void Collect(LocalizableStringIndex & index, Properties & properties,
+ OtherStrings & ... args)
+ {
+ if (!SwitchSubIndexIfNeeded(index))
+ return;
+
+ auto subIndex = index[m_counter];
+ auto const sz = static_cast<int8_t>(subIndex.size() / 2);
+ for (int8_t i = 0; i < sz; i++)
+ {
+ properties.insert(std::make_pair(ExtractString(subIndex[2 * i]),
+ ExtractString(subIndex[2 * i + 1])));
+ }
m_counter++;
Collect(index, args...);
@@ -550,8 +616,7 @@ private:
return m_counter < index.size();
}
- std::string ExtractString(LocalizableStringSubIndex const & subIndex,
- uint32_t stringIndex) const
+ std::string ExtractString(uint32_t stringIndex) const
{
auto const stringsCount = m_textStorage.GetNumStrings();
if (stringIndex >= stringsCount)