diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c61d1..3d3647c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.12.9 + +* Clean up parsing and serialization. Provide some context with parsing errors. + ## 1.12.8 * Fix the spelling of the --preserve-input-order option diff --git a/geojson.cpp b/geojson.cpp index 272873c..3f071e2 100644 --- a/geojson.cpp +++ b/geojson.cpp @@ -63,11 +63,23 @@ static int mb_geometry[GEOM_TYPES] = { VT_POINT, VT_POINT, VT_LINE, VT_LINE, VT_POLYGON, VT_POLYGON, }; -long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, int op, const char *fname, int line, int *initialized, unsigned *initial_x, unsigned *initial_y) { +void json_context(json_object *j) { + char *s = json_stringify(j); + + if (strlen(s) >= 500) { + sprintf(s + 497, "..."); + } + + fprintf(stderr, "In JSON object %s\n", s); + free(s); +} + +long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, int op, const char *fname, int line, int *initialized, unsigned *initial_x, unsigned *initial_y, json_object *feature) { long long g = 0; if (j == NULL || j->type != JSON_ARRAY) { fprintf(stderr, "%s:%d: expected array for type %d\n", fname, line, t); + json_context(feature); return g; } @@ -83,7 +95,7 @@ long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, i } } - g += parse_geometry(within, j->array[i], bbox, out, op, fname, line, initialized, initial_x, initial_y); + g += parse_geometry(within, j->array[i], bbox, out, op, fname, line, initialized, initial_x, initial_y, feature); } } else { if (j->length >= 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { @@ -97,6 +109,8 @@ long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, i if (!warned) { fprintf(stderr, "%s:%d: ignoring dimensions beyond two\n", fname, line); + json_context(j); + json_context(feature); warned = 1; } } @@ -131,6 +145,8 @@ long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, i g++; } else { fprintf(stderr, "%s:%d: malformed point\n", fname, line); + json_context(j); + json_context(feature); } } @@ -150,12 +166,13 @@ long long parse_geometry(int t, json_object *j, long long *bbox, drawvec &out, i return g; } -int serialize_geometry(json_object *geometry, json_object *properties, json_object *id, const char *reading, int line, volatile long long *layer_seq, volatile long long *progress_seq, long long *metapos, long long *geompos, long long *indexpos, std::set *exclude, std::set *include, int exclude_all, FILE *metafile, FILE *geomfile, FILE *indexfile, struct memfile *poolfile, struct memfile *treefile, const char *fname, int basezoom, int layer, double droprate, long long *file_bbox, json_object *tippecanoe, int segment, int *initialized, unsigned *initial_x, unsigned *initial_y, struct reader *readers, std::set *file_keys, int maxzoom) { +int serialize_geometry(json_object *geometry, json_object *properties, json_object *id, const char *reading, int line, volatile long long *layer_seq, volatile long long *progress_seq, long long *metapos, long long *geompos, long long *indexpos, std::set *exclude, std::set *include, int exclude_all, FILE *metafile, FILE *geomfile, FILE *indexfile, struct memfile *poolfile, struct memfile *treefile, const char *fname, int basezoom, int layer, double droprate, long long *file_bbox, json_object *tippecanoe, int segment, int *initialized, unsigned *initial_x, unsigned *initial_y, struct reader *readers, std::set *file_keys, int maxzoom, json_object *feature) { json_object *geometry_type = json_hash_get(geometry, "type"); if (geometry_type == NULL) { static int warned = 0; if (!warned) { fprintf(stderr, "%s:%d: null geometry (additional not reported)\n", reading, line); + json_context(feature); warned = 1; } @@ -163,13 +180,15 @@ int serialize_geometry(json_object *geometry, json_object *properties, json_obje } if (geometry_type->type != JSON_STRING) { - fprintf(stderr, "%s:%d: geometry without type\n", reading, line); + fprintf(stderr, "%s:%d: geometry type is not a string\n", reading, line); + json_context(feature); return 0; } json_object *coordinates = json_hash_get(geometry, "coordinates"); if (coordinates == NULL || coordinates->type != JSON_ARRAY) { fprintf(stderr, "%s:%d: feature without coordinates array\n", reading, line); + json_context(feature); return 0; } @@ -181,6 +200,7 @@ int serialize_geometry(json_object *geometry, json_object *properties, json_obje } if (t >= GEOM_TYPES) { fprintf(stderr, "%s:%d: Can't handle geometry type %s\n", reading, line, geometry_type->string); + json_context(feature); return 0; } @@ -288,7 +308,7 @@ int serialize_geometry(json_object *geometry, json_object *properties, json_obje } drawvec dv; - long long g = parse_geometry(t, coordinates, bbox, dv, VT_MOVETO, fname, line, initialized, initial_x, initial_y); + long long g = parse_geometry(t, coordinates, bbox, dv, VT_MOVETO, fname, line, initialized, initial_x, initial_y, feature); if (mb_geometry[t] == VT_POLYGON) { dv = fix_polygon(dv); } @@ -440,6 +460,9 @@ void parse_json(json_pull *jp, const char *reading, volatile long long *layer_se if (j == NULL) { if (jp->error != NULL) { fprintf(stderr, "%s:%d: %s\n", reading, jp->line, jp->error); + if (jp->root != NULL) { + json_context(jp->root); + } } json_free(jp->root); @@ -495,7 +518,7 @@ void parse_json(json_pull *jp, const char *reading, volatile long long *layer_se } found_geometries++; - serialize_geometry(j, NULL, NULL, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, NULL, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom); + serialize_geometry(j, NULL, NULL, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, NULL, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom, j); json_free(j); continue; } @@ -517,6 +540,7 @@ void parse_json(json_pull *jp, const char *reading, volatile long long *layer_se json_object *geometry = json_hash_get(j, "geometry"); if (geometry == NULL) { fprintf(stderr, "%s:%d: feature with no geometry\n", reading, jp->line); + json_context(j); json_free(j); continue; } @@ -524,6 +548,7 @@ void parse_json(json_pull *jp, const char *reading, volatile long long *layer_se json_object *properties = json_hash_get(j, "properties"); if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) { fprintf(stderr, "%s:%d: feature without properties hash\n", reading, jp->line); + json_context(j); json_free(j); continue; } @@ -535,10 +560,10 @@ void parse_json(json_pull *jp, const char *reading, volatile long long *layer_se if (geometries != NULL) { size_t g; for (g = 0; g < geometries->length; g++) { - serialize_geometry(geometries->array[g], properties, id, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, tippecanoe, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom); + serialize_geometry(geometries->array[g], properties, id, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, tippecanoe, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom, j); } } else { - serialize_geometry(geometry, properties, id, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, tippecanoe, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom); + serialize_geometry(geometry, properties, id, reading, jp->line, layer_seq, progress_seq, metapos, geompos, indexpos, exclude, include, exclude_all, metafile, geomfile, indexfile, poolfile, treefile, fname, basezoom, layer, droprate, file_bbox, tippecanoe, segment, initialized, initial_x, initial_y, readers, file_keys, maxzoom, j); } json_free(j); diff --git a/version.hpp b/version.hpp index 932c0e7..6eae3fa 100644 --- a/version.hpp +++ b/version.hpp @@ -1 +1 @@ -#define VERSION "tippecanoe v1.12.8\n" +#define VERSION "tippecanoe v1.12.9\n"