diff --git a/geojson.cpp b/geojson.cpp index b0c6daa..dba5857 100644 --- a/geojson.cpp +++ b/geojson.cpp @@ -194,41 +194,20 @@ int serialize_geometry(json_object *geometry, json_object *properties, json_obje continue; } - type_and_string tas; - tas.string = s; - tas.type = -1; + int type = -1; + std::string val; + stringify_value(properties->values[i], type, val, reading, line, feature); - metakey[m] = properties->keys[i]->string; + if (type >= 0) { + metakey[m] = properties->keys[i]->string; + metatype[m] = type; + metaval[m] = val; + m++; - if (properties->values[i] != NULL && properties->values[i]->type == JSON_STRING) { - tas.type = metatype[m] = VT_STRING; - metaval[m] = std::string(properties->values[i]->string); - std::string err = check_utf8(metaval[m]); - if (err != "") { - fprintf(stderr, "%s:%d: %s\n", reading, line, err.c_str()); - json_context(feature); - exit(EXIT_FAILURE); - } - m++; - } else if (properties->values[i] != NULL && properties->values[i]->type == JSON_NUMBER) { - tas.type = metatype[m] = VT_NUMBER; - metaval[m] = std::string(properties->values[i]->string); - m++; - } else if (properties->values[i] != NULL && (properties->values[i]->type == JSON_TRUE || properties->values[i]->type == JSON_FALSE)) { - tas.type = metatype[m] = VT_BOOLEAN; - metaval[m] = std::string(properties->values[i]->type == JSON_TRUE ? "true" : "false"); - m++; - } else if (properties->values[i] != NULL && (properties->values[i]->type == JSON_NULL)) { - ; - } else { - tas.type = metatype[m] = VT_STRING; - const char *v = json_stringify(properties->values[i]); - metaval[m] = std::string(v); - free((void *) v); // stringify - m++; - } + type_and_string tas; + tas.string = s; + tas.type = type; - if (tas.type >= 0) { auto fk = layermap->find(layername); fk->second.file_keys.insert(tas); } diff --git a/mvt.cpp b/mvt.cpp index f11164b..a0fbdbe 100644 --- a/mvt.cpp +++ b/mvt.cpp @@ -4,7 +4,9 @@ #include #include #include +#include #include "mvt.hpp" +#include "geometry.hpp" #include "protozero/varint.hpp" #include "protozero/pbf_reader.hpp" #include "protozero/pbf_writer.hpp" @@ -417,3 +419,69 @@ void mvt_layer::tag(mvt_feature &feature, std::string key, mvt_value value) { feature.tags.push_back(ko); feature.tags.push_back(vo); } + +static int is_integer(const char *s, long long *v) { + errno = 0; + char *endptr; + + *v = strtoll(s, &endptr, 0); + if (*v == 0 && errno != 0) { + return 0; + } + if ((*v == LLONG_MIN || *v == LLONG_MAX) && (errno == ERANGE)) { + return 0; + } + if (*endptr != '\0') { + // Special case: If it is an integer followed by .0000 or similar, + // it is still an integer + + if (*endptr != '.') { + return 0; + } + endptr++; + for (; *endptr != '\0'; endptr++) { + if (*endptr != '0') { + return 0; + } + } + + return 1; + } + + return 1; +} + +mvt_value stringified_to_mvt_value(int type, const char *s) { + mvt_value tv; + + if (type == VT_NUMBER) { + long long v; + if (is_integer(s, &v)) { + if (v >= 0) { + tv.type = mvt_int; + tv.numeric_value.int_value = v; + } else { + tv.type = mvt_sint; + tv.numeric_value.sint_value = v; + } + } else { + double d = atof(s); + + if (d == (float) d) { + tv.type = mvt_float; + tv.numeric_value.float_value = d; + } else { + tv.type = mvt_double; + tv.numeric_value.double_value = d; + } + } + } else if (type == VT_BOOLEAN) { + tv.type = mvt_bool; + tv.numeric_value.bool_value = (s[0] == 't'); + } else { + tv.type = mvt_string; + tv.string_value = s; + } + + return tv; +} diff --git a/mvt.hpp b/mvt.hpp index ff07467..d1b641a 100644 --- a/mvt.hpp +++ b/mvt.hpp @@ -86,3 +86,5 @@ bool is_compressed(std::string const &data); int decompress(std::string const &input, std::string &output); int compress(std::string const &input, std::string &output); int dezig(unsigned n); + +mvt_value stringified_to_mvt_value(int type, const char *s); diff --git a/plugin.cpp b/plugin.cpp index 2f64087..ff77391 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -182,20 +182,14 @@ mvt_layer parse_layer(int fd, unsigned z, unsigned x, unsigned y, mvt_layer cons } for (size_t i = 0; i < properties->length; i++) { - mvt_value v; + int tp = -1; + std::string s; - // XXX reconcile with JSON property parsing - if (properties->values[i]->type == JSON_STRING) { - v.type = mvt_string; - v.string_value = std::string(properties->values[i]->string); - } else if (properties->values[i]->type == JSON_NUMBER) { - v.type = mvt_double; - v.numeric_value.double_value = atof(properties->values[i]->string); - } else { - continue; + stringify_value(properties->values[i], tp, s, "Filter output", jp->line, j); + if (tp >= 0) { + mvt_value v = stringified_to_mvt_value(tp, s.c_str()); + ret.tag(feature, std::string(properties->keys[i]->string), v); } - - ret.tag(feature, std::string(properties->keys[i]->string), v); } ret.features.push_back(feature); diff --git a/read_json.cpp b/read_json.cpp index 660d5a1..7158a53 100644 --- a/read_json.cpp +++ b/read_json.cpp @@ -2,6 +2,7 @@ #include #include #include +#include extern "C" { #include "jsonpull/jsonpull.h" @@ -10,6 +11,7 @@ extern "C" { #include "geometry.hpp" #include "projection.hpp" #include "read_json.hpp" +#include "text.hpp" const char *geometry_names[GEOM_TYPES] = { "Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", @@ -100,3 +102,29 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna out.push_back(draw(VT_CLOSEPATH, 0, 0)); } } + +void stringify_value(json_object *value, int &type, std::string &stringified, const char *reading, int line, json_object *feature) { + if (value != NULL && value->type == JSON_STRING) { + type = VT_STRING; + stringified = std::string(value->string); + std::string err = check_utf8(stringified); + if (err != "") { + fprintf(stderr, "%s:%d: %s\n", reading, line, err.c_str()); + json_context(feature); + exit(EXIT_FAILURE); + } + } else if (value != NULL && value->type == JSON_NUMBER) { + type = VT_NUMBER; + stringified = std::string(value->string); + } else if (value != NULL && (value->type == JSON_TRUE || value->type == JSON_FALSE)) { + type = VT_BOOLEAN; + stringified = std::string(value->type == JSON_TRUE ? "true" : "false"); + } else if (value != NULL && (value->type == JSON_NULL)) { + ; + } else { + type = VT_STRING; + const char *v = json_stringify(value); + stringified = std::string(v); + free((void *) v); // stringify + } +} diff --git a/read_json.hpp b/read_json.hpp index 7cf4c9f..559329e 100644 --- a/read_json.hpp +++ b/read_json.hpp @@ -12,3 +12,5 @@ extern int mb_geometry[GEOM_TYPES]; void json_context(json_object *j); void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature); + +void stringify_value(json_object *value, int &type, std::string &stringified, const char *reading, int line, json_object *feature); diff --git a/tile.cpp b/tile.cpp index 264f50c..9a93501 100644 --- a/tile.cpp +++ b/tile.cpp @@ -62,7 +62,6 @@ bool draws_something(drawvec &geom) { int metacmp(int m1, const std::vector &keys1, const std::vector &values1, char *stringpool1, int m2, const std::vector &keys2, const std::vector &values2, char *stringpool2); int coalindexcmp(const struct coalesce *c1, const struct coalesce *c2); -static int is_integer(const char *s, long long *v); struct coalesce { char *meta; @@ -136,37 +135,7 @@ mvt_value retrieve_string(long long off, char *stringpool, int *otype) { *otype = type; } - mvt_value tv; - if (type == VT_NUMBER) { - long long v; - if (is_integer(s, &v)) { - if (v >= 0) { - tv.type = mvt_int; - tv.numeric_value.int_value = v; - } else { - tv.type = mvt_sint; - tv.numeric_value.sint_value = v; - } - } else { - double d = atof(s); - - if (d == (float) d) { - tv.type = mvt_float; - tv.numeric_value.float_value = d; - } else { - tv.type = mvt_double; - tv.numeric_value.double_value = d; - } - } - } else if (type == VT_BOOLEAN) { - tv.type = mvt_bool; - tv.numeric_value.bool_value = (s[0] == 't'); - } else { - tv.type = mvt_string; - tv.string_value = s; - } - - return tv; + return stringified_to_mvt_value(type, s); } void decode_meta(int m, std::vector &metakeys, std::vector &metavals, char *stringpool, mvt_layer &layer, mvt_feature &feature) { @@ -223,37 +192,6 @@ int metacmp(int m1, const std::vector &keys1, const std::vector &metakeys, std::vector &metavals, bool has_id, unsigned long long id, unsigned long long index, long long extent) { if (geom.size() > 0 && nextzoom <= maxzoom) { int xo, yo;