Store hash key/value pairs in one ordered vector

Replace the parallel std::vector<json_object_ptr> keys / values on
json_hash with a single std::vector<json_entry>, where json_entry is
a small {key, value} aggregate. This still preserves insertion order
(the property the parallel vectors were providing) but removes the
"keep two vectors in lockstep" pattern, and call sites can now use
range-for with structured bindings:

    for (auto &[k, v] : o->entries()) { ... }

Side effects:

* sizeof(json_hash) drops from 72 to 48 bytes (one fewer vector
  header), matching json_array.
* The keys() and values() accessors on json_object are replaced by a
  single entries() accessor returning std::vector<json_entry>&.
* All call sites were swept from the old paired-index pattern
  (`o->keys()[i]` / `o->values()[i]`) to entry-based access. Where the
  original pattern relied on `nprop = 0` to short-circuit iteration on
  a null or non-hash `properties`, the rewrite now guards the loop
  explicitly with `if (o->type == JSON_HASH)` so that calling
  entries() doesn't trip the asserting downcast.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Erica Fischer
2026-05-30 17:49:13 -07:00
co-authored by Cursor
parent f366b2c4aa
commit 4d9a48c3d4
11 changed files with 122 additions and 137 deletions
+11 -13
View File
@@ -175,24 +175,22 @@ int serialize_geojson_feature(struct serialization_state *sst, json_object_ptr g
}
}
size_t nprop = 0;
if (properties != nullptr && properties->type == JSON_HASH) {
nprop = properties->keys().size();
}
std::vector<std::shared_ptr<std::string>> full_keys;
std::vector<serial_val> values;
full_keys.reserve(nprop);
values.reserve(nprop);
key_pool key_pool;
for (size_t i = 0; i < nprop; i++) {
if (properties->keys()[i]->type == JSON_STRING) {
serial_val sv = stringify_value(properties->values()[i], sst->fname, sst->line, feature);
if (properties != nullptr && properties->type == JSON_HASH) {
const auto &entries = properties->entries();
full_keys.reserve(entries.size());
values.reserve(entries.size());
full_keys.emplace_back(key_pool.pool(properties->keys()[i]->string().c_str()));
values.push_back(std::move(sv));
for (const auto &e : entries) {
if (e.key->type == JSON_STRING) {
serial_val sv = stringify_value(e.value, sst->fname, sst->line, feature);
full_keys.emplace_back(key_pool.pool(e.key->string().c_str()));
values.push_back(std::move(sv));
}
}
}