authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-10-27 02:54:02 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-10-27 02:54:19 -07:00
logb0258f059b85c1df70dc99a9c9e4b9d95da206fe
tree073cc2997615218ea2ea977bf14fae1267464d6c
parent532d0876e5b06b52fcdef345854ff9792ec02380

make Parser public so that it can be used as an independent Document builder


1 files changed, 40 insertions(+), 18 deletions(-)

json.zig+40-18
...@@ -4,8 +4,8 @@ const extras = @import("extras");...@@ -4,8 +4,8 @@ const extras = @import("extras");
4const tracer = @import("tracer");4const tracer = @import("tracer");
5const intrusive_parser = @import("intrusive-parser");5const intrusive_parser = @import("intrusive-parser");
66
7const Error = error{ OutOfMemory, EndOfStream, MalformedJson };7pub const Error = error{ OutOfMemory, EndOfStream, MalformedJson };
8const ObjectHashMap = std.AutoArrayHashMapUnmanaged(StringIndex, ValueIndex);8pub const ObjectHashMap = std.AutoArrayHashMapUnmanaged(StringIndex, ValueIndex);
99
10pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options: Parser.Options) (@TypeOf(inreader).Error || Error)!Document {10pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options: Parser.Options) (@TypeOf(inreader).Error || Error)!Document {
11 const t = tracer.trace(@src(), "", .{});11 const t = tracer.trace(@src(), "", .{});
...@@ -13,19 +13,8 @@ pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options:...@@ -13,19 +13,8 @@ pub fn parse(alloc: std.mem.Allocator, path: string, inreader: anytype, options:
1313
14 _ = path;14 _ = path;
1515
16 var p = Parser.init(alloc, inreader.any(), options);16 var p = try Parser.init(alloc, inreader.any(), options);
17 defer p.parser.deinit();17 defer p.deinit();
18 defer p.numbers_map.deinit(alloc);
19
20 comptime std.debug.assert(@intFromEnum(Value.zero) == 0);
21 try p.parser.data.ensureUnusedCapacity(alloc, 4096);
22 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.zero));
23 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.null));
24 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.true));
25 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.false));
26 _ = try p.addStr(alloc, "");
27 std.debug.assert(try p.addArray(alloc, &.{}) == .empty_array);
28 std.debug.assert(try p.addObject(alloc, &ObjectHashMap{}) == .empty_object);
2918
30 const root = try parseElementPrecise(alloc, &p, @TypeOf(inreader).Error || Error);19 const root = try parseElementPrecise(alloc, &p, @TypeOf(inreader).Error || Error);
31 if (p.avail() > 0) return error.MalformedJson;20 if (p.avail() > 0) return error.MalformedJson;
...@@ -251,7 +240,7 @@ fn parseWs(p: *Parser) !void {...@@ -251,7 +240,7 @@ fn parseWs(p: *Parser) !void {
251 }240 }
252}241}
253242
254const Parser = struct {243pub const Parser = struct {
255 parser: intrusive_parser.Parser,244 parser: intrusive_parser.Parser,
256 numbers_map: std.StringArrayHashMapUnmanaged(NumberIndex) = .{},245 numbers_map: std.StringArrayHashMapUnmanaged(NumberIndex) = .{},
257 depth: u16 = 0,246 depth: u16 = 0,
...@@ -259,12 +248,28 @@ const Parser = struct {...@@ -259,12 +248,28 @@ const Parser = struct {
259 support_trailing_commas: bool,248 support_trailing_commas: bool,
260 maximum_depth: u16,249 maximum_depth: u16,
261250
262 pub fn init(allocator: std.mem.Allocator, any: std.io.AnyReader, options: Options) Parser {251 pub fn init(allocator: std.mem.Allocator, any: std.io.AnyReader, options: Options) !Parser {
263 return .{252 var p: Parser = .{
264 .parser = intrusive_parser.Parser.init(allocator, any, @intFromEnum(Value.Tag.string)),253 .parser = intrusive_parser.Parser.init(allocator, any, @intFromEnum(Value.Tag.string)),
265 .support_trailing_commas = options.support_trailing_commas,254 .support_trailing_commas = options.support_trailing_commas,
266 .maximum_depth = options.maximum_depth,255 .maximum_depth = options.maximum_depth,
267 };256 };
257 comptime std.debug.assert(@intFromEnum(Value.zero) == 0);
258 try p.parser.data.ensureUnusedCapacity(allocator, 4096);
259 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.zero));
260 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.null));
261 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.true));
262 p.parser.data.appendAssumeCapacity(@intFromEnum(Value.Tag.false));
263 _ = try p.addStr(allocator, "");
264 std.debug.assert(try p.addArray(allocator, &.{}) == .empty_array);
265 std.debug.assert(try p.addObject(allocator, &ObjectHashMap{}) == .empty_object);
266
267 return p;
268 }
269
270 pub fn deinit(p: *Parser) void {
271 defer p.numbers_map.deinit(p.parser.allocator);
272 defer p.parser.deinit();
268 }273 }
269274
270 pub const Options = struct {275 pub const Options = struct {
...@@ -290,6 +295,17 @@ const Parser = struct {...@@ -290,6 +295,17 @@ const Parser = struct {
290 return @enumFromInt(r);295 return @enumFromInt(r);
291 }296 }
292297
298 pub fn addObjectFromConst(p: *Parser, alloc: std.mem.Allocator, members: []const struct { StringIndex, ValueIndex }) !ValueIndex {
299 const t = tracer.trace(@src(), "({d})", .{members.len});
300 defer t.end();
301
302 var map = ObjectHashMap{};
303 defer map.deinit(alloc);
304 try map.ensureTotalCapacity(alloc, members.len);
305 for (members) |member| map.putAssumeCapacity(member[0], member[1]);
306 return p.addObject(alloc, &map);
307 }
308
293 // tag(u8) + len(u32) + items(N * u32)309 // tag(u8) + len(u32) + items(N * u32)
294 pub fn addArray(p: *Parser, alloc: std.mem.Allocator, items: []const ValueIndex) !ValueIndex {310 pub fn addArray(p: *Parser, alloc: std.mem.Allocator, items: []const ValueIndex) !ValueIndex {
295 const t = tracer.trace(@src(), "({d})", .{items.len});311 const t = tracer.trace(@src(), "({d})", .{items.len});
...@@ -313,6 +329,11 @@ const Parser = struct {...@@ -313,6 +329,11 @@ const Parser = struct {
313 return @enumFromInt(try p.parser.addStr(alloc, str));329 return @enumFromInt(try p.parser.addStr(alloc, str));
314 }330 }
315331
332 // tag(u8) + len(u32) + bytes(N)
333 pub fn addStrV(p: *Parser, alloc: std.mem.Allocator, str: string) !ValueIndex {
334 return @enumFromInt(@intFromEnum(try p.addStr(alloc, str)));
335 }
336
316 const Adapter = struct {337 const Adapter = struct {
317 p: *const Parser,338 p: *const Parser,
318339
...@@ -414,6 +435,7 @@ pub const ValueIndex = enum(u32) {...@@ -414,6 +435,7 @@ pub const ValueIndex = enum(u32) {
414435
415 pub fn v(this: ValueIndex) Value {436 pub fn v(this: ValueIndex) Value {
416 std.debug.assert(this != .zero);437 std.debug.assert(this != .zero);
438 std.debug.assert(doc != null); // make sure to call Document.acquire()
417 return switch (@as(Value.Tag, @enumFromInt(doc.?.extras[@intFromEnum(this)]))) {439 return switch (@as(Value.Tag, @enumFromInt(doc.?.extras[@intFromEnum(this)]))) {
418 .zero => .zero,440 .zero => .zero,
419 .null => .null,441 .null => .null,