From 3f9dfdc452fc24a99b1627c58e1d7c9f621b4326 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Mon, 4 Jun 2018 16:56:27 -0700 Subject: [PATCH] Progress on converting jsonpull to more of a C++ idiom --- decode.cpp | 2 +- dirtiles.cpp | 8 +- evaluator.cpp | 120 ++++----- evaluator.hpp | 2 +- geobuf.cpp | 6 +- geojson.cpp | 51 ++-- geojson.hpp | 2 +- jsonpull/{jsonpull.c => jsonpull.cpp} | 374 +++++++++----------------- jsonpull/{jsonpull.h => jsonpull.hpp} | 38 ++- jsontool.cpp | 72 ++--- main.cpp | 4 +- plugin.cpp | 50 ++-- read_json.cpp | 37 ++- serial.hpp | 2 +- tile-join.cpp | 16 +- tile.cpp | 2 +- tile.hpp | 2 +- 17 files changed, 313 insertions(+), 475 deletions(-) rename jsonpull/{jsonpull.c => jsonpull.cpp} (62%) rename jsonpull/{jsonpull.h => jsonpull.hpp} (75%) diff --git a/decode.cpp b/decode.cpp index 63d70b8..4772575 100644 --- a/decode.cpp +++ b/decode.cpp @@ -20,7 +20,7 @@ #include "projection.hpp" #include "geometry.hpp" #include "write_json.hpp" -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "dirtiles.hpp" int minzoom = 0; diff --git a/dirtiles.cpp b/dirtiles.cpp index 3104caf..c8df2e2 100644 --- a/dirtiles.cpp +++ b/dirtiles.cpp @@ -9,7 +9,7 @@ #include #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "dirtiles.hpp" std::string dir_read_tile(std::string base, struct zxy tile) { @@ -181,14 +181,14 @@ sqlite3 *dirmeta2tmp(const char *fname) { exit(EXIT_FAILURE); } - for (size_t i = 0; i < o->length; i++) { + for (size_t i = 0; i < o->keys.size(); i++) { if (o->keys[i]->type != JSON_STRING || o->values[i]->type != JSON_STRING) { fprintf(stderr, "%s: non-string in metadata\n", name.c_str()); } - char *sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES (%Q, %Q);", o->keys[i]->string, o->values[i]->string); + char *sql = sqlite3_mprintf("INSERT INTO metadata (name, value) VALUES (%Q, %Q);", o->keys[i]->string.c_str(), o->values[i]->string.c_str()); if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) { - fprintf(stderr, "set %s in metadata: %s\n", o->keys[i]->string, err); + fprintf(stderr, "set %s in metadata: %s\n", o->keys[i]->string.c_str(), err); } sqlite3_free(sql); } diff --git a/evaluator.cpp b/evaluator.cpp index 20fe823..5bff04a 100644 --- a/evaluator.cpp +++ b/evaluator.cpp @@ -12,7 +12,7 @@ int compare(mvt_value one, json_object *two, bool &fail) { return false; // string vs non-string } - return strcmp(one.string_value.c_str(), two->string); + return strcmp(one.string_value.c_str(), two->string.c_str()); } if (one.type == mvt_double || one.type == mvt_float || one.type == mvt_int || one.type == mvt_uint || one.type == mvt_sint) { @@ -71,56 +71,56 @@ int compare(mvt_value one, json_object *two, bool &fail) { bool eval(std::map const &feature, json_object *f) { if (f == NULL || f->type != JSON_ARRAY) { - fprintf(stderr, "Filter is not an array: %s\n", json_stringify(f)); + fprintf(stderr, "Filter is not an array: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } - if (f->length < 1) { - fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f)); + if (f->array.size() < 1) { + fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } if (f->array[0]->type != JSON_STRING) { - fprintf(stderr, "Filter operation is not a string: %s\n", json_stringify(f)); + fprintf(stderr, "Filter operation is not a string: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } - if (strcmp(f->array[0]->string, "has") == 0 || - strcmp(f->array[0]->string, "!has") == 0) { - if (f->length != 2) { - fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f)); + if (f->array[0]->string == "has" || + f->array[0]->string == "!has") { + if (f->array.size() != 2) { + fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } - if (strcmp(f->array[0]->string, "has") == 0) { + if (f->array[0]->string == "has") { if (f->array[1]->type != JSON_STRING) { - fprintf(stderr, "\"has\" key is not a string: %s\n", json_stringify(f)); + fprintf(stderr, "\"has\" key is not a string: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } return feature.count(std::string(f->array[1]->string)) != 0; } - if (strcmp(f->array[0]->string, "!has") == 0) { + if (f->array[0]->string == "!has") { if (f->array[1]->type != JSON_STRING) { - fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f)); + fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } return feature.count(std::string(f->array[1]->string)) == 0; } } - if (strcmp(f->array[0]->string, "==") == 0 || - strcmp(f->array[0]->string, "!=") == 0 || - strcmp(f->array[0]->string, ">") == 0 || - strcmp(f->array[0]->string, ">=") == 0 || - strcmp(f->array[0]->string, "<") == 0 || - strcmp(f->array[0]->string, "<=") == 0) { - if (f->length != 3) { - fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f)); + if (f->array[0]->string == "==" || + f->array[0]->string == "!=" || + f->array[0]->string == ">" || + f->array[0]->string == ">=" || + f->array[0]->string == "<" || + f->array[0]->string == "<=") { + if (f->array.size() != 3) { + fprintf(stderr, "Wrong number of array elements in filter: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } if (f->array[1]->type != JSON_STRING) { - fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f)); + fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } @@ -128,12 +128,11 @@ bool eval(std::map const &feature, json_object *f) { if (ff == feature.end()) { static bool warned = false; if (!warned) { - const char *s = json_stringify(f); - fprintf(stderr, "Warning: attribute not found for comparison: %s\n", s); - free((void *) s); + std::string s = json_stringify(f); + fprintf(stderr, "Warning: attribute not found for comparison: %s\n", s.c_str()); warned = true; } - if (strcmp(f->array[0]->string, "!=") == 0) { + if (f->array[0]->string == "!=") { return true; // attributes that aren't found are not equal } return false; // not found: comparison is false @@ -145,55 +144,54 @@ bool eval(std::map const &feature, json_object *f) { if (fail) { static bool warned = false; if (!warned) { - const char *s = json_stringify(f); - fprintf(stderr, "Warning: mismatched type in comparison: %s\n", s); - free((void *) s); + std::string s = json_stringify(f); + fprintf(stderr, "Warning: mismatched type in comparison: %s\n", s.c_str()); warned = true; } - if (strcmp(f->array[0]->string, "!=") == 0) { + if (f->array[0]->string == "!=") { return true; // mismatched types are not equal } return false; } - if (strcmp(f->array[0]->string, "==") == 0) { + if (f->array[0]->string == "==") { return cmp == 0; } - if (strcmp(f->array[0]->string, "!=") == 0) { + if (f->array[0]->string == "!=") { return cmp != 0; } - if (strcmp(f->array[0]->string, ">") == 0) { + if (f->array[0]->string == ">") { return cmp > 0; } - if (strcmp(f->array[0]->string, ">=") == 0) { + if (f->array[0]->string == ">=") { return cmp >= 0; } - if (strcmp(f->array[0]->string, "<") == 0) { + if (f->array[0]->string == "<") { return cmp < 0; } - if (strcmp(f->array[0]->string, "<=") == 0) { + if (f->array[0]->string == "<=") { return cmp <= 0; } - fprintf(stderr, "Internal error: can't happen: %s\n", json_stringify(f)); + fprintf(stderr, "Internal error: can't happen: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } - if (strcmp(f->array[0]->string, "all") == 0 || - strcmp(f->array[0]->string, "any") == 0 || - strcmp(f->array[0]->string, "none") == 0) { + if (f->array[0]->string == "all" || + f->array[0]->string == "any" || + f->array[0]->string == "none") { bool v; - if (strcmp(f->array[0]->string, "all") == 0) { + if (f->array[0]->string == "all") { v = true; } else { v = false; } - for (size_t i = 1; i < f->length; i++) { + for (size_t i = 1; i < f->array.size(); i++) { bool out = eval(feature, f->array[i]); - if (strcmp(f->array[0]->string, "all") == 0) { + if (f->array[0]->string == "all") { v = v && out; if (!v) { break; @@ -206,22 +204,22 @@ bool eval(std::map const &feature, json_object *f) { } } - if (strcmp(f->array[0]->string, "none") == 0) { + if (f->array[0]->string == "none") { return !v; } else { return v; } } - if (strcmp(f->array[0]->string, "in") == 0 || - strcmp(f->array[0]->string, "!in") == 0) { - if (f->length < 2) { - fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f)); + if (f->array[0]->string == "in" || + f->array[0]->string == "!in") { + if (f->array.size() < 2) { + fprintf(stderr, "Array too small in filter: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } if (f->array[1]->type != JSON_STRING) { - fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f)); + fprintf(stderr, "\"!has\" key is not a string: %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } @@ -229,28 +227,26 @@ bool eval(std::map const &feature, json_object *f) { if (ff == feature.end()) { static bool warned = false; if (!warned) { - const char *s = json_stringify(f); - fprintf(stderr, "Warning: attribute not found for comparison: %s\n", s); - free((void *) s); + std::string s = json_stringify(f); + fprintf(stderr, "Warning: attribute not found for comparison: %s\n", s.c_str()); warned = true; } - if (strcmp(f->array[0]->string, "!in") == 0) { + if (f->array[0]->string == "!in") { return true; // attributes that aren't found are not in } return false; // not found: comparison is false } bool found = false; - for (size_t i = 2; i < f->length; i++) { + for (size_t i = 2; i < f->array.size(); i++) { bool fail = false; int cmp = compare(ff->second, f->array[i], fail); if (fail) { static bool warned = false; if (!warned) { - const char *s = json_stringify(f); - fprintf(stderr, "Warning: mismatched type in comparison: %s\n", s); - free((void *) s); + std::string s = json_stringify(f); + fprintf(stderr, "Warning: mismatched type in comparison: %s\n", s.c_str()); warned = true; } cmp = 1; @@ -262,20 +258,20 @@ bool eval(std::map const &feature, json_object *f) { } } - if (strcmp(f->array[0]->string, "in") == 0) { + if (f->array[0]->string == "in") { return found; } else { return !found; } } - fprintf(stderr, "Unknown filter %s\n", json_stringify(f)); + fprintf(stderr, "Unknown filter %s\n", json_stringify(f).c_str()); exit(EXIT_FAILURE); } bool evaluate(std::map const &feature, std::string const &layer, json_object *filter) { if (filter == NULL || filter->type != JSON_HASH) { - fprintf(stderr, "Error: filter is not a hash: %s\n", json_stringify(filter)); + fprintf(stderr, "Error: filter is not a hash: %s\n", json_stringify(filter).c_str()); exit(EXIT_FAILURE); } @@ -305,7 +301,7 @@ json_object *read_filter(const char *fname) { json_pull *jp = json_begin_file(fp); json_object *filter = json_read_tree(jp); if (filter == NULL) { - fprintf(stderr, "%s: %s\n", fname, jp->error); + fprintf(stderr, "%s: %s\n", fname, jp->error.c_str()); exit(EXIT_FAILURE); } json_disconnect(filter); @@ -319,7 +315,7 @@ json_object *parse_filter(const char *s) { json_object *filter = json_read_tree(jp); if (filter == NULL) { fprintf(stderr, "Could not parse filter %s\n", s); - fprintf(stderr, "%s\n", jp->error); + fprintf(stderr, "%s\n", jp->error.c_str()); exit(EXIT_FAILURE); } json_disconnect(filter); diff --git a/evaluator.hpp b/evaluator.hpp index 99bcb27..7a03318 100644 --- a/evaluator.hpp +++ b/evaluator.hpp @@ -3,7 +3,7 @@ #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "mvt.hpp" bool evaluate(std::map const &feature, std::string const &layer, json_object *filter); diff --git a/geobuf.cpp b/geobuf.cpp index 6bfa872..8a495cb 100644 --- a/geobuf.cpp +++ b/geobuf.cpp @@ -12,7 +12,7 @@ #include "protozero/pbf_reader.hpp" #include "protozero/pbf_writer.hpp" #include "milo/dtoa_milo.h" -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #define POINT 0 #define MULTIPOINT 1 @@ -397,13 +397,13 @@ void readFeature(protozero::pbf_reader &pbf, size_t dim, double e, std::vectortype == JSON_STRING || min->type == JSON_NUMBER)) { sf.has_tippecanoe_minzoom = true; - sf.tippecanoe_minzoom = atoi(min->string); + sf.tippecanoe_minzoom = atoi(min->string.c_str()); } json_object *max = json_hash_get(o, "maxzoom"); if (max != NULL && (max->type == JSON_STRING || max->type == JSON_NUMBER)) { sf.has_tippecanoe_maxzoom = true; - sf.tippecanoe_maxzoom = atoi(max->string); + sf.tippecanoe_maxzoom = atoi(max->string.c_str()); } json_object *tlayer = json_hash_get(o, "layer"); diff --git a/geojson.cpp b/geojson.cpp index 514ecbe..7c46012 100644 --- a/geojson.cpp +++ b/geojson.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "pool.hpp" #include "projection.hpp" #include "memfile.hpp" @@ -66,12 +66,12 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom int t; for (t = 0; t < GEOM_TYPES; t++) { - if (strcmp(geometry_type->string, geometry_names[t]) == 0) { + if (geometry_type->string == std::string(geometry_names[t])) { break; } } if (t >= GEOM_TYPES) { - fprintf(stderr, "%s:%d: Can't handle geometry type %s\n", sst->fname, sst->line, geometry_type->string); + fprintf(stderr, "%s:%d: Can't handle geometry type %s\n", sst->fname, sst->line, geometry_type->string.c_str()); json_context(feature); return 0; } @@ -86,7 +86,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom tippecanoe_minzoom = min->number; } if (min != NULL && min->type == JSON_STRING) { - tippecanoe_minzoom = atoi(min->string); + tippecanoe_minzoom = atoi(min->string.c_str()); } json_object *max = json_hash_get(tippecanoe, "maxzoom"); @@ -94,7 +94,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom tippecanoe_maxzoom = max->number; } if (max != NULL && max->type == JSON_STRING) { - tippecanoe_maxzoom = atoi(max->string); + tippecanoe_maxzoom = atoi(max->string.c_str()); } json_object *ln = json_hash_get(tippecanoe, "layer"); @@ -109,13 +109,13 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom if (id->type == JSON_NUMBER) { if (id->number >= 0) { char *err = NULL; - id_value = strtoull(id->string, &err, 10); + id_value = strtoull(id->string.c_str(), &err, 10); if (err != NULL && *err != '\0') { static bool warned_frac = false; if (!warned_frac) { - fprintf(stderr, "Warning: Can't represent non-integer feature ID %s\n", id->string); + fprintf(stderr, "Warning: Can't represent non-integer feature ID %s\n", id->string.c_str()); warned_frac = true; } } else { @@ -125,7 +125,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom static bool warned_neg = false; if (!warned_neg) { - fprintf(stderr, "Warning: Can't represent negative feature ID %s\n", id->string); + fprintf(stderr, "Warning: Can't represent negative feature ID %s\n", id->string.c_str()); warned_neg = true; } } @@ -133,9 +133,8 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom static bool warned_nan = false; if (!warned_nan) { - char *s = json_stringify(id); - fprintf(stderr, "Warning: Can't represent non-numeric feature ID %s\n", s); - free(s); // stringify + std::string s = json_stringify(id); + fprintf(stderr, "Warning: Can't represent non-numeric feature ID %s\n", s.c_str()); warned_nan = true; } } @@ -143,10 +142,10 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object *geom size_t nprop = 0; if (properties != NULL && properties->type == JSON_HASH) { - nprop = properties->length; + nprop = properties->keys.size(); } - std::vector metakey; + std::vector metakey; metakey.resize(nprop); std::vector metaval; @@ -222,9 +221,9 @@ void check_crs(json_object *j, const char *reading) { if (properties != NULL) { json_object *name = json_hash_get(properties, "name"); if (name->type == JSON_STRING) { - if (strcmp(name->string, projection->alias) != 0) { + if (name->string != std::string(projection->alias)) { if (!quiet) { - fprintf(stderr, "%s: Warning: GeoJSON specified projection \"%s\", not the expected \"%s\".\n", reading, name->string, projection->alias); + fprintf(stderr, "%s: Warning: GeoJSON specified projection \"%s\", not the expected \"%s\".\n", reading, name->string.c_str(), projection->alias); fprintf(stderr, "%s: If \"%s\" is not the expected projection, use -s to specify the right one.\n", reading, projection->alias); } } @@ -241,8 +240,8 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: while (1) { json_object *j = json_read(jp); if (j == NULL) { - if (jp->error != NULL) { - fprintf(stderr, "%s:%d: %s\n", sst->fname, jp->line, jp->error); + if (jp->error.size() != 0) { + fprintf(stderr, "%s:%zu: %s\n", sst->fname, jp->line, jp->error.c_str()); if (jp->root != NULL) { json_context(jp->root); } @@ -256,7 +255,7 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: found_hashes++; if (found_hashes == 50 && found_features == 0 && found_geometries == 0) { - fprintf(stderr, "%s:%d: Warning: not finding any GeoJSON features or geometries in input yet after 50 objects.\n", sst->fname, jp->line); + fprintf(stderr, "%s:%zu: Warning: not finding any GeoJSON features or geometries in input yet after 50 objects.\n", sst->fname, jp->line); } } @@ -269,7 +268,7 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: int i; int is_geometry = 0; for (i = 0; i < GEOM_TYPES; i++) { - if (strcmp(type->string, geometry_names[i]) == 0) { + if (type->string == std::string(geometry_names[i])) { is_geometry = 1; break; } @@ -297,7 +296,7 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: if (is_geometry) { if (found_features != 0 && found_geometries == 0) { - fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line); + fprintf(stderr, "%s:%zu: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line); } found_geometries++; @@ -307,8 +306,8 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: } } - if (strcmp(type->string, "Feature") != 0) { - if (strcmp(type->string, "FeatureCollection") == 0) { + if (type->string != std::string("Feature")) { + if (type->string == std::string("FeatureCollection")) { check_crs(j, sst->fname); json_free(j); } @@ -317,13 +316,13 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: } if (found_features == 0 && found_geometries != 0) { - fprintf(stderr, "%s:%d: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line); + fprintf(stderr, "%s:%zu: Warning: found a mixture of features and bare geometries\n", sst->fname, jp->line); } found_features++; json_object *geometry = json_hash_get(j, "geometry"); if (geometry == NULL) { - fprintf(stderr, "%s:%d: feature with no geometry\n", sst->fname, jp->line); + fprintf(stderr, "%s:%zu: feature with no geometry\n", sst->fname, jp->line); json_context(j); json_free(j); continue; @@ -331,7 +330,7 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: 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", sst->fname, jp->line); + fprintf(stderr, "%s:%zu: feature without properties hash\n", sst->fname, jp->line); json_context(j); json_free(j); continue; @@ -343,7 +342,7 @@ void parse_json(struct serialization_state *sst, json_pull *jp, int layer, std:: json_object *geometries = json_hash_get(geometry, "geometries"); if (geometries != NULL && geometries->type == JSON_ARRAY) { size_t g; - for (g = 0; g < geometries->length; g++) { + for (g = 0; g < geometries->array.size(); g++) { serialize_geojson_feature(sst, geometries->array[g], properties, id, layer, tippecanoe, j, layername); } } else { diff --git a/geojson.hpp b/geojson.hpp index 664ea2e..3090a3e 100644 --- a/geojson.hpp +++ b/geojson.hpp @@ -6,7 +6,7 @@ #include #include #include "mbtiles.hpp" -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "serial.hpp" struct parse_json_args { diff --git a/jsonpull/jsonpull.c b/jsonpull/jsonpull.cpp similarity index 62% rename from jsonpull/jsonpull.c rename to jsonpull/jsonpull.cpp index d32a97e..86ac1bf 100644 --- a/jsonpull/jsonpull.c +++ b/jsonpull/jsonpull.cpp @@ -4,18 +4,18 @@ #include #include #include -#include "jsonpull.h" +#include "jsonpull.hpp" #define BUFFER 10000 json_pull *json_begin(ssize_t (*read)(struct json_pull *, char *buffer, size_t n), void *source) { - json_pull *j = malloc(sizeof(json_pull)); + json_pull *j = new json_pull; if (j == NULL) { perror("Out of memory"); exit(EXIT_FAILURE); } - j->error = NULL; + j->error = ""; j->line = 1; j->container = NULL; j->root = NULL; @@ -25,11 +25,7 @@ json_pull *json_begin(ssize_t (*read)(struct json_pull *, char *buffer, size_t n j->buffer_head = 0; j->buffer_tail = 0; - j->buffer = malloc(BUFFER); - if (j->buffer == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } + j->buffer.resize(BUFFER); return j; } @@ -39,7 +35,7 @@ static inline int peek(json_pull *j) { return (unsigned char) j->buffer[j->buffer_head]; } else { j->buffer_head = 0; - j->buffer_tail = j->read(j, j->buffer, BUFFER); + j->buffer_tail = j->read(j, (char *) j->buffer.c_str(), BUFFER); if (j->buffer_head >= j->buffer_tail) { return EOF; } @@ -52,7 +48,7 @@ static inline int next(json_pull *j) { return (unsigned char) j->buffer[j->buffer_head++]; } else { j->buffer_head = 0; - j->buffer_tail = j->read(j, j->buffer, BUFFER); + j->buffer_tail = j->read(j, (char *) j->buffer.c_str(), BUFFER); if (j->buffer_head >= j->buffer_tail) { return EOF; } @@ -61,7 +57,7 @@ static inline int next(json_pull *j) { } static ssize_t read_file(json_pull *j, char *buffer, size_t n) { - return fread(buffer, 1, n, j->source); + return fread(buffer, 1, n, (FILE *) j->source); } json_pull *json_begin_file(FILE *f) { @@ -69,7 +65,7 @@ json_pull *json_begin_file(FILE *f) { } static ssize_t read_string(json_pull *j, char *buffer, size_t n) { - const char *cp = j->source; + const char *cp = (const char *) j->source; size_t out = 0; while (out < n && cp[out] != '\0') { @@ -87,8 +83,7 @@ json_pull *json_begin_string(const char *s) { void json_end(json_pull *p) { json_free(p->root); - free(p->buffer); - free(p); + delete p; } static inline int read_wrap(json_pull *j) { @@ -101,20 +96,14 @@ static inline int read_wrap(json_pull *j) { return c; } -#define SIZE_FOR(i, size) ((size_t)((((i) + 31) & ~31) * size)) - static json_object *fabricate_object(json_pull *jp, json_object *parent, json_type type) { - json_object *o = malloc(sizeof(struct json_object)); + json_object *o = new json_object; if (o == NULL) { perror("Out of memory"); exit(EXIT_FAILURE); } o->type = type; o->parent = parent; - o->array = NULL; - o->keys = NULL; - o->values = NULL; - o->length = 0; o->parser = jp; return o; } @@ -126,56 +115,30 @@ static json_object *add_object(json_pull *j, json_type type) { if (c != NULL) { if (c->type == JSON_ARRAY) { if (c->expect == JSON_ITEM) { - if (SIZE_FOR(c->length + 1, sizeof(json_object *)) != SIZE_FOR(c->length, sizeof(json_object *))) { - if (SIZE_FOR(c->length + 1, sizeof(json_object *)) < SIZE_FOR(c->length, sizeof(json_object *))) { - fprintf(stderr, "Array size overflow\n"); - exit(EXIT_FAILURE); - } - c->array = realloc(c->array, SIZE_FOR(c->length + 1, sizeof(json_object *))); - if (c->array == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } - } - - c->array[c->length++] = o; + c->array.push_back(o); c->expect = JSON_COMMA; } else { j->error = "Expected a comma, not a list item"; - free(o); + delete o; return NULL; } } else if (c->type == JSON_HASH) { if (c->expect == JSON_VALUE) { - c->values[c->length - 1] = o; + c->values[c->values.size() - 1] = o; c->expect = JSON_COMMA; } else if (c->expect == JSON_KEY) { if (type != JSON_STRING) { j->error = "Hash key is not a string"; - free(o); + delete o; return NULL; } - if (SIZE_FOR(c->length + 1, sizeof(json_object *)) != SIZE_FOR(c->length, sizeof(json_object *))) { - if (SIZE_FOR(c->length + 1, sizeof(json_object *)) < SIZE_FOR(c->length, sizeof(json_object *))) { - fprintf(stderr, "Hash size overflow\n"); - exit(EXIT_FAILURE); - } - c->keys = realloc(c->keys, SIZE_FOR(c->length + 1, sizeof(json_object *))); - c->values = realloc(c->values, SIZE_FOR(c->length + 1, sizeof(json_object *))); - if (c->keys == NULL || c->values == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } - } - - c->keys[c->length] = o; - c->values[c->length] = NULL; - c->length++; + c->keys.push_back(o); + c->values.push_back(NULL); c->expect = JSON_COLON; } else { j->error = "Expected a comma or colon"; - free(o); + delete o; return NULL; } } @@ -190,15 +153,15 @@ static json_object *add_object(json_pull *j, json_type type) { return o; } -json_object *json_hash_get(json_object *o, const char *s) { +json_object *json_hash_get(json_object *o, std::string const &s) { if (o == NULL || o->type != JSON_HASH) { return NULL; } size_t i; - for (i = 0; i < o->length; i++) { + for (i = 0; i < o->keys.size(); i++) { if (o->keys[i] != NULL && o->keys[i]->type == JSON_STRING) { - if (strcmp(o->keys[i]->string, s) == 0) { + if (o->keys[i]->string == s) { return o->values[i]; } } @@ -207,70 +170,6 @@ json_object *json_hash_get(json_object *o, const char *s) { return NULL; } -struct string { - char *buf; - size_t n; - size_t nalloc; -}; - -static void string_init(struct string *s) { - s->nalloc = 500; - s->buf = malloc(s->nalloc); - if (s->buf == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } - s->n = 0; - s->buf[0] = '\0'; -} - -static void string_append(struct string *s, char c) { - if (s->n + 2 >= s->nalloc) { - size_t prev = s->nalloc; - s->nalloc += 500; - if (s->nalloc <= prev) { - fprintf(stderr, "String size overflowed\n"); - exit(EXIT_FAILURE); - } - s->buf = realloc(s->buf, s->nalloc); - if (s->buf == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } - } - - s->buf[s->n++] = c; - s->buf[s->n] = '\0'; -} - -static void string_append_string(struct string *s, char *add) { - size_t len = strlen(add); - - if (s->n + len + 1 >= s->nalloc) { - size_t prev = s->nalloc; - s->nalloc += 500 + len; - if (s->nalloc <= prev) { - fprintf(stderr, "String size overflowed\n"); - exit(EXIT_FAILURE); - } - s->buf = realloc(s->buf, s->nalloc); - if (s->buf == NULL) { - perror("Out of memory"); - exit(EXIT_FAILURE); - } - } - - for (; *add != '\0'; add++) { - s->buf[s->n++] = *add; - } - - s->buf[s->n] = '\0'; -} - -static void string_free(struct string *s) { - free(s->buf); -} - json_object *json_read_separators(json_pull *j, json_separator_callback cb, void *state) { int c; @@ -340,7 +239,7 @@ again: } if (j->container->expect != JSON_COMMA) { - if (!(j->container->expect == JSON_ITEM && j->container->length == 0)) { + if (!(j->container->expect == JSON_ITEM && j->container->array.size() == 0)) { j->error = "Found ] without final element"; return NULL; } @@ -378,7 +277,7 @@ again: } if (j->container->expect != JSON_COMMA) { - if (!(j->container->expect == JSON_KEY && j->container->length == 0)) { + if (!(j->container->expect == JSON_KEY && j->container->keys.size() == 0)) { j->error = "Found } without final element"; return NULL; } @@ -496,69 +395,63 @@ again: /////////////////////////// Numbers if (c == '-' || (c >= '0' && c <= '9')) { - struct string val; - string_init(&val); + std::string val; if (c == '-') { - string_append(&val, c); + val.push_back(c); c = read_wrap(j); } if (c == '0') { - string_append(&val, c); + val.push_back(c); } else if (c >= '1' && c <= '9') { - string_append(&val, c); + val.push_back(c); c = peek(j); while (c >= '0' && c <= '9') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); c = peek(j); } } if (peek(j) == '.') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); c = peek(j); if (c < '0' || c > '9') { j->error = "Decimal point without digits"; - string_free(&val); return NULL; } while (c >= '0' && c <= '9') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); c = peek(j); } } c = peek(j); if (c == 'e' || c == 'E') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); c = peek(j); if (c == '+' || c == '-') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); } c = peek(j); if (c < '0' || c > '9') { j->error = "Exponent without digits"; - string_free(&val); return NULL; } while (c >= '0' && c <= '9') { - string_append(&val, read_wrap(j)); + val.push_back(read_wrap(j)); c = peek(j); } } json_object *n = add_object(j, JSON_NUMBER); if (n != NULL) { - n->number = atof(val.buf); - n->string = val.buf; - n->length = val.n; - } else { - string_free(&val); + n->number = atof(val.c_str()); + n->string = val; } return n; } @@ -566,16 +459,15 @@ again: /////////////////////////// Strings if (c == '"') { - struct string val; - string_init(&val); + std::string val; int surrogate = -1; while ((c = read_wrap(j)) != EOF) { if (c == '"') { if (surrogate >= 0) { - string_append(&val, 0xE0 | (surrogate >> 12)); - string_append(&val, 0x80 | ((surrogate >> 6) & 0x3F)); - string_append(&val, 0x80 | (surrogate & 0x3F)); + val.push_back(0xE0 | (surrogate >> 12)); + val.push_back(0x80 | ((surrogate >> 6) & 0x3F)); + val.push_back(0x80 | (surrogate & 0x3F)); surrogate = -1; } @@ -590,7 +482,6 @@ again: hex[i] = read_wrap(j); if (hex[i] < '0' || (hex[i] > '9' && hex[i] < 'A') || (hex[i] > 'F' && hex[i] < 'a') || hex[i] > 'f') { j->error = "Invalid \\u hex character"; - string_free(&val); return NULL; } } @@ -602,9 +493,9 @@ again: } else { // Impossible surrogate, so output the first half, // keep what might be a legitimate new first half. - string_append(&val, 0xE0 | (surrogate >> 12)); - string_append(&val, 0x80 | ((surrogate >> 6) & 0x3F)); - string_append(&val, 0x80 | (surrogate & 0x3F)); + val.push_back(0xE0 | (surrogate >> 12)); + val.push_back(0x80 | ((surrogate >> 6) & 0x3F)); + val.push_back(0x80 | (surrogate & 0x3F)); surrogate = ch; } continue; @@ -618,84 +509,78 @@ again: } if (surrogate >= 0) { - string_append(&val, 0xE0 | (surrogate >> 12)); - string_append(&val, 0x80 | ((surrogate >> 6) & 0x3F)); - string_append(&val, 0x80 | (surrogate & 0x3F)); + val.push_back(0xE0 | (surrogate >> 12)); + val.push_back(0x80 | ((surrogate >> 6) & 0x3F)); + val.push_back(0x80 | (surrogate & 0x3F)); surrogate = -1; } if (ch <= 0x7F) { - string_append(&val, ch); + val.push_back(ch); } else if (ch <= 0x7FF) { - string_append(&val, 0xC0 | (ch >> 6)); - string_append(&val, 0x80 | (ch & 0x3F)); + val.push_back(0xC0 | (ch >> 6)); + val.push_back(0x80 | (ch & 0x3F)); } else if (ch < 0xFFFF) { - string_append(&val, 0xE0 | (ch >> 12)); - string_append(&val, 0x80 | ((ch >> 6) & 0x3F)); - string_append(&val, 0x80 | (ch & 0x3F)); + val.push_back(0xE0 | (ch >> 12)); + val.push_back(0x80 | ((ch >> 6) & 0x3F)); + val.push_back(0x80 | (ch & 0x3F)); } else { - string_append(&val, 0xF0 | (ch >> 18)); - string_append(&val, 0x80 | ((ch >> 12) & 0x3F)); - string_append(&val, 0x80 | ((ch >> 6) & 0x3F)); - string_append(&val, 0x80 | (ch & 0x3F)); + val.push_back(0xF0 | (ch >> 18)); + val.push_back(0x80 | ((ch >> 12) & 0x3F)); + val.push_back(0x80 | ((ch >> 6) & 0x3F)); + val.push_back(0x80 | (ch & 0x3F)); } } else { if (surrogate >= 0) { - string_append(&val, 0xE0 | (surrogate >> 12)); - string_append(&val, 0x80 | ((surrogate >> 6) & 0x3F)); - string_append(&val, 0x80 | (surrogate & 0x3F)); + val.push_back(0xE0 | (surrogate >> 12)); + val.push_back(0x80 | ((surrogate >> 6) & 0x3F)); + val.push_back(0x80 | (surrogate & 0x3F)); surrogate = -1; } if (c == '"') { - string_append(&val, '"'); + val.push_back('"'); } else if (c == '\\') { - string_append(&val, '\\'); + val.push_back('\\'); } else if (c == '/') { - string_append(&val, '/'); + val.push_back('/'); } else if (c == 'b') { - string_append(&val, '\b'); + val.push_back('\b'); } else if (c == 'f') { - string_append(&val, '\f'); + val.push_back('\f'); } else if (c == 'n') { - string_append(&val, '\n'); + val.push_back('\n'); } else if (c == 'r') { - string_append(&val, '\r'); + val.push_back('\r'); } else if (c == 't') { - string_append(&val, '\t'); + val.push_back('\t'); } else { j->error = "Found backslash followed by unknown character"; - string_free(&val); return NULL; } } } else if (c < ' ') { j->error = "Found control character in string"; - string_free(&val); return NULL; } else { if (surrogate >= 0) { - string_append(&val, 0xE0 | (surrogate >> 12)); - string_append(&val, 0x80 | ((surrogate >> 6) & 0x3F)); - string_append(&val, 0x80 | (surrogate & 0x3F)); + val.push_back(0xE0 | (surrogate >> 12)); + val.push_back(0x80 | ((surrogate >> 6) & 0x3F)); + val.push_back(0x80 | (surrogate & 0x3F)); surrogate = -1; } - string_append(&val, c); + val.push_back(c); } } if (c == EOF) { j->error = "String without closing quote mark"; - string_free(&val); return NULL; } json_object *s = add_object(j, JSON_STRING); if (s != NULL) { - s->string = val.buf; - s->length = val.n; - } else { - string_free(&val); + s->string = val; } return s; } @@ -730,52 +615,43 @@ void json_free(json_object *o) { // Free any data linked from here if (o->type == JSON_ARRAY) { - json_object **a = o->array; - size_t n = o->length; + std::vector a = o->array; + size_t n = o->array.size(); - o->array = NULL; - o->length = 0; + o->array.resize(0); for (i = 0; i < n; i++) { json_free(a[i]); } - - free(a); } else if (o->type == JSON_HASH) { - json_object **k = o->keys; - json_object **v = o->values; - size_t n = o->length; + std::vector k = o->keys; + std::vector v = o->values; + size_t n = o->keys.size(); - o->keys = NULL; - o->values = NULL; - o->length = 0; + o->keys.resize(0); + o->values.resize(0); for (i = 0; i < n; i++) { json_free(k[i]); json_free(v[i]); } - - free(k); - free(v); - } else if (o->type == JSON_STRING || o->type == JSON_NUMBER) { - free(o->string); } json_disconnect(o); - free(o); + delete o; } static void json_disconnect_parser(json_object *o) { if (o->type == JSON_HASH) { size_t i; - for (i = 0; i < o->length; i++) { + for (i = 0; i < o->keys.size(); i++) { json_disconnect_parser(o->keys[i]); json_disconnect_parser(o->values[i]); } } else if (o->type == JSON_ARRAY) { size_t i; - for (i = 0; i < o->length; i++) { + for (i = 0; i < o->array.size(); i++) { json_disconnect_parser(o->array[i]); } } @@ -791,22 +667,21 @@ void json_disconnect(json_object *o) { if (o->parent->type == JSON_ARRAY) { size_t i; - for (i = 0; i < o->parent->length; i++) { + for (i = 0; i < o->parent->array.size(); i++) { if (o->parent->array[i] == o) { break; } } - if (i < o->parent->length) { - memmove(o->parent->array + i, o->parent->array + i + 1, o->parent->length - i - 1); - o->parent->length--; + if (i < o->parent->array.size()) { + o->parent->array.erase(o->parent->array.begin() + i); } } if (o->parent->type == JSON_HASH) { size_t i; - for (i = 0; i < o->parent->length; i++) { + for (i = 0; i < o->parent->keys.size(); i++) { if (o->parent->keys[i] == o) { o->parent->keys[i] = fabricate_object(o->parser, o->parent, JSON_NULL); break; @@ -817,15 +692,14 @@ void json_disconnect(json_object *o) { } } - if (i < o->parent->length) { + if (i < o->parent->keys.size()) { if (o->parent->keys[i] != NULL && o->parent->keys[i]->type == JSON_NULL) { if (o->parent->values[i] != NULL && o->parent->values[i]->type == JSON_NULL) { - free(o->parent->keys[i]); - free(o->parent->values[i]); + delete o->parent->keys[i]; + delete o->parent->values[i]; - memmove(o->parent->keys + i, o->parent->keys + i + 1, o->parent->length - i - 1); - memmove(o->parent->values + i, o->parent->values + i + 1, o->parent->length - i - 1); - o->parent->length--; + o->parent->keys.erase(o->parent->keys.begin() + i); + o->parent->values.erase(o->parent->values.begin() + i); } } } @@ -840,80 +714,78 @@ void json_disconnect(json_object *o) { o->parent = NULL; } -static void json_print_one(struct string *val, json_object *o) { +static void json_print_one(std::string &val, json_object *o) { if (o == NULL) { - string_append_string(val, "..."); + val.append("..."); } else if (o->type == JSON_STRING) { - string_append(val, '\"'); + val.push_back('\"'); - char *cp; - for (cp = o->string; *cp != '\0'; cp++) { + const char *cp; + for (cp = o->string.c_str(); *cp != '\0'; cp++) { if (*cp == '\\' || *cp == '"') { - string_append(val, '\\'); - string_append(val, *cp); + val.push_back('\\'); + val.push_back(*cp); } else if (*cp >= 0 && *cp < ' ') { char *s; if (asprintf(&s, "\\u%04x", *cp) >= 0) { - string_append_string(val, s); + val.append(s); free(s); } } else { - string_append(val, *cp); + val.push_back(*cp); } } - string_append(val, '\"'); + val.push_back('\"'); } else if (o->type == JSON_NUMBER) { - string_append_string(val, o->string); + val.append(o->string); } else if (o->type == JSON_NULL) { - string_append_string(val, "null"); + val.append("null"); } else if (o->type == JSON_TRUE) { - string_append_string(val, "true"); + val.append("true"); } else if (o->type == JSON_FALSE) { - string_append_string(val, "false"); + val.append("false"); } else if (o->type == JSON_HASH) { - string_append(val, '}'); + val.push_back('}'); } else if (o->type == JSON_ARRAY) { - string_append(val, ']'); + val.push_back(']'); } } -static void json_print(struct string *val, json_object *o) { +static void json_print(std::string &val, json_object *o) { if (o == NULL) { // Hash value in incompletely read hash - string_append_string(val, "..."); + val.append("..."); } else if (o->type == JSON_HASH) { - string_append(val, '{'); + val.push_back('{'); size_t i; - for (i = 0; i < o->length; i++) { + for (i = 0; i < o->keys.size(); i++) { json_print(val, o->keys[i]); - string_append(val, ':'); + val.push_back(':'); json_print(val, o->values[i]); - if (i + 1 < o->length) { - string_append(val, ','); + if (i + 1 < o->keys.size()) { + val.push_back(','); } } - string_append(val, '}'); + val.push_back('}'); } else if (o->type == JSON_ARRAY) { - string_append(val, '['); + val.push_back('['); size_t i; - for (i = 0; i < o->length; i++) { + for (i = 0; i < o->array.size(); i++) { json_print(val, o->array[i]); - if (i + 1 < o->length) { - string_append(val, ','); + if (i + 1 < o->array.size()) { + val.push_back(','); } } - string_append(val, ']'); + val.push_back(']'); } else { json_print_one(val, o); } } -char *json_stringify(json_object *o) { - struct string val; - string_init(&val); - json_print(&val, o); - - return val.buf; +std::string json_stringify(json_object *o) { + std::string val; + json_print(val, o); + return val; } diff --git a/jsonpull/jsonpull.h b/jsonpull/jsonpull.hpp similarity index 75% rename from jsonpull/jsonpull.h rename to jsonpull/jsonpull.hpp index 1983a35..a6635ff 100644 --- a/jsonpull/jsonpull.h +++ b/jsonpull/jsonpull.hpp @@ -1,9 +1,8 @@ -#ifndef JSONPULL_H -#define JSONPULL_H +#ifndef JSONPULL_HPP +#define JSONPULL_HPP -#ifdef __cplusplus -extern "C" { -#endif +#include +#include typedef enum json_type { // These types can be returned by json_read() @@ -25,29 +24,30 @@ typedef enum json_type { JSON_VALUE, } json_type; -typedef struct json_object { +struct json_object; + +struct json_object { json_type type; struct json_object *parent; struct json_pull *parser; - char *string; + std::string string; double number; - struct json_object **array; - struct json_object **keys; - struct json_object **values; - size_t length; + std::vector array; + std::vector keys; + std::vector values; int expect; -} json_object; +}; typedef struct json_pull { - char *error; - int line; + std::string error; + size_t line; ssize_t (*read)(struct json_pull *, char *buf, size_t n); void *source; - char *buffer; + std::string buffer; ssize_t buffer_tail; ssize_t buffer_head; @@ -69,12 +69,8 @@ json_object *json_read_separators(json_pull *j, json_separator_callback cb, void void json_free(json_object *j); void json_disconnect(json_object *j); -json_object *json_hash_get(json_object *o, const char *s); +json_object *json_hash_get(json_object *o, std::string const &key); -char *json_stringify(json_object *o); - -#ifdef __cplusplus -} -#endif +std::string json_stringify(json_object *o); #endif diff --git a/jsontool.cpp b/jsontool.cpp index 0ab6e89..208cf1a 100644 --- a/jsontool.cpp +++ b/jsontool.cpp @@ -7,7 +7,7 @@ #include #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "csv.hpp" #include "text.hpp" @@ -145,14 +145,13 @@ void out(std::string const &s, int type, json_object *properties) { if (o != NULL) { found = true; if (o->type == JSON_STRING || o->type == JSON_NUMBER) { - extracted = sort_quote(o->string); + extracted = sort_quote(o->string.c_str()); } else { // Don't really know what to do about sort quoting // for arbitrary objects - const char *out = json_stringify(o); - extracted = sort_quote(out); - free((void *) out); + std::string out = json_stringify(o); + extracted = sort_quote(out.c_str()); } } @@ -247,9 +246,8 @@ void join_csv(json_object *j) { if (key->type == JSON_STRING || key->type == JSON_NUMBER) { joinkey = key->string; } else { - const char *s = json_stringify(key); + std::string s = json_stringify(key); joinkey = s; - free((void *) s); } if (joinkey < prev_joinkey) { @@ -300,12 +298,6 @@ void join_csv(json_object *j) { if (fields.size() > 0 && joinkey == fields[0]) { // This knows more about the structure of JSON objects than it ought to - properties->keys = (json_object **) realloc((void *) properties->keys, (properties->length + 32 + fields.size()) * sizeof(json_object *)); - properties->values = (json_object **) realloc((void *) properties->values, (properties->length + 32 + fields.size()) * sizeof(json_object *)); - if (properties->keys == NULL || properties->values == NULL) { - perror("realloc"); - exit(EXIT_FAILURE); - } for (size_t i = 1; i < fields.size(); i++) { std::string k = header[i]; @@ -323,8 +315,8 @@ void join_csv(json_object *j) { { // This knows more about the structure of JSON objects than it ought to - json_object *ko = (json_object *) malloc(sizeof(json_object)); - json_object *vo = (json_object *) malloc(sizeof(json_object)); + json_object *ko = new json_object; + json_object *vo = new json_object; if (ko == NULL || vo == NULL) { perror("malloc"); exit(EXIT_FAILURE); @@ -334,26 +326,14 @@ void join_csv(json_object *j) { vo->type = attr_type; ko->parent = vo->parent = properties; - ko->array = vo->array = NULL; - ko->keys = vo->keys = NULL; - ko->values = vo->values = NULL; ko->parser = vo->parser = properties->parser; - ko->string = strdup(k.c_str()); - vo->string = strdup(v.c_str()); + ko->string = k; + vo->string = v; + vo->number = atof(vo->string.c_str()); - if (ko->string == NULL || vo->string == NULL) { - perror("strdup"); - exit(EXIT_FAILURE); - } - - ko->length = strlen(ko->string); - vo->length = strlen(vo->string); - vo->number = atof(vo->string); - - properties->keys[properties->length] = ko; - properties->values[properties->length] = vo; - properties->length++; + properties->keys.push_back(ko); + properties->values.push_back(vo); } } } @@ -365,8 +345,8 @@ void process(FILE *fp, const char *fname) { while (1) { json_object *j = json_read(jp); if (j == NULL) { - if (jp->error != NULL) { - fprintf(stderr, "%s:%d: %s\n", fname, jp->line, jp->error); + if (jp->error.size() != 0) { + fprintf(stderr, "%s:%zu: %s\n", fname, jp->line, jp->error.c_str()); } json_free(jp->root); @@ -378,20 +358,19 @@ void process(FILE *fp, const char *fname) { continue; } - if (strcmp(type->string, "Feature") == 0) { + if (type->string == "Feature") { if (csvfile != NULL) { join_csv(j); } - char *s = json_stringify(j); - out(s, 1, json_hash_get(j, "properties")); - free(s); + std::string s = json_stringify(j); + out(s.c_str(), 1, json_hash_get(j, "properties")); json_free(j); - } else if (strcmp(type->string, "Point") == 0 || - strcmp(type->string, "MultiPoint") == 0 || - strcmp(type->string, "LineString") == 0 || - strcmp(type->string, "MultiLineString") == 0 || - strcmp(type->string, "MultiPolygon") == 0) { + } else if (type->string == "Point" || + type->string == "MultiPoint" || + type->string == "LineString" || + type->string == "MultiLineString" || + type->string == "MultiPolygon") { int is_geometry = 1; if (j->parent != NULL) { @@ -413,12 +392,11 @@ void process(FILE *fp, const char *fname) { } if (is_geometry) { - char *s = json_stringify(j); - out(s, 2, NULL); - free(s); + std::string s = json_stringify(j); + out(s.c_str(), 2, NULL); json_free(j); } - } else if (strcmp(type->string, "FeatureCollection") == 0) { + } else if (type->string == "FeatureCollection") { json_free(j); } } diff --git a/main.cpp b/main.cpp index 1dbe289..21d2f7a 100644 --- a/main.cpp +++ b/main.cpp @@ -43,7 +43,7 @@ #include #endif -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "mbtiles.hpp" #include "tile.hpp" #include "pool.hpp" @@ -2379,7 +2379,7 @@ void parse_json_source(const char *arg, struct source &src) { json_object *o = json_read_tree(jp); if (o == NULL) { - fprintf(stderr, "%s: -L%s: %s\n", *av, arg, jp->error); + fprintf(stderr, "%s: -L%s: %s\n", *av, arg, jp->error.c_str()); exit(EXIT_FAILURE); } diff --git a/plugin.cpp b/plugin.cpp index b1f5413..a30f6c3 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -26,7 +26,7 @@ #include "serial.hpp" extern "C" { -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" } #include "plugin.hpp" @@ -97,8 +97,8 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: while (1) { json_object *j = json_read(jp); if (j == NULL) { - if (jp->error != NULL) { - fprintf(stderr, "Filter output:%d: %s\n", jp->line, jp->error); + if (jp->error.size() != 0) { + fprintf(stderr, "Filter output:%zu: %s\n", jp->line, jp->error.c_str()); if (jp->root != NULL) { json_context(jp->root); } @@ -113,13 +113,13 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: if (type == NULL || type->type != JSON_STRING) { continue; } - if (strcmp(type->string, "Feature") != 0) { + if (type->string != std::string("Feature")) { continue; } json_object *geometry = json_hash_get(j, "geometry"); if (geometry == NULL) { - fprintf(stderr, "Filter output:%d: filtered feature with no geometry\n", jp->line); + fprintf(stderr, "Filter output:%zu: filtered feature with no geometry\n", jp->line); json_context(j); json_free(j); exit(EXIT_FAILURE); @@ -127,7 +127,7 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: json_object *properties = json_hash_get(j, "properties"); if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) { - fprintf(stderr, "Filter output:%d: feature without properties hash\n", jp->line); + fprintf(stderr, "Filter output:%zu: feature without properties hash\n", jp->line); json_context(j); json_free(j); exit(EXIT_FAILURE); @@ -135,32 +135,32 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: json_object *geometry_type = json_hash_get(geometry, "type"); if (geometry_type == NULL) { - fprintf(stderr, "Filter output:%d: null geometry (additional not reported)\n", jp->line); + fprintf(stderr, "Filter output:%zu: null geometry (additional not reported)\n", jp->line); json_context(j); exit(EXIT_FAILURE); } if (geometry_type->type != JSON_STRING) { - fprintf(stderr, "Filter output:%d: geometry type is not a string\n", jp->line); + fprintf(stderr, "Filter output:%zu: geometry type is not a string\n", jp->line); json_context(j); exit(EXIT_FAILURE); } json_object *coordinates = json_hash_get(geometry, "coordinates"); if (coordinates == NULL || coordinates->type != JSON_ARRAY) { - fprintf(stderr, "Filter output:%d: feature without coordinates array\n", jp->line); + fprintf(stderr, "Filter output:%zu: feature without coordinates array\n", jp->line); json_context(j); exit(EXIT_FAILURE); } int t; for (t = 0; t < GEOM_TYPES; t++) { - if (strcmp(geometry_type->string, geometry_names[t]) == 0) { + if (geometry_type->string == std::string(geometry_names[t])) { break; } } if (t >= GEOM_TYPES) { - fprintf(stderr, "Filter output:%d: Can't handle geometry type %s\n", jp->line, geometry_type->string); + fprintf(stderr, "Filter output:%zu: Can't handle geometry type %s\n", jp->line, geometry_type->string.c_str()); json_context(j); exit(EXIT_FAILURE); } @@ -216,7 +216,7 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: json_object *id = json_hash_get(j, "id"); if (id != NULL) { - feature.id = atoll(id->string); + feature.id = atoll(id->string.c_str()); feature.has_id = true; } @@ -254,7 +254,7 @@ std::vector parse_layers(int fd, int z, unsigned x, unsigned y, std:: fk->second.polygons++; } - for (size_t i = 0; i < properties->length; i++) { + for (size_t i = 0; i < properties->keys.size(); i++) { int tp = -1; std::string s; @@ -301,8 +301,8 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: while (1) { json_object *j = json_read(jp); if (j == NULL) { - if (jp->error != NULL) { - fprintf(stderr, "Filter output:%d: %s\n", jp->line, jp->error); + if (jp->error.size() != 0) { + fprintf(stderr, "Filter output:%zu: %s\n", jp->line, jp->error.c_str()); if (jp->root != NULL) { json_context(jp->root); } @@ -318,13 +318,13 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: if (type == NULL || type->type != JSON_STRING) { continue; } - if (strcmp(type->string, "Feature") != 0) { + if (type->string != std::string("Feature")) { continue; } json_object *geometry = json_hash_get(j, "geometry"); if (geometry == NULL) { - fprintf(stderr, "Filter output:%d: filtered feature with no geometry\n", jp->line); + fprintf(stderr, "Filter output:%zu: filtered feature with no geometry\n", jp->line); json_context(j); json_free(j); exit(EXIT_FAILURE); @@ -332,7 +332,7 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: json_object *properties = json_hash_get(j, "properties"); if (properties == NULL || (properties->type != JSON_HASH && properties->type != JSON_NULL)) { - fprintf(stderr, "Filter output:%d: feature without properties hash\n", jp->line); + fprintf(stderr, "Filter output:%zu: feature without properties hash\n", jp->line); json_context(j); json_free(j); exit(EXIT_FAILURE); @@ -340,32 +340,32 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: json_object *geometry_type = json_hash_get(geometry, "type"); if (geometry_type == NULL) { - fprintf(stderr, "Filter output:%d: null geometry (additional not reported)\n", jp->line); + fprintf(stderr, "Filter output:%zu: null geometry (additional not reported)\n", jp->line); json_context(j); exit(EXIT_FAILURE); } if (geometry_type->type != JSON_STRING) { - fprintf(stderr, "Filter output:%d: geometry type is not a string\n", jp->line); + fprintf(stderr, "Filter output:%zu: geometry type is not a string\n", jp->line); json_context(j); exit(EXIT_FAILURE); } json_object *coordinates = json_hash_get(geometry, "coordinates"); if (coordinates == NULL || coordinates->type != JSON_ARRAY) { - fprintf(stderr, "Filter output:%d: feature without coordinates array\n", jp->line); + fprintf(stderr, "Filter output:%zu: feature without coordinates array\n", jp->line); json_context(j); exit(EXIT_FAILURE); } int t; for (t = 0; t < GEOM_TYPES; t++) { - if (strcmp(geometry_type->string, geometry_names[t]) == 0) { + if (geometry_type->string == std::string(geometry_names[t])) { break; } } if (t >= GEOM_TYPES) { - fprintf(stderr, "Filter output:%d: Can't handle geometry type %s\n", jp->line, geometry_type->string); + fprintf(stderr, "Filter output:%zu: Can't handle geometry type %s\n", jp->line, geometry_type->string.c_str()); json_context(j); exit(EXIT_FAILURE); } @@ -448,7 +448,7 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: json_object *id = json_hash_get(j, "id"); if (id != NULL) { - sf.id = atoll(id->string); + sf.id = atoll(id->string.c_str()); sf.has_id = true; } @@ -491,7 +491,7 @@ serial_feature parse_feature(json_pull *jp, int z, unsigned x, unsigned y, std:: } } - for (size_t i = 0; i < properties->length; i++) { + for (size_t i = 0; i < properties->keys.size(); i++) { serial_val v; v.type = -1; diff --git a/read_json.cpp b/read_json.cpp index cdb2211..b943487 100644 --- a/read_json.cpp +++ b/read_json.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "geometry.hpp" #include "projection.hpp" #include "read_json.hpp" @@ -31,14 +31,14 @@ int mb_geometry[GEOM_TYPES] = { }; void json_context(json_object *j) { - char *s = json_stringify(j); + std::string s = json_stringify(j); - if (strlen(s) >= 500) { - sprintf(s + 497, "..."); + if (s.size() >= 500) { + s.resize(497); + s.append("..."); } - fprintf(stderr, "In JSON object %s\n", s); - free(s); // stringify + fprintf(stderr, "In JSON object %s\n", s.c_str()); } void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fname, int line, json_object *feature) { @@ -51,7 +51,7 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna int within = geometry_within[t]; if (within >= 0) { size_t i; - for (i = 0; i < j->length; i++) { + for (i = 0; i < j->array.size(); i++) { if (within == GEOM_POINT) { if (i == 0 || mb_geometry[t] == GEOM_MULTIPOINT) { op = VT_MOVETO; @@ -63,13 +63,13 @@ void parse_geometry(int t, json_object *j, drawvec &out, int op, const char *fna parse_geometry(within, j->array[i], out, op, fname, line, feature); } } else { - if (j->length >= 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { + if (j->array.size() >= 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { long long x, y; double lon = j->array[0]->number; double lat = j->array[1]->number; projection->project(lon, lat, 32, &x, &y); - if (j->length > 2) { + if (j->array.size() > 2) { static int warned = 0; if (!warned) { @@ -109,21 +109,20 @@ void canonicalize(json_object *o) { long long v; unsigned long long uv; - if (is_integer(o->string, &v)) { + if (is_integer(o->string.c_str(), &v)) { s = std::to_string(v); - } else if (is_unsigned_integer(o->string, &uv)) { + } else if (is_unsigned_integer(o->string.c_str(), &uv)) { s = std::to_string(uv); } else { s = milo::dtoa_milo(o->number); } - free(o->string); - o->string = strdup(s.c_str()); + o->string = s; } else if (o->type == JSON_HASH) { - for (size_t i = 0; i < o->length; i++) { + for (size_t i = 0; i < o->keys.size(); i++) { canonicalize(o->values[i]); } } else if (o->type == JSON_ARRAY) { - for (size_t i = 0; i < o->length; i++) { + for (size_t i = 0; i < o->array.size(); i++) { canonicalize(o->array[i]); } } @@ -144,9 +143,7 @@ void stringify_value(json_object *value, int &type, std::string &stringified, co val = "null"; } else { canonicalize(value); - const char *v = json_stringify(value); - val = std::string(v); - free((void *) v); // stringify + val = json_stringify(value); } if (vt == JSON_STRING) { @@ -164,9 +161,9 @@ void stringify_value(json_object *value, int &type, std::string &stringified, co long long v; unsigned long long uv; - if (is_integer(value->string, &v)) { + if (is_integer(value->string.c_str(), &v)) { stringified = std::to_string(v); - } else if (is_unsigned_integer(value->string, &uv)) { + } else if (is_unsigned_integer(value->string.c_str(), &uv)) { stringified = std::to_string(uv); } else { stringified = milo::dtoa_milo(value->number); diff --git a/serial.hpp b/serial.hpp index e52a6a8..3b54ee1 100644 --- a/serial.hpp +++ b/serial.hpp @@ -9,7 +9,7 @@ #include #include "geometry.hpp" #include "mbtiles.hpp" -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" size_t fwrite_check(const void *ptr, size_t size, size_t nitems, FILE *stream, const char *fname); diff --git a/tile-join.cpp b/tile-join.cpp index ee9269c..526855f 100644 --- a/tile-join.cpp +++ b/tile-join.cpp @@ -33,7 +33,7 @@ #include #include #include -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" #include "milo/dtoa_milo.h" int pk = false; @@ -575,7 +575,7 @@ void handle_tasks(std::map> &tasks, std::vector &layermap, std::map &attribute_descriptions) { if (vector_layers != NULL && vector_layers->type == JSON_ARRAY) { - for (size_t i = 0; i < vector_layers->length; i++) { + for (size_t i = 0; i < vector_layers->array.size(); i++) { if (vector_layers->array[i]->type == JSON_HASH) { json_object *id = json_hash_get(vector_layers->array[i], "id"); json_object *desc = json_hash_get(vector_layers->array[i], "description"); @@ -594,14 +594,14 @@ void handle_vector_layers(json_object *vector_layers, std::maparray[i], "fields"); if (fields != NULL && fields->type == JSON_HASH) { - for (size_t j = 0; j < fields->length; j++) { + for (size_t j = 0; j < fields->keys.size(); j++) { if (fields->keys[j]->type == JSON_STRING && fields->values[j]->type) { - const char *desc2 = fields->values[j]->string; + std::string desc2 = fields->values[j]->string; - if (strcmp(desc2, "Number") != 0 && - strcmp(desc2, "String") != 0 && - strcmp(desc2, "Boolean") != 0 && - strcmp(desc2, "Mixed") != 0) { + if (desc2 != "Number" && + desc2 != "String" && + desc2 != "Boolean" && + desc2 != "Mixed") { attribute_descriptions.insert(std::pair(fields->keys[j]->string, desc2)); } } diff --git a/tile.cpp b/tile.cpp index 1ef626d..5f63c81 100644 --- a/tile.cpp +++ b/tile.cpp @@ -41,7 +41,7 @@ #include "evaluator.hpp" extern "C" { -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" } #include "plugin.hpp" diff --git a/tile.hpp b/tile.hpp index 32fb227..f5315c4 100644 --- a/tile.hpp +++ b/tile.hpp @@ -7,7 +7,7 @@ #include #include #include "mbtiles.hpp" -#include "jsonpull/jsonpull.h" +#include "jsonpull/jsonpull.hpp" enum attribute_op { op_sum,