diff options
author | Sergey Yershov <yershov@corp.mail.ru> | 2014-12-25 20:32:07 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:35:26 +0300 |
commit | 8f6b34bdb4e0e3ffb4010d5bd44df96bb4467a22 (patch) | |
tree | 2a02f3ce859edf2397c83d1fd2f3e48efa0b9bc0 | |
parent | af6bd463306aad0bc7154d5550a298a104bad143 (diff) |
Moved work with metadata to separated files
-rw-r--r-- | defines.hpp | 4 | ||||
-rw-r--r-- | generator/feature_builder.hpp | 2 | ||||
-rw-r--r-- | generator/feature_sorter.cpp | 38 | ||||
-rw-r--r-- | generator/generator_tests/metadata_test.cpp | 153 | ||||
-rw-r--r-- | generator/osm2meta.cpp | 1 | ||||
-rw-r--r-- | generator/osm2meta.hpp | 111 | ||||
-rw-r--r-- | generator/osm2type.cpp | 42 | ||||
-rw-r--r-- | generator/xml_element.cpp | 51 | ||||
-rw-r--r-- | indexer/feature.cpp | 10 | ||||
-rw-r--r-- | indexer/feature.hpp | 9 | ||||
-rw-r--r-- | indexer/feature_data.cpp | 13 | ||||
-rw-r--r-- | indexer/feature_data.hpp | 51 | ||||
-rw-r--r-- | indexer/feature_loader.cpp | 15 | ||||
-rw-r--r-- | indexer/feature_loader.hpp | 2 | ||||
-rw-r--r-- | indexer/feature_loader_base.cpp | 8 | ||||
-rw-r--r-- | indexer/feature_loader_base.hpp | 6 | ||||
-rw-r--r-- | indexer/feature_meta.cpp | 1 | ||||
-rw-r--r-- | indexer/feature_meta.hpp | 108 | ||||
-rw-r--r-- | indexer/old/feature_loader_101.hpp | 2 |
19 files changed, 454 insertions, 173 deletions
diff --git a/defines.hpp b/defines.hpp index 74defadd37..f051d8b5fa 100644 --- a/defines.hpp +++ b/defines.hpp @@ -12,8 +12,8 @@ #define SEARCH_INDEX_FILE_TAG "sdx" #define HEADER_FILE_TAG "header" #define VERSION_FILE_TAG "version" -#define ADDITIONAL_INFO_FILE_TAG "ainf" -#define ADDITIONAL_INFO_INDEX_FILE_TAG "ainfidx" +#define METADATA_FILE_TAG "meta" +#define METADATA_INDEX_FILE_TAG "metaidx" #define ROUTING_MATRIX_FILE_TAG "mercedes" #define ROUTING_EDGEDATA_FILE_TAG "daewoo" diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index c62e308d7d..dc3de46bb6 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -39,7 +39,7 @@ public: void AddPolygon(vector<m2::PointD> & poly); //@} - inline FeatureParams::AdditionalInfoT const & GetAdditionalInfo() const { return m_params.m_additional_info; } + inline feature::FeatureMetadata const & GetMetadata() const { return m_params.GetMetadata(); } inline feature::EGeomType GetGeomType() const { return m_params.GetGeomType(); } diff --git a/generator/feature_sorter.cpp b/generator/feature_sorter.cpp index 098648c50c..c423f15c9a 100644 --- a/generator/feature_sorter.cpp +++ b/generator/feature_sorter.cpp @@ -90,9 +90,9 @@ namespace feature vector<FileWriter*> m_geoFile, m_trgFile; - unique_ptr<FileWriter> m_AdditionalInfoWriter; + unique_ptr<FileWriter> m_MetadataWriter; - vector<pair<uint32_t, uint32_t>> m_AdditionalInfoIndex; + vector<pair<uint32_t, uint32_t>> m_MetadataIndex; DataHeader m_header; @@ -102,7 +102,7 @@ namespace feature FeaturesCollector2(string const & fName, DataHeader const & header) : FeaturesCollector(fName + DATA_FILE_TAG), m_writer(fName), m_header(header) { - m_AdditionalInfoWriter.reset(new FileWriter(fName + ADDITIONAL_INFO_FILE_TAG)); + m_MetadataWriter.reset(new FileWriter(fName + METADATA_FILE_TAG)); for (size_t i = 0; i < m_header.GetScalesCount(); ++i) { @@ -155,10 +155,10 @@ namespace feature } - FileWriter ainf_index = m_writer.GetWriter(ADDITIONAL_INFO_INDEX_FILE_TAG); - ainf_index.Write(m_AdditionalInfoIndex.data(), m_AdditionalInfoIndex.size()*(sizeof(uint32_t)*2)); - m_AdditionalInfoWriter->Flush(); - m_writer.Write(m_AdditionalInfoWriter->GetName(), ADDITIONAL_INFO_FILE_TAG); + FileWriter metadata_index = m_writer.GetWriter(METADATA_INDEX_FILE_TAG); + metadata_index.Write(m_MetadataIndex.data(), m_MetadataIndex.size()*(sizeof(uint32_t)*2)); + m_MetadataWriter->Flush(); + m_writer.Write(m_MetadataWriter->GetName(), METADATA_FILE_TAG); m_writer.Finish(); @@ -526,31 +526,17 @@ namespace feature uint32_t const ftID = WriteFeatureBase(holder.m_buffer.m_buffer, fb); - ProcessFeatureAdditionalInfo(ftID, fb); + if (!fb.GetMetadata().Empty()) { + uint64_t offset = m_MetadataWriter->Pos(); + m_MetadataIndex.push_back(make_pair(ftID, static_cast<uint32_t>(offset))); + fb.GetMetadata().SerializeToMWM(*m_MetadataWriter); + } uint64_t const osmID = fb.GetWayIDForRouting(); if (osmID != 0) m_osm2ft.Add(make_pair(osmID, ftID)); } } - - void ProcessFeatureAdditionalInfo(uint32_t const ftID, FeatureBuilder2 const & f) - { - FeatureParams::AdditionalInfoT const & ainf = f.GetAdditionalInfo(); - if (ainf.size()) - { - uint64_t offset = m_AdditionalInfoWriter->Pos(); - m_AdditionalInfoIndex.push_back(make_pair(ftID, static_cast<uint32_t>(offset))); - for (auto const & e: ainf) - { - uint8_t last_key_mark = (&e == &(*ainf.crbegin())) << 7; /// set high bit (0x80) if it last element - uint8_t elem[2] = {static_cast<uint8_t>(e.first | last_key_mark), numeric_limits<uint8_t>::max()}; - m_AdditionalInfoWriter->Write(elem, sizeof(elem)); - m_AdditionalInfoWriter->Write(e.second.data(), elem[1]); - } - } - } - }; /// Simplify geometry for the upper scale. diff --git a/generator/generator_tests/metadata_test.cpp b/generator/generator_tests/metadata_test.cpp new file mode 100644 index 0000000000..a427f2d16f --- /dev/null +++ b/generator/generator_tests/metadata_test.cpp @@ -0,0 +1,153 @@ +#include "../../testing/testing.hpp" +#include "../../base/logging.hpp" + +#include "../../indexer/classificator_loader.hpp" +#include "../../generator/osm2meta.hpp" +#include "../../coding/writer.hpp" +#include "../../coding/reader.hpp" + +UNIT_TEST(Metadata_ValidateAndFormat_stars) +{ + FeatureParams params; + MetadataTagProcessor p(params); + + // ignore incorrect values + p("stars","0"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","-1"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","aasdasdas"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","8"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","10"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","910"); + TEST(params.GetMetadata().Empty(), ()); + p("stars","100"); + TEST(params.GetMetadata().Empty(), ()); + + // check correct values + p("stars","1"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "1", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","2"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "2", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","3"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "3", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","4"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "4", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","5"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "5", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","6"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "6", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","7"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "7", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + // check almost correct values + p("stars","4+"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "4", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + + p("stars","5s"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "5", ()) + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_STARS); + +} + +UNIT_TEST(Metadata_ValidateAndFormat_operator) +{ + classificator::Load(); + Classificator const & c = classif(); + uint32_t const type_atm = c.GetTypeByPath({ "amenity", "atm" }); + uint32_t const type_fuel = c.GetTypeByPath({ "amenity", "fuel" }); + + FeatureParams params; + MetadataTagProcessor p(params); + + // ignore tag 'operator' if feature have inappropriate type + p("operator","Some"); + TEST(params.GetMetadata().Empty(), ()); + + params.SetType(type_atm); + p("operator","Some"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_OPERATOR), "Some", ()); + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_OPERATOR); + + params.SetType(type_fuel); + p("operator","Some"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_OPERATOR), "Some", ()); + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_OPERATOR); + + params.SetType(type_atm); + params.AddType(type_fuel); + p("operator","Some"); + TEST_EQUAL(params.GetMetadata().Get(feature::FeatureMetadata::FMD_OPERATOR), "Some", ()); + params.GetMetadata().Drop(feature::FeatureMetadata::FMD_OPERATOR); +} + +UNIT_TEST(Metadata_ReadWrite_Intermediate) +{ + FeatureParams params; + FeatureParams params_test; + MetadataTagProcessor p(params); + + vector<char> buffer; + MemWriter<vector<char> > writer(buffer); + + p("stars","3"); + p("phone","+123456789"); + p("opening_hours","24/7"); + p("cuisine","regional"); + p("operator","Unused"); + params.GetMetadata().Serialize(writer); + + MemReader reader(buffer.data(), buffer.size()); + ReaderSource<MemReader> src(reader); + params_test.GetMetadata().Deserialize(src); + + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "3", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_PHONE_NUMBER), "+123456789", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_OPEN_HOURS), "24/7", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_CUISINE), "regional", ()) + TEST(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_OPERATOR).empty(), ()) +} + +UNIT_TEST(Metadata_ReadWrite_MWM) +{ + FeatureParams params; + FeatureParams params_test; + MetadataTagProcessor p(params); + + vector<char> buffer; + MemWriter<vector<char> > writer(buffer); + + p("stars","3"); + p("phone","+123456789"); + p("opening_hours","24/7"); + p("cuisine","regional"); + p("operator","Unused"); + params.GetMetadata().SerializeToMWM(writer); + + MemReader reader(buffer.data(), buffer.size()); + ReaderSource<MemReader> src(reader); + params_test.GetMetadata().DeserializeFromMWM(src); + + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_STARS), "3", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_PHONE_NUMBER), "+123456789", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_OPEN_HOURS), "24/7", ()) + TEST_EQUAL(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_CUISINE), "regional", ()) + TEST(params_test.GetMetadata().Get(feature::FeatureMetadata::FMD_OPERATOR).empty(), ()) +} diff --git a/generator/osm2meta.cpp b/generator/osm2meta.cpp new file mode 100644 index 0000000000..dc1bd346e1 --- /dev/null +++ b/generator/osm2meta.cpp @@ -0,0 +1 @@ +#include "osm2meta.hpp" diff --git a/generator/osm2meta.hpp b/generator/osm2meta.hpp new file mode 100644 index 0000000000..5249ded5aa --- /dev/null +++ b/generator/osm2meta.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include "../indexer/feature_data.hpp" +#include "../indexer/classificator.hpp" + +#include "../std/string.hpp" + +class MetadataTagProcessor +{ + FeatureParams & m_params; + +public: + typedef bool result_type; + + MetadataTagProcessor(FeatureParams ¶ms) + : m_params(params) + { + } + + bool operator() (string const & k, string const & v) + { + + if (v.empty()) + return false; + + if (k == "cuisine") + { + string const & value = ValidateAndFormat_cuisine(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_CUISINE, value); + } + else if (k == "phone") + { + string const & value = ValidateAndFormat_phone(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_PHONE_NUMBER, value); + } + else if (k == "stars") + { + string const & value = ValidateAndFormat_stars(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_STARS, value); + } + else if (k == "url") + { + string const & value = ValidateAndFormat_url(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_URL, value); + } + else if (k == "operator") + { + string const & value = ValidateAndFormat_operator(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_OPERATOR, value); + } + else if (k == "opening_hours") + { + string const & value = ValidateAndFormat_opening_hours(v); + if (!value.empty()) + m_params.GetMetadata().Add(feature::FeatureMetadata::FMD_OPEN_HOURS, value); + } + return false; + } +protected: + /// Validation and formatting functions + + string ValidateAndFormat_stars(string const & v) const + { + if (v.empty()) + return string(); + + // we accepting stars from 1 to 7 + if (v[0] <= '0' || v[0] > '7') + return string(); + + // ignore numbers large then 9 + if (v.size() > 1 && (v[1] >= '0' && v[1] <= '9')) + return string(); + + return string(1, v[0]); + } + + string ValidateAndFormat_cuisine(string const & v) const + { + return v; + } + string ValidateAndFormat_operator(string const & v) const + { + Classificator const & c = classif(); + uint32_t const type_atm = c.GetTypeByPath({ "amenity", "atm" }); + uint32_t const type_fuel = c.GetTypeByPath({ "amenity", "fuel" }); + + if (!(m_params.IsTypeExist(type_atm) || m_params.IsTypeExist(type_fuel))) + return string(); + + return v; + } + string ValidateAndFormat_url(string const & v) const + { + return v; + } + string ValidateAndFormat_phone(string const & v) const + { + return v; + } + string ValidateAndFormat_opening_hours(string const & v) const + { + return v; + } + +}; diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp index 70358c21fc..a31b56c766 100644 --- a/generator/osm2type.cpp +++ b/generator/osm2type.cpp @@ -1,4 +1,5 @@ #include "osm2type.hpp" +#include "osm2meta.hpp" #include "xml_element.hpp" #include "../indexer/classificator.hpp" @@ -101,44 +102,6 @@ namespace ftype } }; - class do_find_additional_info - { - size_t & m_count; - FeatureParams & m_params; - - public: - typedef bool result_type; - - do_find_additional_info(size_t &count, FeatureParams ¶ms) - : m_count(count), m_params(params) - { - m_count = 0; - } - - bool operator() (string const & k, string const & v) - { - ++m_count; - - if (v.empty()) - return false; - - if (k == "cuisine") - { - m_params.AddAdditionalInfo(FeatureParams::AIT_CUISINE, v); - } - else if (k == "phone") - { - m_params.AddAdditionalInfo(FeatureParams::AIT_PHONE_NUMBER, v); - } - else if (k == "opening_hours") - { - m_params.AddAdditionalInfo(FeatureParams::AIT_OPEN_HOURS, v); - } - return false; - } - - }; - class do_find_name { set<string> m_savedNames; @@ -397,7 +360,6 @@ namespace ftype { size_t count; for_each_tag(p, do_find_name(count, params)); - for_each_tag(p, do_find_additional_info(count, params)); return count; } @@ -574,6 +536,8 @@ namespace ftype } params.FinishAddingTypes(); + /// Collect addidtional information about feature such as start for hotels, opening hours and etc. + for_each_tag(p, MetadataTagProcessor(params)); } uint32_t GetBoundaryType2() diff --git a/generator/xml_element.cpp b/generator/xml_element.cpp index b37bf9e199..72af0c9a21 100644 --- a/generator/xml_element.cpp +++ b/generator/xml_element.cpp @@ -78,35 +78,36 @@ void BaseOSMParser::Pop(string const &) } } - -struct StdinReader +namespace { - uint64_t Read(char * buffer, uint64_t bufferSize) + struct StdinReader { - return fread(buffer, sizeof(char), bufferSize, stdin); - } -}; - -struct FileReader -{ - FILE * m_file; - - FileReader(string const & filename) - { - m_file = fopen(filename.c_str(), "rb"); - } + uint64_t Read(char * buffer, uint64_t bufferSize) + { + return fread(buffer, sizeof(char), bufferSize, stdin); + } + }; - ~FileReader() + struct FileReader { - fclose(m_file); - } - - uint64_t Read(char * buffer, uint64_t bufferSize) - { - return fread(buffer, sizeof(char), bufferSize, m_file); - } -}; - + FILE * m_file; + + FileReader(string const & filename) + { + m_file = fopen(filename.c_str(), "rb"); + } + + ~FileReader() + { + fclose(m_file); + } + + uint64_t Read(char * buffer, uint64_t bufferSize) + { + return fread(buffer, sizeof(char), bufferSize, m_file); + } + }; +} void ParseXMLFromStdIn(BaseOSMParser & parser) { diff --git a/indexer/feature.cpp b/indexer/feature.cpp index 4d2827d98f..6877d86525 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -82,7 +82,7 @@ void FeatureType::Deserialize(feature::LoaderBase * pLoader, BufferT buffer) m_pLoader->InitFeature(this); - m_bHeader2Parsed = m_bPointsParsed = m_bTrianglesParsed = m_bAdditionalInfoParsed = false; + m_bHeader2Parsed = m_bPointsParsed = m_bTrianglesParsed = m_bMetadataParsed = false; m_innerStats.MakeZero(); } @@ -137,12 +137,12 @@ uint32_t FeatureType::ParseTriangles(int scale) const return sz; } -void FeatureType::ParseAdditionalInfo() const +void FeatureType::ParseMetadata() const { - if (m_bAdditionalInfoParsed) return; + if (m_bMetadataParsed) return; - m_pLoader->ParseAdditionalInfo(); - m_bAdditionalInfoParsed = true; + m_pLoader->ParseMetadata(); + m_bMetadataParsed = true; } diff --git a/indexer/feature.hpp b/indexer/feature.hpp index 8db0e00856..dc7ee5650e 100644 --- a/indexer/feature.hpp +++ b/indexer/feature.hpp @@ -164,7 +164,7 @@ public: uint32_t ParseGeometry(int scale) const; uint32_t ParseTriangles(int scale) const; - void ParseAdditionalInfo() const; + void ParseMetadata() const; //@} /// @name Geometry. @@ -261,7 +261,8 @@ public: uint8_t GetRank() const; uint32_t GetPopulation() const; string GetRoadNumber() const; - inline FeatureParams::AdditionalInfoT const & GetAdditionalInfo() const { return m_additional_info; } + inline feature::FeatureMetadata const & GetMetadata() const { return m_metadata; } + inline feature::FeatureMetadata & GetMetadata() { return m_metadata; } double GetDistance(m2::PointD const & pt, int scale) const; @@ -311,9 +312,9 @@ private: typedef buffer_vector<m2::PointD, static_buffer> points_t; mutable points_t m_points, m_triangles; - mutable FeatureParams::AdditionalInfoT m_additional_info; + mutable feature::FeatureMetadata m_metadata; - mutable bool m_bHeader2Parsed, m_bPointsParsed, m_bTrianglesParsed, m_bAdditionalInfoParsed; + mutable bool m_bHeader2Parsed, m_bPointsParsed, m_bTrianglesParsed, m_bMetadataParsed; mutable inner_geom_stat_t m_innerStats; diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp index 33843dcb97..2488338e8a 100644 --- a/indexer/feature_data.cpp +++ b/indexer/feature_data.cpp @@ -168,19 +168,6 @@ bool FeatureParams::AddHouseName(string const & s) return false; } -bool FeatureParams::AddAdditionalInfo(additional_info_types type, string const & s) -{ - if (m_additional_info[type].empty()) - { - m_additional_info[type] = s; - } - else - { - m_additional_info[type] = m_additional_info[type] + ", " + s; - } - return true; -} - bool FeatureParams::AddHouseNumber(string const & ss) { diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp index 216ee08936..a638a61e02 100644 --- a/indexer/feature_data.hpp +++ b/indexer/feature_data.hpp @@ -11,6 +11,7 @@ #include "../std/vector.hpp" #include "../std/algorithm.hpp" +#include "feature_meta.hpp" class FeatureBase; @@ -205,17 +206,10 @@ class FeatureParams : public FeatureParamsBase /// We use it now only for search unit tests string m_street; -public: + feature::FeatureMetadata m_metadata; - enum additional_info_types { - AIT_CUISINE = 1, - AIT_OPEN_HOURS, - AIT_PHONE_NUMBER, - AIT_FAX_NUMBER - }; +public: - typedef map<uint8_t, string> AdditionalInfoT; - AdditionalInfoT m_additional_info; typedef vector<uint32_t> types_t; types_t m_Types; @@ -228,8 +222,6 @@ public: bool AddHouseName(string const & s); bool AddHouseNumber(string const & s); - bool AddAdditionalInfo(additional_info_types type, string const & s); - /// @name Used in storing full street address only. //@{ void AddStreetAddress(string const & s); @@ -244,7 +236,7 @@ public: m_Types = rhs.m_Types; m_street = rhs.m_street; - m_additional_info = rhs.m_additional_info; + m_metadata = rhs.m_metadata; } inline bool IsValid() const { return !m_Types.empty(); } @@ -270,7 +262,10 @@ public: uint8_t GetHeader() const; - template <class SinkT> void Write(SinkT & sink, bool needStoreAdditionalInfo = true) const + feature::FeatureMetadata const & GetMetadata() const { return m_metadata; } + feature::FeatureMetadata & GetMetadata() { return m_metadata; } + + template <class SinkT> void Write(SinkT & sink, bool needStoreMetadata = true) const { uint8_t const header = GetHeader(); @@ -279,24 +274,13 @@ public: for (size_t i = 0; i < m_Types.size(); ++i) WriteVarUint(sink, GetIndexForType(m_Types[i])); - if (needStoreAdditionalInfo) - { - uint8_t const ait_size = m_additional_info.size(); - WriteToSink(sink, ait_size); - if (ait_size) - { - for(auto & it: m_additional_info) - { - WriteToSink(sink, uint8_t(it.first)); - utils::WriteString(sink, it.second); - } - } - } + if (needStoreMetadata) + m_metadata.Serialize(sink); BaseT::Write(sink, header); } - template <class SrcT> void Read(SrcT & src, bool needReadAdditionalInfo = true) + template <class SrcT> void Read(SrcT & src, bool needReadMetadata = true) { using namespace feature; @@ -307,17 +291,8 @@ public: for (size_t i = 0; i < count; ++i) m_Types.push_back(GetTypeForIndex(ReadVarUint<uint32_t>(src))); - if (needReadAdditionalInfo) - { - uint8_t const ait_size = ReadPrimitiveFromSource<uint8_t>(src); - for (size_t i=0; i < ait_size; ++i) - { - uint8_t const key = ReadPrimitiveFromSource<uint8_t>(src); - string value; - utils::ReadString(src, value); - m_additional_info.insert(make_pair(key, value)); - } - } + if (needReadMetadata) + m_metadata.Deserialize(src); BaseT::Read(src, header); } diff --git a/indexer/feature_loader.cpp b/indexer/feature_loader.cpp index b88c63f80a..55664f903a 100644 --- a/indexer/feature_loader.cpp +++ b/indexer/feature_loader.cpp @@ -252,12 +252,12 @@ uint32_t LoaderCurrent::ParseTriangles(int scale) return sz; } -void LoaderCurrent::ParseAdditionalInfo() +void LoaderCurrent::ParseMetadata() { try { typedef pair<uint32_t, uint32_t> IdxElementT; - DDVector<IdxElementT, FilesContainerR::ReaderT> idx(m_Info.GetAdditionalInfoIndexReader()); + DDVector<IdxElementT, FilesContainerR::ReaderT> idx(m_Info.GetMetadataIndexReader()); auto it = lower_bound(idx.begin(), idx.end() , make_pair(uint32_t(m_pF->m_id.m_offset), uint32_t(0)) @@ -266,16 +266,9 @@ void LoaderCurrent::ParseAdditionalInfo() if (it != idx.end() && m_pF->m_id.m_offset == it->first) { - uint8_t header[2] = {0}; - char buffer[numeric_limits<uint8_t>::max()] = {0}; - ReaderSource<FilesContainerR::ReaderT> reader(m_Info.GetAdditionalInfoReader()); + ReaderSource<FilesContainerR::ReaderT> reader(m_Info.GetMetadataReader()); reader.Skip(it->second); - do - { - reader.Read(header, sizeof(header)); - reader.Read(buffer, header[1]); - m_pF->m_additional_info[uint8_t(header[0] & 0x7F)].assign(buffer, header[1]); - } while (!(header[0] & 0x80)); + m_pF->GetMetadata().DeserializeFromMWM(reader); } } catch(Reader::OpenException & e) diff --git a/indexer/feature_loader.hpp b/indexer/feature_loader.hpp index d4165a1a02..b2b00deca2 100644 --- a/indexer/feature_loader.hpp +++ b/indexer/feature_loader.hpp @@ -28,6 +28,6 @@ namespace feature virtual void ParseHeader2(); virtual uint32_t ParseGeometry(int scale); virtual uint32_t ParseTriangles(int scale); - virtual void ParseAdditionalInfo(); + virtual void ParseMetadata(); }; } diff --git a/indexer/feature_loader_base.cpp b/indexer/feature_loader_base.cpp index eb127876be..6b6f72e90d 100644 --- a/indexer/feature_loader_base.cpp +++ b/indexer/feature_loader_base.cpp @@ -34,14 +34,14 @@ SharedLoadInfo::ReaderT SharedLoadInfo::GetDataReader() const return m_cont.GetReader(DATA_FILE_TAG); } -SharedLoadInfo::ReaderT SharedLoadInfo::GetAdditionalInfoReader() const +SharedLoadInfo::ReaderT SharedLoadInfo::GetMetadataReader() const { - return m_cont.GetReader(ADDITIONAL_INFO_FILE_TAG); + return m_cont.GetReader(METADATA_FILE_TAG); } -SharedLoadInfo::ReaderT SharedLoadInfo::GetAdditionalInfoIndexReader() const +SharedLoadInfo::ReaderT SharedLoadInfo::GetMetadataIndexReader() const { - return m_cont.GetReader(ADDITIONAL_INFO_INDEX_FILE_TAG); + return m_cont.GetReader(METADATA_INDEX_FILE_TAG); } SharedLoadInfo::ReaderT SharedLoadInfo::GetGeometryReader(int ind) const diff --git a/indexer/feature_loader_base.hpp b/indexer/feature_loader_base.hpp index eab6dca536..409d3e0e27 100644 --- a/indexer/feature_loader_base.hpp +++ b/indexer/feature_loader_base.hpp @@ -30,8 +30,8 @@ namespace feature ~SharedLoadInfo(); ReaderT GetDataReader() const; - ReaderT GetAdditionalInfoReader() const; - ReaderT GetAdditionalInfoIndexReader() const; + ReaderT GetMetadataReader() const; + ReaderT GetMetadataIndexReader() const; ReaderT GetGeometryReader(int ind) const; ReaderT GetTrianglesReader(int ind) const; @@ -75,7 +75,7 @@ namespace feature virtual void ParseHeader2() = 0; virtual uint32_t ParseGeometry(int scale) = 0; virtual uint32_t ParseTriangles(int scale) = 0; - virtual void ParseAdditionalInfo() = 0; + virtual void ParseMetadata() = 0; inline uint32_t GetTypesSize() const { return m_CommonOffset - m_TypesOffset; } diff --git a/indexer/feature_meta.cpp b/indexer/feature_meta.cpp new file mode 100644 index 0000000000..5897638c50 --- /dev/null +++ b/indexer/feature_meta.cpp @@ -0,0 +1 @@ +#include "feature_meta.hpp" diff --git a/indexer/feature_meta.hpp b/indexer/feature_meta.hpp new file mode 100644 index 0000000000..f1e4d8ff08 --- /dev/null +++ b/indexer/feature_meta.hpp @@ -0,0 +1,108 @@ +#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" + +namespace feature +{ + class FeatureMetadata + { + typedef map<uint8_t, string> MetadataT; + MetadataT m_metadata; + + public: + enum EMetadataType { + FMD_CUISINE = 1, + FMD_OPEN_HOURS, + FMD_PHONE_NUMBER, + FMD_FAX_NUMBER, + FMD_STARS, + FMD_OPERATOR, + FMD_URL, + FMD_INTERNET + }; + + 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) + { + auto it = m_metadata.find(type); + return (it == m_metadata.end()) ? string() : it->second; + } + + 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[numeric_limits<uint8_t>::max()] = {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)); + } + + } + + + }; +} diff --git a/indexer/old/feature_loader_101.hpp b/indexer/old/feature_loader_101.hpp index a576373df1..e18dfb32b5 100644 --- a/indexer/old/feature_loader_101.hpp +++ b/indexer/old/feature_loader_101.hpp @@ -36,7 +36,7 @@ namespace old_101 { namespace feature virtual void ParseHeader2(); virtual uint32_t ParseGeometry(int scale); virtual uint32_t ParseTriangles(int scale); - virtual void ParseAdditionalInfo() {} /// not supported in this version + virtual void ParseMetadata() {} /// not supported in this version }; } |