Introduced V9MM version. It has the same format as V8MM but with extra flag in tracks data.
Signed-off-by: Sergiy Kozyr <s.trump@gmail.com>
This commit is contained in:
parent
fcbf955aea
commit
e0e59da62b
5 changed files with 169 additions and 9 deletions
|
@ -22,6 +22,7 @@ set(SRC
|
|||
types_v8.hpp
|
||||
types_v8mm.hpp
|
||||
types_v9.hpp
|
||||
types_v9mm.hpp
|
||||
visitors.hpp
|
||||
)
|
||||
|
||||
|
|
|
@ -26,9 +26,12 @@ enum class Version : uint8_t
|
|||
// tags to kml
|
||||
V9 = 9, // 01 October 2020: add minZoom to bookmarks
|
||||
Latest = V9,
|
||||
V8MM = 10 // 27 July 2023: MapsMe release version v15.0.71617. Technically it's version is 8
|
||||
// (first byte is 0x08), but it's not compatible with V8 from this repo. It has
|
||||
// no compilations.
|
||||
V8MM = 10, // 27 July 2023: MapsMe release version v15.0.71617. Technically it's version is 8
|
||||
// (first byte is 0x08), but it's not compatible with V8 from this repo. It has
|
||||
// no compilations.
|
||||
V9MM = 11 // In July 2024 MapsMe release version with new KMB format. Technically its version is 9
|
||||
// (first byte is 0x09), but it's not compatible with OrganicMaps V9 from this repo. It has
|
||||
// extra flag in tracks data.
|
||||
};
|
||||
|
||||
struct Header
|
||||
|
|
|
@ -865,7 +865,7 @@ UNIT_TEST(Kml_Deserialization_From_Bin_V8_And_V8MM)
|
|||
TEST_EQUAL(dataFromBinV8.m_tracksData, dataFromBinV8MM.m_tracksData, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(Kml_Deserialization_From_KMB_V9MM)
|
||||
UNIT_TEST(Kml_Deserialization_From_KMB_V8_And_V9MM)
|
||||
{
|
||||
kml::FileData dataFromBinV8;
|
||||
try
|
||||
|
@ -903,7 +903,10 @@ UNIT_TEST(Kml_Deserialization_From_KMB_V9MM)
|
|||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_tags, dataFromBinV9MM.m_categoryData.m_tags, ());
|
||||
TEST_EQUAL(dataFromBinV8.m_categoryData.m_properties, dataFromBinV9MM.m_categoryData.m_properties, ());
|
||||
|
||||
dataFromBinV8.m_bookmarksData[0].m_id = dataFromBinV9MM.m_bookmarksData[0].m_id; // V8 and V9MM bookmarks have different IDs. Fix ID value manually.
|
||||
TEST_EQUAL(dataFromBinV8.m_bookmarksData, dataFromBinV9MM.m_bookmarksData, ());
|
||||
|
||||
dataFromBinV8.m_tracksData[0].m_id = dataFromBinV9MM.m_tracksData[0].m_id; // V8 and V9MM tracks have different IDs. Fix ID value manually.
|
||||
TEST_EQUAL(dataFromBinV8.m_tracksData, dataFromBinV9MM.m_tracksData, ());
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "kml/types_v7.hpp"
|
||||
#include "kml/types_v8.hpp"
|
||||
#include "kml/types_v8mm.hpp"
|
||||
#include "kml/types_v9mm.hpp"
|
||||
#include "kml/types.hpp"
|
||||
#include "kml/visitors.hpp"
|
||||
|
||||
|
@ -195,6 +196,16 @@ public:
|
|||
m_data = dataV8MM.ConvertToLatestVersion();
|
||||
break;
|
||||
}
|
||||
case Version::V9MM:
|
||||
{
|
||||
FileDataV9MM dataV9MM;
|
||||
dataV9MM.m_deviceId = m_data.m_deviceId;
|
||||
dataV9MM.m_serverId = m_data.m_serverId;
|
||||
DeserializeFileData(subReader, dataV9MM);
|
||||
|
||||
m_data = dataV9MM.ConvertToLatestVersion();
|
||||
break;
|
||||
}
|
||||
case Version::V7:
|
||||
{
|
||||
FileDataV7 dataV7;
|
||||
|
@ -251,12 +262,10 @@ private:
|
|||
NonOwningReaderSource source(reader);
|
||||
m_header.Deserialize(source);
|
||||
|
||||
// The recent MapsMe update increased the version number, but it is not clear yet what changed/added in a newer version.
|
||||
// Revise V9 in case of discovered crashes.
|
||||
if (m_header.m_version == Version::V8 || m_header.m_version == Version::V9)
|
||||
if (m_header.m_version == Version::V8)
|
||||
{
|
||||
// Check if file has Opensource V8 or MapsMe V8.
|
||||
// Actual V8 format has 6 offset (uint64_t) in header. While V8MM has 5 offsets.
|
||||
// Check if file has Opensource V8 or MapsMe V8 format.
|
||||
// Actual V8 format has 6 offsets (uint64_t) in header. While V8MM has 5 offsets.
|
||||
// It means that first section (usually categories) has offset 0x28 = 40 = 5 * 8.
|
||||
if (m_header.m_categoryOffset == 0x28 || m_header.m_bookmarksOffset == 0x28 ||
|
||||
m_header.m_tracksOffset == 0x28 || m_header.m_stringsOffset == 0x28 ||
|
||||
|
@ -268,6 +277,21 @@ private:
|
|||
m_header.m_stringsOffset = m_header.m_compilationsOffset;
|
||||
}
|
||||
}
|
||||
if (m_header.m_version == Version::V9)
|
||||
{
|
||||
// Check if file has Opensource V9 or MapsMe V9 format.
|
||||
// Actual V9 format has 6 offsets (uint64_t) in header. While V9MM has 5 offsets.
|
||||
// It means that first section (usually categories) has offset 0x28 = 40 = 5 * 8.
|
||||
if (m_header.m_categoryOffset == 0x28 || m_header.m_bookmarksOffset == 0x28 ||
|
||||
m_header.m_tracksOffset == 0x28 || m_header.m_stringsOffset == 0x28 ||
|
||||
m_header.m_compilationsOffset == 0x28)
|
||||
{
|
||||
LOG(LWARNING, ("KMB file has version V9MM"));
|
||||
m_header.m_version = Version::V9MM;
|
||||
m_header.m_eosOffset = m_header.m_stringsOffset;
|
||||
m_header.m_stringsOffset = m_header.m_compilationsOffset;
|
||||
}
|
||||
}
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
|
|
129
kml/types_v9mm.hpp
Normal file
129
kml/types_v9mm.hpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
#include "kml/types.hpp"
|
||||
#include "kml/types_v8mm.hpp"
|
||||
|
||||
namespace kml
|
||||
{
|
||||
struct TrackDataV9MM
|
||||
{
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(TrackDataV9MM, visitor(m_id, "id"),
|
||||
visitor(m_localId, "localId"),
|
||||
visitor(m_name, "name"),
|
||||
visitor(m_description, "description"),
|
||||
visitor(m_layers, "layers"),
|
||||
visitor(m_timestamp, "timestamp"),
|
||||
visitor(m_flag1, "flag1"), // Extra field introduced in V9MM.
|
||||
visitor(m_geometry, "geometry"),
|
||||
visitor(m_visible, "visible"),
|
||||
visitor(m_constant1, "constant1"),
|
||||
visitor(m_constant2, "constant2"),
|
||||
visitor(m_constant3, "constant3"),
|
||||
visitor(m_nearestToponyms, "nearestToponyms"),
|
||||
visitor(m_properties, "properties"),
|
||||
VISITOR_COLLECTABLE)
|
||||
|
||||
DECLARE_COLLECTABLE(LocalizableStringIndex, m_name, m_description, m_nearestToponyms, m_properties)
|
||||
|
||||
bool operator==(TrackDataV9MM const & data) const
|
||||
{
|
||||
return m_id == data.m_id && m_localId == data.m_localId && m_name == data.m_name &&
|
||||
m_description == data.m_description && m_layers == data.m_layers &&
|
||||
IsEqual(m_timestamp, data.m_timestamp) && m_geometry == data.m_geometry &&
|
||||
m_visible == data.m_visible && m_nearestToponyms == data.m_nearestToponyms &&
|
||||
m_properties == data.m_properties;
|
||||
}
|
||||
|
||||
bool operator!=(TrackDataV9MM const & data) const { return !operator==(data); }
|
||||
|
||||
TrackData ConvertToLatestVersion() const
|
||||
{
|
||||
TrackData data;
|
||||
data.m_id = m_id;
|
||||
data.m_localId = m_localId;
|
||||
data.m_name = m_name;
|
||||
data.m_description = m_description;
|
||||
data.m_layers = m_layers;
|
||||
data.m_timestamp = m_timestamp;
|
||||
data.m_geometry = m_geometry;
|
||||
data.m_visible = m_visible;
|
||||
data.m_nearestToponyms = m_nearestToponyms;
|
||||
data.m_properties = m_properties;
|
||||
return data;
|
||||
}
|
||||
|
||||
// Unique id (it will not be serialized in text files).
|
||||
TrackId m_id = kInvalidTrackId;
|
||||
// Local track id.
|
||||
LocalId m_localId = 0;
|
||||
// Track's name.
|
||||
LocalizableString m_name;
|
||||
// Track's description.
|
||||
LocalizableString m_description;
|
||||
// Layers.
|
||||
std::vector<TrackLayer> m_layers;
|
||||
// Creation timestamp.
|
||||
TimestampMillis m_timestamp{};
|
||||
MultiGeometry m_geometry;
|
||||
// Visibility.
|
||||
bool m_visible = true;
|
||||
// These constants were introduced in KMB V8MM. Usually have value 0. Don't know its purpose.
|
||||
uint8_t m_constant1 = 0;
|
||||
uint8_t m_constant2 = 0;
|
||||
uint8_t m_constant3 = 0;
|
||||
// Nearest toponyms.
|
||||
std::vector<std::string> m_nearestToponyms;
|
||||
// Key-value properties.
|
||||
Properties m_properties;
|
||||
// Extra field introduced in V9MM.
|
||||
bool m_flag1 = true;
|
||||
};
|
||||
|
||||
|
||||
// FileDataV8MM contains the same sections as FileDataV8MM but with changed m_tracksData format
|
||||
struct FileDataV9MM
|
||||
{
|
||||
DECLARE_VISITOR_AND_DEBUG_PRINT(FileDataV9MM, visitor(m_serverId, "serverId"),
|
||||
visitor(m_categoryData, "category"),
|
||||
visitor(m_bookmarksData, "bookmarks"),
|
||||
visitor(m_tracksData, "tracks"))
|
||||
|
||||
bool operator==(FileDataV9MM const & data) const
|
||||
{
|
||||
return m_serverId == data.m_serverId && m_categoryData == data.m_categoryData &&
|
||||
m_bookmarksData == data.m_bookmarksData && m_tracksData == data.m_tracksData;
|
||||
}
|
||||
|
||||
bool operator!=(FileDataV9MM const & data) const { return !operator==(data); }
|
||||
|
||||
FileData ConvertToLatestVersion()
|
||||
{
|
||||
FileData data;
|
||||
data.m_deviceId = m_deviceId;
|
||||
data.m_serverId = m_serverId;
|
||||
|
||||
data.m_categoryData = m_categoryData.ConvertToLatestVersion();
|
||||
|
||||
data.m_bookmarksData.reserve(m_bookmarksData.size());
|
||||
for (auto & d : m_bookmarksData)
|
||||
data.m_bookmarksData.emplace_back(d.ConvertToLatestVersion());
|
||||
|
||||
data.m_tracksData.reserve(m_tracksData.size());
|
||||
for (auto & t : m_tracksData)
|
||||
data.m_tracksData.emplace_back(t.ConvertToLatestVersion());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Device id (it will not be serialized in text files).
|
||||
std::string m_deviceId;
|
||||
// Server id.
|
||||
std::string m_serverId;
|
||||
// Category's data.
|
||||
CategoryDataV8MM m_categoryData;
|
||||
// Bookmarks collection.
|
||||
std::vector<BookmarkDataV8MM> m_bookmarksData;
|
||||
// Tracks collection.
|
||||
std::vector<TrackDataV9MM> m_tracksData;
|
||||
};
|
||||
} // namespace kml
|
Reference in a new issue