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:...@@ -15,6 +15,7 @@ pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options:
15 var p = Parser.init(alloc, inreader.any(), options);15 var p = Parser.init(alloc, inreader.any(), options);
16 defer p.temp.deinit(alloc);16 defer p.temp.deinit(alloc);
17 defer p.strings_map.deinit(alloc);17 defer p.strings_map.deinit(alloc);
18 defer p.numbers_map.deinit(alloc);
18 errdefer p.extras.deinit(alloc);19 errdefer p.extras.deinit(alloc);
1920
20 comptime std.debug.assert(@intFromEnum(Value.zero) == 0);21 comptime std.debug.assert(@intFromEnum(Value.zero) == 0);
...@@ -257,6 +258,7 @@ const Parser = struct {...@@ -257,6 +258,7 @@ const Parser = struct {
257 col: usize = 1,258 col: usize = 1,
258 extras: std.ArrayListUnmanaged(u8) = .{},259 extras: std.ArrayListUnmanaged(u8) = .{},
259 strings_map: std.StringArrayHashMapUnmanaged(StringIndex) = .{},260 strings_map: std.StringArrayHashMapUnmanaged(StringIndex) = .{},
261 numbers_map: std.StringArrayHashMapUnmanaged(NumberIndex) = .{},
260 depth: u16 = 0,262 depth: u16 = 0,
261263
262 support_trailing_commas: bool,264 support_trailing_commas: bool,
...@@ -432,16 +434,40 @@ const Parser = struct {...@@ -432,16 +434,40 @@ const Parser = struct {
432 const t = tracer.trace(@src(), "({s})", .{v});434 const t = tracer.trace(@src(), "({s})", .{v});
433 defer t.end();435 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);
435 const r = p.extras.items.len;441 const r = p.extras.items.len;
436 const l = v.len;442 const l = v.len;
437 if (l > std.math.maxInt(u8)) return error.JsonExpectedTODO;443 try p.extras.ensureUnusedCapacity(alloc, 1 + 4 + l);
438 try p.extras.ensureUnusedCapacity(alloc, 1 + 1 + l);
439 p.extras.appendAssumeCapacity(@intFromEnum(Value.Tag.number));444 p.extras.appendAssumeCapacity(@intFromEnum(Value.Tag.number));
440 p.extras.appendAssumeCapacity(@intCast(l));445 p.extras.appendSliceAssumeCapacity(&std.mem.toBytes(@as(u32, @intCast(l))));
441 p.extras.appendSliceAssumeCapacity(v);446 p.extras.appendSliceAssumeCapacity(v);
447 res.value_ptr.* = @enumFromInt(r);
442 return @enumFromInt(r);448 return @enumFromInt(r);
443 }449 }
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
445 pub fn getStr(p: *const Parser, sidx: StringIndex) string {471 pub fn getStr(p: *const Parser, sidx: StringIndex) string {
446 const i: u32 = @intFromEnum(sidx);472 const i: u32 = @intFromEnum(sidx);
447 std.debug.assert(@as(Value.Tag, @enumFromInt(p.extras.items[i])) == .string);473 std.debug.assert(@as(Value.Tag, @enumFromInt(p.extras.items[i])) == .string);