From 36a4d31aa80d6ae4856357aa758592341f089474 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 29 Nov 2022 20:01:28 +0800 Subject: [PATCH] C++ headers: add sort comparator and deserialize_header --- cpp/pmtiles.hpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ cpp/test.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/cpp/pmtiles.hpp b/cpp/pmtiles.hpp index d528854..e068374 100644 --- a/cpp/pmtiles.hpp +++ b/cpp/pmtiles.hpp @@ -74,6 +74,57 @@ struct headerv3 { } }; +struct pmtiles_magic_number_exception : std::exception { + const char* what() const noexcept override { + return "pmtiles magic number exception"; + } +}; + +struct pmtiles_version_exception : std::exception { + const char* what() const noexcept override { + return "pmtiles version: must be 3"; + } +}; + +inline headerv3 deserialize_header(const std::string &s) { + if (s.substr(0,7) != "PMTiles") { + throw pmtiles_magic_number_exception{}; + } + if (s.size() != 127 || s[7] != 0x3) { + throw pmtiles_version_exception{}; + } + headerv3 h; + s.copy((char *)&h.root_dir_offset,8,8); + s.copy((char *)&h.root_dir_bytes,8,16); + s.copy((char *)&h.json_metadata_offset,8,24); + s.copy((char *)&h.json_metadata_bytes,8,32); + s.copy((char *)&h.leaf_dirs_offset,8,40); + s.copy((char *)&h.leaf_dirs_bytes,8,48); + s.copy((char *)&h.tile_data_offset,8,56); + s.copy((char *)&h.tile_data_bytes,8,64); + s.copy((char *)&h.addressed_tiles_count,8,72); + s.copy((char *)&h.tile_entries_count,8,80); + s.copy((char *)&h.tile_contents_count,8,88); + if (s[96] == 0x1) { + h.clustered = true; + } else { + h.clustered = false; + } + h.internal_compression = s[97]; + h.tile_compression = s[98]; + h.tile_type = s[99]; + h.min_zoom = s[100]; + h.max_zoom = s[101]; + s.copy((char *)&h.min_lon_e7,4,102); + s.copy((char *)&h.min_lat_e7,4,106); + s.copy((char *)&h.max_lon_e7,4,110); + s.copy((char *)&h.max_lat_e7,4,114); + h.center_zoom = s[118]; + s.copy((char *)&h.center_lon_e7,4,119); + s.copy((char *)&h.center_lat_e7,4,123); + return h; +} + struct zxy { uint8_t z; uint32_t x; @@ -97,6 +148,10 @@ struct entryv3 { } }; +struct { + bool operator()(entryv3 a, entryv3 b) const { return a.tile_id < b.tile_id; } +} entryv3_cmp; + struct varint_too_long_exception : std::exception { const char* what() const noexcept override { return "varint too long exception"; diff --git a/cpp/test.cpp b/cpp/test.cpp index eaa8fa6..e596d74 100644 --- a/cpp/test.cpp +++ b/cpp/test.cpp @@ -67,11 +67,66 @@ MU_TEST(test_serialize_header) { mu_check(len == 127); } +MU_TEST(test_deserialize_header) { + headerv3 header; + header.root_dir_offset = 1; + header.root_dir_bytes = 2; + header.json_metadata_offset = 3; + header.json_metadata_bytes = 4; + header.leaf_dirs_offset = 5; + header.leaf_dirs_bytes = 6; + header.tile_data_offset = 7; + header.tile_data_bytes = 8; + header.addressed_tiles_count = 9; + header.tile_entries_count = 10; + header.tile_contents_count = 11; + header.clustered = true; + header.internal_compression = 0x1; + header.tile_compression = 0x2; + header.tile_type = 0x3; + header.min_zoom = 12; + header.max_zoom = 13; + header.min_lon_e7 = 14; + header.min_lat_e7 = 15; + header.max_lon_e7 = 16; + header.max_lat_e7 = 17; + header.center_zoom = 14; + header.center_lon_e7 = 18; + header.center_lat_e7 = 19; + auto serialized = header.serialize(); + auto deserialized = deserialize_header(serialized); + mu_check(deserialized.root_dir_offset == 1); + mu_check(deserialized.root_dir_bytes == 2); + mu_check(deserialized.json_metadata_offset == 3); + mu_check(deserialized.json_metadata_bytes == 4); + mu_check(deserialized.leaf_dirs_offset == 5); + mu_check(deserialized.leaf_dirs_bytes == 6); + mu_check(deserialized.tile_data_offset == 7); + mu_check(deserialized.tile_data_bytes == 8); + mu_check(deserialized.addressed_tiles_count == 9); + mu_check(deserialized.tile_entries_count == 10); + mu_check(deserialized.tile_contents_count == 11); + mu_check(deserialized.clustered == true); + mu_check(deserialized.internal_compression == 0x1); + mu_check(deserialized.tile_compression == 0x2); + mu_check(deserialized.tile_type == 0x3); + mu_check(deserialized.min_zoom == 12); + mu_check(deserialized.max_zoom == 13); + mu_check(deserialized.min_lon_e7 == 14); + mu_check(deserialized.min_lat_e7 == 15); + mu_check(deserialized.max_lon_e7 == 16); + mu_check(deserialized.max_lat_e7 == 17); + mu_check(deserialized.center_zoom == 14); + mu_check(deserialized.center_lon_e7 == 18); + mu_check(deserialized.center_lat_e7 == 19); +} + MU_TEST_SUITE(test_suite) { MU_RUN_TEST(test_tileid_to_zxy); MU_RUN_TEST(test_zxy_to_tileid); MU_RUN_TEST(test_serialize_directory); MU_RUN_TEST(test_serialize_header); + MU_RUN_TEST(test_deserialize_header); } int main(int argc, char *argv[]) {