mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 16:35:40 +02:00
Migrate jsonpull to unique_ptr ownership
Replaces the shared_ptr-based json_object_ptr with a unique_ptr that has a stateless custom deleter dispatching on json_object::type before calling the right subclass destructor. Eliminates per-node atomic reference-counting and the control-block allocation that shared_ptr required for every node in the tree. API now distinguishes owning and borrowing pointers explicitly: - json_read / json_read_separators / json_hash_get return raw json_object * (borrowed from the parser-owned tree). - json_read_tree / json_disconnect return json_object_ptr (caller takes ownership; back-pointers are cleared so the subtree can outlive the parser). - json_free / json_context / json_stringify take raw pointers. - The parser's container_stack holds raw pointers; jp->root keeps unique_ptr ownership of the most recent top-level value. Internally, take_from_owner moves the unique_ptr out of whichever parent vector / hash entry / parser root owned it, which both json_free and json_disconnect rely on. In the streaming parsers (parse_feature, parse_layers, the geojson-loop callback), we are careful to free `j` only after we have processed a complete Feature: json_read returns each token as the tree is being built up, and freeing an intermediate node would splice it out of the surrounding hash and corrupt the in-progress feature. Benchmark (tl_2022_us_county.json, -z0 --extend-zooms-if-still-dropping, median of 5 runs on macOS arm64): 8.5s, vs 10.6s with shared_ptr and 8.7s on the pre-refactor C baseline. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+15
-15
@@ -40,8 +40,8 @@
|
||||
#include "milo/dtoa_milo.h"
|
||||
#include "errors.hpp"
|
||||
|
||||
int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr geometry, json_object_ptr properties, json_object_ptr id, int layer, json_object_ptr tippecanoe, json_object_ptr feature, std::string const &layername) {
|
||||
json_object_ptr geometry_type = json_hash_get(geometry, "type");
|
||||
int serialize_geojson_feature(struct serialization_state *sst, json_object *geometry, json_object *properties, json_object *id, int layer, json_object *tippecanoe, json_object *feature, std::string const &layername) {
|
||||
json_object *geometry_type = json_hash_get(geometry, "type");
|
||||
if (geometry_type == nullptr) {
|
||||
static int warned = 0;
|
||||
if (!warned) {
|
||||
@@ -59,7 +59,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr g
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_object_ptr coordinates = json_hash_get(geometry, "coordinates");
|
||||
json_object *coordinates = json_hash_get(geometry, "coordinates");
|
||||
if (coordinates == nullptr || coordinates->type != JSON_ARRAY) {
|
||||
fprintf(stderr, "%s:%d: feature without coordinates array: ", sst->fname, sst->line);
|
||||
json_context(feature);
|
||||
@@ -83,17 +83,17 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr g
|
||||
std::string tippecanoe_layername = layername;
|
||||
|
||||
if (tippecanoe != nullptr) {
|
||||
json_object_ptr min = json_hash_get(tippecanoe, "minzoom");
|
||||
json_object *min = json_hash_get(tippecanoe, "minzoom");
|
||||
if (min != nullptr && (min->type == JSON_NUMBER)) {
|
||||
tippecanoe_minzoom = integer_zoom(sst->fname, milo::dtoa_milo(min->number()));
|
||||
}
|
||||
|
||||
json_object_ptr max = json_hash_get(tippecanoe, "maxzoom");
|
||||
json_object *max = json_hash_get(tippecanoe, "maxzoom");
|
||||
if (max != nullptr && (max->type == JSON_NUMBER)) {
|
||||
tippecanoe_maxzoom = integer_zoom(sst->fname, milo::dtoa_milo(max->number()));
|
||||
}
|
||||
|
||||
json_object_ptr ln = json_hash_get(tippecanoe, "layer");
|
||||
json_object *ln = json_hash_get(tippecanoe, "layer");
|
||||
if (ln != nullptr && (ln->type == JSON_STRING)) {
|
||||
tippecanoe_layername = ln->string();
|
||||
}
|
||||
@@ -186,7 +186,7 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr g
|
||||
|
||||
for (const auto &e : entries) {
|
||||
if (e.key->type == JSON_STRING) {
|
||||
serial_val sv = stringify_value(e.value, sst->fname, sst->line, feature);
|
||||
serial_val sv = stringify_value(e.value.get(), sst->fname, sst->line, feature);
|
||||
|
||||
full_keys.emplace_back(key_pool.pool(e.key->string().c_str()));
|
||||
values.push_back(std::move(sv));
|
||||
@@ -214,12 +214,12 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr g
|
||||
return serialize_feature(sst, sf, tippecanoe_layername);
|
||||
}
|
||||
|
||||
void check_crs(json_object_ptr j, const char *reading) {
|
||||
json_object_ptr crs = json_hash_get(j, "crs");
|
||||
void check_crs(json_object *j, const char *reading) {
|
||||
json_object *crs = json_hash_get(j, "crs");
|
||||
if (crs != nullptr) {
|
||||
json_object_ptr properties = json_hash_get(crs, "properties");
|
||||
json_object *properties = json_hash_get(crs, "properties");
|
||||
if (properties != nullptr) {
|
||||
json_object_ptr name = json_hash_get(properties, "name");
|
||||
json_object *name = json_hash_get(properties, "name");
|
||||
if (name != nullptr && name->type == JSON_STRING) {
|
||||
if (name->string() != projection->alias) {
|
||||
if (!quiet) {
|
||||
@@ -237,12 +237,12 @@ struct json_serialize_action : json_feature_action {
|
||||
int layer;
|
||||
std::string layername;
|
||||
|
||||
int add_feature(json_object_ptr geometry, bool geometrycollection, json_object_ptr properties, json_object_ptr id, json_object_ptr tippecanoe, json_object_ptr feature) {
|
||||
int add_feature(json_object *geometry, bool geometrycollection, json_object *properties, json_object *id, json_object *tippecanoe, json_object *feature) {
|
||||
sst->line = geometry->parser->line;
|
||||
if (geometrycollection) {
|
||||
int ret = 1;
|
||||
for (size_t g = 0; g < geometry->array().size(); g++) {
|
||||
ret &= serialize_geojson_feature(sst, geometry->array()[g], properties, id, layer, tippecanoe, feature, layername);
|
||||
ret &= serialize_geojson_feature(sst, geometry->array()[g].get(), properties, id, layer, tippecanoe, feature, layername);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
@@ -250,12 +250,12 @@ struct json_serialize_action : json_feature_action {
|
||||
}
|
||||
}
|
||||
|
||||
void check_crs(json_object_ptr j) {
|
||||
void check_crs(json_object *j) {
|
||||
::check_crs(j, fname.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
void parse_json(struct serialization_state *sst, json_pull_ptr jp, int layer, std::string layername) {
|
||||
void parse_json(struct serialization_state *sst, json_pull_ptr &jp, int layer, std::string layername) {
|
||||
json_serialize_action jsa;
|
||||
jsa.fname = sst->fname;
|
||||
jsa.sst = sst;
|
||||
|
||||
Reference in New Issue
Block a user