From bfc211adc7b8ff963a2e4f0d0d188353f2087217 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Tue, 14 Aug 2018 17:55:02 -0700 Subject: [PATCH] Closer to encoding and decoding lists and hashes --- mvt.cpp | 93 ++++++++++++++++++++++++++++++++++++++------------ mvt.hpp | 2 +- tile-join.cpp | 8 +++-- write_json.cpp | 6 ++-- 4 files changed, 82 insertions(+), 27 deletions(-) diff --git a/mvt.cpp b/mvt.cpp index 69655ff..cbb78f4 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -902,31 +902,31 @@ void mvt_layer::reorder_values() { } } -mvt_value mvt_layer::decode_property(unsigned long property) const { - int type = property & 0x0F; +mvt_value mvt_layer::decode_property(std::vector const &property, size_t &off) const { + int type = property[off] & 0x0F; mvt_value ret; switch (type) { case 0: /* signed integer */ ret.type = mvt_sint; - ret.numeric_value.sint_value = protozero::decode_zigzag64(property >> 4); + ret.numeric_value.sint_value = protozero::decode_zigzag64(property[off] >> 4); return ret; case 1: /* unsigned integer */ ret.type = mvt_uint; - ret.numeric_value.uint_value = property >> 4; + ret.numeric_value.uint_value = property[off] >> 4; return ret; case 2: /* boolean */ ret.type = mvt_bool; - ret.numeric_value.bool_value = property >> 4; + ret.numeric_value.bool_value = property[off] >> 4; return ret; case 3: /* float reference */ ret.type = mvt_float; if (mvt_format == mvt_blake_float) { unsigned char buf[sizeof(float)]; - unsigned long val = property >> 4; + unsigned long val = property[off] >> 4; for (size_t i = 0; i < sizeof(float); i++) { buf[i] = val >> (i * 8); } @@ -934,48 +934,99 @@ mvt_value mvt_layer::decode_property(unsigned long property) const { memcpy(&f, buf, sizeof(float)); ret.numeric_value.float_value = f; } else { - if (property >> 4 >= float_values.size()) { - fprintf(stderr, "Out of bounds float reference: %lu vs %zu\n", property >> 4, float_values.size()); + if (property[off] >> 4 >= float_values.size()) { + fprintf(stderr, "Out of bounds float reference: %lu vs %zu\n", property[off] >> 4, float_values.size()); exit(EXIT_FAILURE); } - ret.numeric_value.float_value = float_values[property >> 4]; + ret.numeric_value.float_value = float_values[property[off] >> 4]; } return ret; case 4: /* double reference */ ret.type = mvt_double; - if (property >> 4 >= double_values.size()) { - fprintf(stderr, "Out of bounds double reference: %lu vs %zu\n", property >> 4, double_values.size()); + if (property[off] >> 4 >= double_values.size()) { + fprintf(stderr, "Out of bounds double reference: %lu vs %zu\n", property[off] >> 4, double_values.size()); exit(EXIT_FAILURE); } - ret.numeric_value.double_value = double_values[property >> 4]; + ret.numeric_value.double_value = double_values[property[off] >> 4]; return ret; case 5: /* string reference */ ret.type = mvt_string; - if (property >> 4 >= string_values.size()) { - fprintf(stderr, "Out of bounds string reference: %lu vs %zu\n", property >> 4, string_values.size()); + if (property[off] >> 4 >= string_values.size()) { + fprintf(stderr, "Out of bounds string reference: %lu vs %zu\n", property[off] >> 4, string_values.size()); exit(EXIT_FAILURE); } - ret.string_value = string_values[property >> 4]; + ret.string_value = string_values[property[off] >> 4]; return ret; case 6: /* signed int reference */ ret.type = mvt_sint; - if (property >> 4 >= sint64_values.size()) { - fprintf(stderr, "Out of bounds sint reference: %lu vs %zu\n", property >> 4, sint64_values.size()); + if (property[off] >> 4 >= sint64_values.size()) { + fprintf(stderr, "Out of bounds sint reference: %lu vs %zu\n", property[off] >> 4, sint64_values.size()); exit(EXIT_FAILURE); } - ret.numeric_value.sint_value = sint64_values[property >> 4]; + ret.numeric_value.sint_value = sint64_values[property[off] >> 4]; return ret; case 7: /* unsigned int reference */ ret.type = mvt_uint; - if (property >> 4 >= uint64_values.size()) { - fprintf(stderr, "Out of bounds uint reference: %lu vs %zu\n", property >> 4, uint64_values.size()); + if (property[off] >> 4 >= uint64_values.size()) { + fprintf(stderr, "Out of bounds uint reference: %lu vs %zu\n", property[off] >> 4, uint64_values.size()); exit(EXIT_FAILURE); } - ret.numeric_value.uint_value = uint64_values[property >> 4]; + ret.numeric_value.uint_value = uint64_values[property[off] >> 4]; + return ret; + + case 8: /* hash or list */ + if (((property[off] >> 4) & 1) == 0) { + ret.type = mvt_hash; + size_t len = property[off] >> 5; + fprintf(stderr, "hash %zu\n", len); + off++; + + ret.string_value = "{"; + + for (size_t i = 0; i < len; i++) { + mvt_value v1 = decode_property(property, off); + off++; + + mvt_value v2 = decode_property(property, off); + off++; + + ret.string_value.append(v1.toString()); + ret.string_value.append(":"); + ret.string_value.append(v2.toString()); + + if (i + 1 < len) { + ret.string_value.push_back(','); + } + } + + ret.string_value.append("}"); + off--; // so caller can increment + } else { + ret.type = mvt_list; + size_t len = property[off] >> 5; + fprintf(stderr, "array %zu\n", len); + off++; + + ret.string_value = "["; + + for (size_t i = 0; i < len; i++) { + mvt_value v1 = decode_property(property, off); + off++; + + ret.string_value.append(v1.toString()); + + if (i + 1 < len) { + ret.string_value.push_back(','); + } + } + + ret.string_value.append("]"); + off--; // so caller can increment + } return ret; default: diff --git a/mvt.hpp b/mvt.hpp index 9589beb..bc1e6fb 100644 --- a/mvt.hpp +++ b/mvt.hpp @@ -129,7 +129,7 @@ struct mvt_layer { std::map value_map{}; std::map property_map{}; - mvt_value decode_property(unsigned long property) const; + mvt_value decode_property(std::vector const &property, size_t &off) const; void reorder_values(); }; diff --git a/tile-join.cpp b/tile-join.cpp index 8ce05da..d57cfe4 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -159,9 +159,10 @@ void handle(std::string message, int z, unsigned x, unsigned y, std::map(key, val)); } - for (size_t t = 0; t + 1 < feat.properties.size(); t += 2) { + for (size_t t = 0; t + 1 < feat.properties.size(); t++) { std::string key = layer.keys[feat.properties[t]]; - mvt_value val = layer.decode_property(feat.properties[t + 1]); + t++; + mvt_value val = layer.decode_property(feat.properties, t); attributes.insert(std::pair(key, val)); } @@ -217,7 +218,8 @@ void handle(std::string message, int z, unsigned x, unsigned y, std::map(key, val)); } diff --git a/write_json.cpp b/write_json.cpp index 65e9248..32cd005 100644 --- a/write_json.cpp +++ b/write_json.cpp @@ -433,9 +433,11 @@ void layer_to_geojson(mvt_layer const &layer, unsigned z, unsigned x, unsigned y print_val(feat, layer, val, feat.tags[t + 1], state); } - for (size_t t = 0; t + 1 < feat.properties.size(); t += 2) { + for (size_t t = 0; t + 1 < feat.properties.size(); t++) { const char *key = layer.keys[feat.properties[t]].c_str(); - mvt_value const &val = layer.decode_property(feat.properties[t + 1]); + + t++; + mvt_value const &val = layer.decode_property(feat.properties, t); state.json_write_string(key); print_val(feat, layer, val, feat.properties[t + 1], state);