support arrays finally done

This commit is contained in:
yuzu 2025-05-25 15:35:05 -05:00
parent 31107aa9d4
commit 3128f9e768

View File

@ -153,38 +153,6 @@ fn addString(self: *Self, allocator: std.mem.Allocator, bytes: []const u8) !usiz
return idx;
}
fn addObject(self: *Self, allocator: std.mem.Allocator, object: std.AutoArrayHashMapUnmanaged([]const u8, JsonInput)) !usize {
var entry: ?ObjectEntry = null;
for (object.keys(), object.values(), 0..) |key, value, times| {
const stridx = try self.property_index.add(allocator, key);
try self.index.ensureUnusedCapacity(allocator, 1);
const vidx = self.index.addOneAssumeCapacity();
self.index.set(vidx, @unionInit(JsonValue, std.meta.activeTag(value), self.addValue(allocator, value)));
if (times == 0) {
entry = ObjectEntry{
.len = object.entries.len,
.property_idx = stridx,
.value_idx = vidx,
};
}
}
try self.index.ensureUnusedCapacity(allocator, 1);
const idx = self.index.addOneAssumeCapacity();
if (entry) |e| {
self.index.set(idx, .{ .object = e });
return idx;
} else {
self.index.set(idx, .{ .object = ObjectEntry{
.len = 0,
.property_idx = 0,
.value_idx = 1,
} });
return idx;
}
}
fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize {
try self.index.ensureUnusedCapacity(allocator, 1);
const idx = self.index.addOneAssumeCapacity();
@ -197,33 +165,6 @@ fn addEmptyObject(self: *Self, allocator: std.mem.Allocator) !usize {
return idx;
}
fn addArray(self: *Self, allocator: std.mem.Allocator, array: []JsonInput) !usize {
var entry: ?ArraySlice = null;
for (array, 0..) |value, times| {
try self.index.ensureUnusedCapacity(allocator, 1);
const idx = self.index.addOneAssumeCapacity();
self.index.set(idx, @unionInit(JsonValue, std.meta.activeTag(value), self.addValue(allocator, value)));
if (times == 0) {
entry = ArraySlice{
.start = idx,
.len = array.len,
};
}
}
try self.index.ensureUnusedCapacity(allocator, 1);
const idx = self.index.addOneAssumeCapacity();
if (entry) |e| {
self.index.set(idx, .{ .array = e });
return idx;
} else {
self.index.set(idx, .{ .array = ArraySlice{
.start = 0,
.len = 0,
} });
return idx;
}
}
fn addEmptyArray(self: *Self, allocator: std.mem.Allocator) !usize {
try self.index.ensureUnusedCapacity(allocator, 1);
const idx = self.index.addOneAssumeCapacity();
@ -248,17 +189,6 @@ fn addNull(self: *Self, allocator: std.mem.Allocator) !usize {
return idx;
}
fn addValue(self: *Self, allocator: std.mem.Allocator, value: JsonInput) !void {
switch (value) {
.null => try self.addNull(allocator),
.bool => try self.addBool(allocator, value.bool),
.number => try self.addNumber(allocator, value.number),
.string => try self.addString(allocator, value.string),
.array => try self.addArray(allocator, value.array),
.object => try self.addObject(allocator, value.object),
}
}
fn getProperty(self: *Self, index: []const u8) ?StringIndex {
return self.property_index.string_table.get(index);
}
@ -435,18 +365,7 @@ test getValue {
const json =
\\ {
\\ "name": "Yuzu",
\\ "author": true,
\\ "age": 15,
\\ "address": {
\\ "street": 1,
\\ "deeply_nested": {
\\ "k": 5,
\\ "socialist": "expansion",
\\ "idk": {"a":"b"}
\\ }
\\ },
\\ "offset": "yes"
\\ "array": [1,2,3,[4,5,6]]
\\ }
;
@ -543,7 +462,7 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
else => return error.InvalidSyntax,
}
},
.object_end => {
.object_end, .array_end => {
defer tokenizer.skipWhitespace();
assert(query.pop() != null);
@ -552,25 +471,66 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
token = next;
switch (next.type) {
.comma => continue :flag .comma,
.object_end, .array_end => |t| continue :flag t,
.object_end, .array_end => continue :flag next.type,
else => return error.InvalidSyntax,
}
},
.array_begin => {
defer tokenizer.skipWhitespace();
// order matters
const parent_idx = query.get(query.len - 1);
const idx_ptr = try query.addOne();
idx_ptr.* = try self.addEmptyArray(allocator);
self.index.set(idx_ptr.*, .{ .array = ArraySlice{
.len = 0,
.start = idx_ptr.* + 1,
} });
switch (self.index.get(parent_idx)) {
.array => |slice| {
self.index.set(parent_idx, .{ .array = ArraySlice{
.len = slice.len + 1,
.start = if (slice.len == 0) idx_ptr.* else slice.start,
} });
},
else => {},
}
const next = it.next() orelse return error.InvalidSyntax;
token = next;
switch (next.type) {
.property => return error.InvalidSyntax,
else => continue :flag next.type,
}
},
.true, .false => {
defer tokenizer.skipWhitespace();
_ = try self.addBool(allocator, if (token.type == .true) true else false);
const idx = try self.addBool(allocator, if (token.type == .true) true else false);
const parent_idx = query.get(query.len - 1);
switch (self.index.get(parent_idx)) {
.array => |slice| {
self.index.set(parent_idx, .{ .array = ArraySlice{
.len = slice.len + 1,
.start = if (slice.len == 0) idx else slice.start,
} });
},
else => {},
}
const next = it.next() orelse return error.InvalidSyntax;
token = next;
switch (next.type) {
.comma => continue :flag .comma,
.object_end => continue :flag .object_end,
.object_end, .array_end => continue :flag next.type,
else => return error.InvalidSyntax,
}
},
.string => {
defer tokenizer.skipWhitespace();
const parent_idx = query.get(query.len - 1);
const next = it.next() orelse return error.InvalidSyntax;
switch (next.type) {
@ -578,8 +538,17 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
continue :flag .property;
},
else => |t| {
_ = try self.addString(allocator, token.value.?.string);
const idx = try self.addString(allocator, token.value.?.string);
allocator.free(token.value.?.string);
switch (self.index.get(parent_idx)) {
.array => |slice| {
self.index.set(parent_idx, .{ .array = ArraySlice{
.len = slice.len + 1,
.start = if (slice.len == 0) idx else slice.start,
} });
},
else => {},
}
token = next;
continue :flag t;
@ -589,13 +558,23 @@ pub fn parse(self: *Self, tokenizer: *Tokenizer) !usize {
.number => {
defer tokenizer.skipWhitespace();
_ = try self.addNumber(allocator, token.value.?.number);
const parent_idx = query.get(query.len - 1);
const idx = try self.addNumber(allocator, token.value.?.number);
switch (self.index.get(parent_idx)) {
.array => |slice| {
self.index.set(parent_idx, .{ .array = ArraySlice{
.len = slice.len + 1,
.start = if (slice.len == 0) idx else slice.start,
} });
},
else => {},
}
const next = it.next() orelse return error.InvalidSyntax;
token = next;
switch (next.type) {
.comma => continue :flag .comma,
.object_end => continue :flag .object_end,
.object_end, .array_end => continue :flag next.type,
else => return error.InvalidSyntax,
}
},