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