diff --git a/libs/editor/editor_tests/feature_type_to_osm_test.cpp b/libs/editor/editor_tests/feature_type_to_osm_test.cpp index af05b9ce4..db8e93d2c 100644 --- a/libs/editor/editor_tests/feature_type_to_osm_test.cpp +++ b/libs/editor/editor_tests/feature_type_to_osm_test.cpp @@ -86,7 +86,8 @@ UNIT_TEST(loadConfigFile) size_t size = translator.GetStorage().size(); LOG(LINFO, ("Size of feature type storage:", size)); - ASSERT(size > 1000, ()); + ASSERT(size > 1300, ()); + ASSERT(size < 1700, ()); } UNIT_TEST(OsmTagsFromType) @@ -110,5 +111,5 @@ UNIT_TEST(OsmTagsFromType) UNIT_TEST(testToFail) { - ASSERT_FAIL("Don't run further tests-------------------"); + ASSERT_FAIL("------------------- Don't run further tests -------------------"); } diff --git a/libs/editor/feature_type_to_osm.cpp b/libs/editor/feature_type_to_osm.cpp index a87b3fc02..7c9fc4471 100644 --- a/libs/editor/feature_type_to_osm.cpp +++ b/libs/editor/feature_type_to_osm.cpp @@ -18,8 +18,6 @@ TypeToOSMTranslator::TypeToOSMTranslator(bool initialize) void TypeToOSMTranslator::LoadConfigFile() { - LOG(LINFO, ("Loading 'mapcss-mapping.csv' file for TypeToOSMTranslator")); - Platform &p = GetPlatform(); std::unique_ptr reader = p.GetReader("mapcss-mapping.csv"); ReaderStreamBuf buffer(std::move(reader)); @@ -33,29 +31,31 @@ void TypeToOSMTranslator::LoadFromStream(std::istream & s) m_storage.clear(); std::string line; - - int lineNumber = 0; while (s.good()) { - ++lineNumber; getline(s, line); strings::Trim(line); - // skip empty lines, comments and deprecated types - if (line.empty() || line[0] == '#' || line.starts_with("deprecated")) + // skip empty lines, comments, deprecated and moved types + if (line.empty() || line.front() == '#' || line.starts_with("deprecated") || + line.starts_with("moved") || line.back() != ';') continue; std::vector tokens = strings::Tokenize(line, ";"); - ASSERT(tokens.size() >= 2, ("Invalid type definition:", line)); + if (tokens.size() < 2) + { + ASSERT(false, ("Invalid feature type definition:", line)); + continue; + } // Get internal feature type std::vector typeTokens = strings::Tokenize(tokens[0], "|"); uint32_t type = classif().GetTypeByPathSafe(typeTokens); - if (typeTokens.size() <= 2) + if (tokens.size() == 2) { - // simple feature type: OSM tags can be derived from type name - ASSERT(!typeTokens.empty(), ("No type name found")); + // Derive OSM tags from type name + ASSERT(typeTokens.size() <= 2, ("OSM tags can not be inferred from name:", line)); OSMTag osmTag; @@ -74,11 +74,8 @@ void TypeToOSMTranslator::LoadFromStream(std::istream & s) } else { - // complex feature type: OSM tags are listed in the entry - ASSERT(tokens.size() > 2, ("OSM tags not listed for complex feature type: ", line)); - + // OSM tags are listed in the feature type entry std::vector osmTagTokens = strings::Tokenize(tokens[1], ","); - ASSERT(!osmTagTokens.empty(), ("No OSM tag tokens found")); // First entry is the best practice way to tag a feature std::string_view osmTagList = osmTagTokens[0]; @@ -87,36 +84,62 @@ void TypeToOSMTranslator::LoadFromStream(std::istream & s) std::vector osmTags; size_t pos = 0; - while ((pos = osmTagList.find('[', pos)) != std::string::npos) { + while ((pos = osmTagList.find('[', pos)) != std::string::npos) + { size_t end = osmTagList.find(']', pos); - ASSERT(end != std::string::npos, ("Bracket not closed in OSM tag: ", line)); + if (end == std::string::npos) + { + ASSERT(false, ("Bracket not closed in OSM tag:", line)); + break; + } std::string_view keyValuePair = osmTagList.substr(pos + 1, end - pos - 1); - size_t equalSign = keyValuePair.find('='); + + if (keyValuePair.empty()) { + ASSERT(false, ("Key value pair is empty:", line)); + break; + } // Skip entries that are not in key=value format - if (equalSign != std::string::npos) { + size_t equalSign = keyValuePair.find('='); + if (equalSign != std::string::npos) + { OSMTag osmTag; - osmTag.key = keyValuePair.substr(0, equalSign); osmTag.value = keyValuePair.substr(equalSign + 1); osmTags.push_back(osmTag); } + else if (keyValuePair.front() == '!') + { + // Tags with "forbidden" selector '!' are skipped + } + else + { + // Tags with optional "mandatory" selector '?' + if (keyValuePair.back() == '?') + keyValuePair.remove_suffix(1); + + OSMTag osmTag; + osmTag.key = keyValuePair; + osmTag.value = "yes"; + + osmTags.push_back(osmTag); + } pos = end + 1; } + ASSERT(!osmTags.empty(), ("No OSM tags found for feature:", line)); + m_storage.insert({type, osmTags}); } } } -std::vector TypeToOSMTranslator::OsmTagsFromType(uint32_t type) const +std::vector const & TypeToOSMTranslator::OsmTagsFromType(uint32_t type) const { - LOG(LINFO, ("Computing OsmTagsFromType for Type: ", type, "/ " , classif().GetReadableObjectName(type))); - auto it = m_storage.find(type); if (it == m_storage.end()) diff --git a/libs/editor/feature_type_to_osm.hpp b/libs/editor/feature_type_to_osm.hpp index 07c4b8053..163c7abf9 100644 --- a/libs/editor/feature_type_to_osm.hpp +++ b/libs/editor/feature_type_to_osm.hpp @@ -21,7 +21,7 @@ public: void LoadConfigFile(); void LoadFromStream(std::istream & s); - std::vector OsmTagsFromType(uint32_t type) const; + std::vector const & OsmTagsFromType(uint32_t type) const; std::map> const & GetStorage() const { return m_storage; } diff --git a/libs/editor/xml_feature.cpp b/libs/editor/xml_feature.cpp index d6892de49..ad11d5549 100644 --- a/libs/editor/xml_feature.cpp +++ b/libs/editor/xml_feature.cpp @@ -648,7 +648,7 @@ void XMLFeature::SetOSMTagsForType(uint32_t type) return; } - std::vector osmTags = GetOSMTranslator().OsmTagsFromType(type); + std::vector const & osmTags = GetOSMTranslator().OsmTagsFromType(type); for(auto const & osmTag : osmTags) SetTagValue(osmTag.key, osmTag.value);