authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-06-01 18:41:28 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-06-01 18:41:28 -07:00
log032680a09a80700a90e356f1fe4035c96e619b33
tree7e78772064d37f3d4eccee4926d6bd3aa27749a3
parent96e162492f32df28e9b38f31ff558d63f59e23a0

add an intern pool for number strings


1 files changed, 29 insertions(+), 3 deletions(-)

json.zig+29-3
......@@ -15,6 +15,7 @@ pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options:
1515 var p = Parser.init(alloc, inreader.any(), options);
1616 defer p.temp.deinit(alloc);
1717 defer p.strings_map.deinit(alloc);
18 defer p.numbers_map.deinit(alloc);
1819 errdefer p.extras.deinit(alloc);
1920
2021 comptime std.debug.assert(@intFromEnum(Value.zero) == 0);
......@@ -257,6 +258,7 @@ const Parser = struct {
257258 col: usize = 1,
258259 extras: std.ArrayListUnmanaged(u8) = .{},
259260 strings_map: std.StringArrayHashMapUnmanaged(StringIndex) = .{},
261 numbers_map: std.StringArrayHashMapUnmanaged(NumberIndex) = .{},
260262 depth: u16 = 0,
261263
262264 support_trailing_commas: bool,
......@@ -432,16 +434,40 @@ const Parser = struct {
432434 const t = tracer.trace(@src(), "({s})", .{v});
433435 defer t.end();
434436
437 const adapter: AdapterNum = .{ .p = p };
438 const res = try p.numbers_map.getOrPutAdapted(alloc, v, adapter);
439 if (res.found_existing) return @enumFromInt(@intFromEnum(res.value_ptr.*));
440 errdefer p.numbers_map.orderedRemoveAt(res.index);
435441 const r = p.extras.items.len;
436442 const l = v.len;
437 if (l > std.math.maxInt(u8)) return error.JsonExpectedTODO;
438 try p.extras.ensureUnusedCapacity(alloc, 1 + 1 + l);
443 try p.extras.ensureUnusedCapacity(alloc, 1 + 4 + l);
439444 p.extras.appendAssumeCapacity(@intFromEnum(Value.Tag.number));
440 p.extras.appendAssumeCapacity(@intCast(l));
445 p.extras.appendSliceAssumeCapacity(&std.mem.toBytes(@as(u32, @intCast(l))));
441446 p.extras.appendSliceAssumeCapacity(v);
447 res.value_ptr.* = @enumFromInt(r);
442448 return @enumFromInt(r);
443449 }
444450
451 const AdapterNum = struct {
452 p: *const Parser,
453
454 pub fn hash(ctx: @This(), a: string) u32 {
455 _ = ctx;
456 var hasher = std.hash.Wyhash.init(0);
457 hasher.update(a);
458 return @truncate(hasher.final());
459 }
460
461 pub fn eql(ctx: @This(), a: string, _: string, b_index: usize) bool {
462 const sidx = ctx.p.numbers_map.values()[b_index];
463 const i: u32 = @intFromEnum(sidx);
464 std.debug.assert(@as(Value.Tag, @enumFromInt(ctx.p.extras.items[i])) == .number);
465 const l: u32 = @bitCast(ctx.p.extras.items[i..][1..][0..4].*);
466 const b = ctx.p.extras.items[i..][1..][4..][0..l];
467 return std.mem.eql(u8, a, b);
468 }
469 };
470
445471 pub fn getStr(p: *const Parser, sidx: StringIndex) string {
446472 const i: u32 = @intFromEnum(sidx);
447473 std.debug.assert(@as(Value.Tag, @enumFromInt(p.extras.items[i])) == .string);