diff --git a/kml/kml_tests/gpx_tests.cpp b/kml/kml_tests/gpx_tests.cpp index cd3a1062d0..e0ae792ee1 100644 --- a/kml/kml_tests/gpx_tests.cpp +++ b/kml/kml_tests/gpx_tests.cpp @@ -1,12 +1,14 @@ #include "testing/testing.hpp" -#include "map/bookmark_helpers.hpp" + +#include "kml/serdes_common.hpp" #include "kml/serdes_gpx.hpp" -#include "base/string_utils.hpp" -#include "coding/string_utf8_multilang.hpp" + #include "geometry/mercator.hpp" + +#include "coding/file_reader.hpp" + #include "platform/platform.hpp" -auto constexpr kDefaultCode = StringUtf8Multilang::kDefaultCode; kml::FileData loadGpxFromString(std::string const & content) { kml::FileData dataFromText; @@ -45,9 +47,9 @@ UNIT_TEST(Gpx_Test_Point) kml::FileData data; kml::BookmarkData bookmarkData; - bookmarkData.m_name[kDefaultCode] = "Waypoint 1"; + bookmarkData.m_name[kml::kDefaultLang] = "Waypoint 1"; bookmarkData.m_point = mercator::FromLatLon(42.81025, -1.65727); - bookmarkData.m_customName[kDefaultCode] = "Waypoint 1"; + bookmarkData.m_customName[kml::kDefaultLang] = "Waypoint 1"; bookmarkData.m_color = {kml::PredefinedColor::Red, 0}; data.m_bookmarksData.emplace_back(std::move(bookmarkData)); @@ -164,7 +166,7 @@ UNIT_TEST(PointsOnly) kml::FileData const dataFromFile = loadGpxFromFile("gpx_test_data/points.gpx"); auto bookmarks = dataFromFile.m_bookmarksData; TEST_EQUAL(bookmarks.size(), 3, ()); - TEST_EQUAL("Point 1", bookmarks[0].m_name[kDefaultCode], ()); + TEST_EQUAL("Point 1", bookmarks[0].m_name[kml::kDefaultLang], ()); TEST_EQUAL(bookmarks[0].m_point, mercator::FromLatLon(48.20984622935899, 16.376023292541507), ()); } @@ -173,7 +175,7 @@ UNIT_TEST(Route) kml::FileData dataFromFile = loadGpxFromFile("gpx_test_data/route.gpx"); auto line = dataFromFile.m_tracksData[0].m_geometry.m_lines[0]; TEST_EQUAL(line.size(), 2, ()); - TEST_EQUAL(dataFromFile.m_categoryData.m_name[kDefaultCode], "Some random route", ()); + TEST_EQUAL(dataFromFile.m_categoryData.m_name[kml::kDefaultLang], "Some random route", ()); TEST_EQUAL(line[0], geometry::PointWithAltitude(mercator::FromLatLon(48.20984622935899, 16.376023292541507), 184), ()); TEST_EQUAL(line[1], geometry::PointWithAltitude(mercator::FromLatLon(48.209503040543545, 16.381065845489506), 187), ()); } @@ -248,4 +250,4 @@ d5 TEST_EQUAL("c3", dataFromText.m_bookmarksData[2].m_description.at(kml::kDefaultLang), ()); TEST_EQUAL("d4\nd5\n\nc4", dataFromText.m_bookmarksData[3].m_description.at(kml::kDefaultLang), ()); TEST_EQUAL("qqq", dataFromText.m_bookmarksData[4].m_description.at(kml::kDefaultLang), ()); -} \ No newline at end of file +} diff --git a/kml/serdes.cpp b/kml/serdes.cpp index 565d1c19ee..ed07855789 100644 --- a/kml/serdes.cpp +++ b/kml/serdes.cpp @@ -50,17 +50,12 @@ std::string const kExtendedDataFooter = std::string const kCompilationFooter = "\n"; -std::string Indent(size_t count) -{ - return std::string(count, ' '); -} - -std::string const kIndent0 = Indent(0); -std::string const kIndent2 = Indent(2); -std::string const kIndent4 = Indent(4); -std::string const kIndent6 = Indent(6); -std::string const kIndent8 = Indent(8); -std::string const kIndent10 = Indent(10); +std::string_view constexpr kIndent0 = {}; +std::string_view constexpr kIndent2 = {" "}; +std::string_view constexpr kIndent4 = {" "}; +std::string_view constexpr kIndent6 = {" "}; +std::string_view constexpr kIndent8 = {" "}; +std::string_view constexpr kIndent10 = {" "}; std::string GetLocalizableString(LocalizableString const & s, int8_t lang) { @@ -180,18 +175,18 @@ void SaveStringWithCDATA(KmlWriter::WriterWrapper & writer, std::string s) } void SaveStyle(KmlWriter::WriterWrapper & writer, std::string const & style, - std::string const & offsetStr) + std::string_view const & indent) { if (style.empty()) return; - writer << offsetStr << kIndent2 << "\n"; + writer << indent << kIndent2 << "\n"; } void SaveColorToABGR(KmlWriter::WriterWrapper & writer, uint32_t rgba) @@ -212,31 +207,31 @@ std::string TimestampToString(Timestamp const & timestamp) } void SaveLocalizableString(KmlWriter::WriterWrapper & writer, LocalizableString const & str, - std::string const & tagName, std::string const & offsetStr) + std::string const & tagName, std::string_view const & indent) { - writer << offsetStr << "\n"; + writer << indent << "\n"; for (auto const & s : str) { - writer << offsetStr << kIndent2 << ""; SaveStringWithCDATA(writer, s.second); writer << "\n"; } - writer << offsetStr << "\n"; + writer << indent << "\n"; } template void SaveStringsArray(KmlWriter::WriterWrapper & writer, std::vector const & stringsArray, - std::string const & tagName, std::string const & offsetStr) + std::string const & tagName, std::string_view const & indent) { if (stringsArray.empty()) return; - writer << offsetStr << "\n"; + writer << indent << "\n"; for (auto const & s : stringsArray) { - writer << offsetStr << kIndent2 << ""; + writer << indent << kIndent2 << ""; // Constants from our code do not need any additional checks or escaping. if constexpr (std::is_same_v) { @@ -247,24 +242,24 @@ void SaveStringsArray(KmlWriter::WriterWrapper & writer, SaveStringWithCDATA(writer, s); writer << "\n"; } - writer << offsetStr << "\n"; + writer << indent << "\n"; } void SaveStringsMap(KmlWriter::WriterWrapper & writer, std::map const & stringsMap, - std::string const & tagName, std::string const & offsetStr) + std::string const & tagName, std::string_view const & indent) { if (stringsMap.empty()) return; - writer << offsetStr << "\n"; + writer << indent << "\n"; for (auto const & p : stringsMap) { - writer << offsetStr << kIndent2 << ""; + writer << indent << kIndent2 << ""; SaveStringWithCDATA(writer, p.second); writer << "\n"; } - writer << offsetStr << "\n"; + writer << indent << "\n"; } void SaveCategoryData(KmlWriter::WriterWrapper & writer, CategoryData const & categoryData, @@ -367,26 +362,21 @@ void SaveCategoryData(KmlWriter::WriterWrapper & writer, CategoryData const & ca if (compilationData) { for (uint8_t i = 0; i < base::Underlying(PredefinedColor::Count); ++i) - { - SaveStyle(writer, GetStyleForPredefinedColor(static_cast(i)), - compilationData ? kIndent0 : kIndent2); - } - - auto const & indent = compilationData ? kIndent2 : kIndent4; + SaveStyle(writer, GetStyleForPredefinedColor(static_cast(i)), kIndent0); // Use CDATA if we have special symbols in the name. - writer << indent << ""; + writer << kIndent2 << ""; SaveStringWithCDATA(writer, GetLocalizableString(categoryData.m_name, kDefaultLang)); writer << "\n"; if (!categoryData.m_description.empty()) { - writer << indent << ""; + writer << kIndent2 << ""; SaveStringWithCDATA(writer, GetLocalizableString(categoryData.m_description, kDefaultLang)); writer << "\n"; } - writer << indent << "" << (categoryData.m_visible ? "1" : "0") << "\n"; + writer << kIndent2 << "" << (categoryData.m_visible ? "1" : "0") << "\n"; } SaveCategoryExtendedData(writer, categoryData, extendedServerId, compilationData); @@ -496,12 +486,12 @@ void SaveBookmarkData(KmlWriter::WriterWrapper & writer, BookmarkData const & bo } void SaveTrackLayer(KmlWriter::WriterWrapper & writer, TrackLayer const & layer, - std::string const & offsetStr) + std::string_view const & indent) { - writer << offsetStr << ""; + writer << indent << ""; SaveColorToABGR(writer, layer.m_color.m_rgba); writer << "\n"; - writer << offsetStr << "" << strings::to_string(layer.m_lineWidth) << "\n"; + writer << indent << "" << strings::to_string(layer.m_lineWidth) << "\n"; } void SaveTrackGeometry(KmlWriter::WriterWrapper & writer, MultiGeometry const & geom) @@ -639,11 +629,13 @@ bool ParsePointWithAltitude(std::string_view s, char const * delim, { geometry::Altitude altitude = geometry::kInvalidAltitude; m2::PointD pt; - auto result = ParsePoint(s, delim, pt, altitude); - point.SetPoint(std::move(pt)); - point.SetAltitude(altitude); - - return result; + if (ParsePoint(s, delim, pt, altitude)) + { + point.SetPoint(pt); + point.SetAltitude(altitude); + return true; + } + return false; } } // namespace @@ -825,7 +817,7 @@ bool KmlParser::Push(std::string movedTag) else if (IsProcessTrackTag()) { m_geometryType = GEOMETRY_TYPE_LINE; - m_geometry.m_lines.push_back({}); + m_geometry.m_lines.emplace_back(); } return true; } @@ -984,9 +976,8 @@ void KmlParser::Pop(std::string_view tag) // loading of KML files which were stored by older versions of OMaps. TrackLayer layer; layer.m_lineWidth = m_trackWidth; - layer.m_color.m_predefinedColor = PredefinedColor::None; layer.m_color.m_rgba = (m_color != 0 ? m_color : kDefaultTrackColor); - m_trackLayers.push_back(std::move(layer)); + m_trackLayers.push_back(layer); m_trackWidth = kDefaultTrackWidth; m_color = 0; @@ -1167,7 +1158,7 @@ void KmlParser::CharData(std::string & value) if (!GetColorForStyle(value, m_color)) { // Remove leading '#' symbol. - std::string styleId = m_mapStyle2Style[value.substr(1)]; + std::string const styleId = m_mapStyle2Style[value.substr(1)]; if (!styleId.empty()) GetColorForStyle(styleId, m_color); } diff --git a/kml/serdes_gpx.cpp b/kml/serdes_gpx.cpp index f69c1933cc..835ec4db90 100644 --- a/kml/serdes_gpx.cpp +++ b/kml/serdes_gpx.cpp @@ -1,8 +1,8 @@ #include "kml/serdes_gpx.hpp" +#include "kml/serdes_common.hpp" #include "coding/hex.hpp" #include "coding/point_coding.hpp" -#include "coding/string_utf8_multilang.hpp" #include "geometry/mercator.hpp" @@ -33,8 +33,8 @@ std::string_view constexpr kCmt = "cmt"; int constexpr kInvalidColor = 0; GpxParser::GpxParser(FileData & data) -: m_data(data) -, m_categoryData(&m_data.m_categoryData) +: m_data{data} +, m_categoryData{&m_data.m_categoryData} { ResetPoint(); } @@ -48,7 +48,6 @@ void GpxParser::ResetPoint() m_predefinedColor = PredefinedColor::None; m_color = kInvalidColor; m_customName.clear(); - m_trackLayers.clear(); m_geometry.Clear(); m_geometryType = GEOMETRY_TYPE_UNKNOWN; m_lat = 0.; @@ -95,7 +94,7 @@ bool GpxParser::Push(std::string tag) return true; } -bool GpxParser::IsValidCoordinatesPosition() +bool GpxParser::IsValidCoordinatesPosition() const { std::string const & lastTag = GetTagFromEnd(0); return lastTag == gpx::kWpt @@ -132,7 +131,8 @@ void GpxParser::ParseColor(std::string const & value) } // https://osmand.net/docs/technical/osmand-file-formats/osmand-gpx/ - "#AARRGGBB" or "#RRGGBB" -void GpxParser::ParseOsmandColor(std::string const & value) { +void GpxParser::ParseOsmandColor(std::string const & value) +{ if (value.empty()) { LOG(LWARNING, ("Empty color value")); @@ -230,17 +230,19 @@ void GpxParser::Pop(std::string_view tag) { BookmarkData data; if (!m_name.empty()) - data.m_name = {{ kDefaultLang, m_name }}; + data.m_name[kDefaultLang] = std::move(m_name); if (!m_description.empty() || !m_comment.empty()) - data.m_description = {{kDefaultLang, BuildDescription()}}; + data.m_description[kDefaultLang] = BuildDescription(); data.m_color.m_predefinedColor = m_predefinedColor; data.m_color.m_rgba = m_color; data.m_point = m_org; if (!m_customName.empty()) - data.m_customName = {{kDefaultLang, m_customName}}; - // Here we set custom name from 'name' field for KML-files exported from 3rd-party services. - if (data.m_name.size() == 1 && data.m_name.begin()->first == kDefaultLangCode && data.m_customName.empty()) + data.m_customName[kDefaultLang] = std::move(m_customName); + else if (!data.m_name.empty()) + { + // Here we set custom name from 'name' field for KML-files exported from 3rd-party services. data.m_customName = data.m_name; + } m_data.m_bookmarksData.push_back(std::move(data)); } @@ -254,15 +256,15 @@ void GpxParser::Pop(std::string_view tag) layer.m_color.m_rgba = m_globalColor; else layer.m_color.m_rgba = kml::kDefaultTrackColor; - m_trackLayers.push_back(std::move(layer)); TrackData data; if (!m_name.empty()) - data.m_name = {{ kDefaultLang, m_name }}; + data.m_name[kDefaultLang] = std::move(m_name); if (!m_description.empty() || !m_comment.empty()) - data.m_description = {{kDefaultLang, BuildDescription()}}; - data.m_layers = std::move(m_trackLayers); + data.m_description[kDefaultLang] = BuildDescription(); + data.m_layers.push_back(layer); data.m_geometry = std::move(m_geometry); + m_data.m_tracksData.push_back(std::move(data)); } } @@ -343,13 +345,11 @@ void GpxParser::ParseAltitude(std::string const & value) m_altitude = geometry::kInvalidAltitude; } -std::string GpxParser::BuildDescription() +std::string GpxParser::BuildDescription() const { if (m_description.empty()) return m_comment; - else if (m_comment.empty()) - return m_description; - else if (m_description == m_comment) + else if (m_comment.empty() || m_description == m_comment) return m_description; return m_description + "\n\n" + m_comment; } diff --git a/kml/serdes_gpx.hpp b/kml/serdes_gpx.hpp index 9b7fae363a..852e7fb00d 100644 --- a/kml/serdes_gpx.hpp +++ b/kml/serdes_gpx.hpp @@ -1,19 +1,14 @@ #pragma once #include "kml/types.hpp" -#include "kml/serdes_common.hpp" #include "coding/parse_xml.hpp" #include "coding/reader.hpp" -#include "coding/writer.hpp" -#include "geometry/point2d.hpp" #include "geometry/point_with_altitude.hpp" #include "base/exception.hpp" -#include "base/stl_helpers.hpp" -#include #include namespace kml @@ -43,7 +38,7 @@ private: void ParseColor(std::string const & value); void ParseGarminColor(std::string const & value); void ParseOsmandColor(std::string const & value); - bool IsValidCoordinatesPosition(); + bool IsValidCoordinatesPosition() const; FileData & m_data; CategoryData m_compilationData; @@ -67,11 +62,10 @@ private: MultiGeometry::LineT m_line; std::string m_customName; - std::vector m_trackLayers; void ParseName(std::string const & value, std::string const & prevTag); void ParseDescription(std::string const & value, std::string const & prevTag); void ParseAltitude(std::string const & value); - std::string BuildDescription(); + std::string BuildDescription() const; }; } // namespace gpx