aboutsummaryrefslogtreecommitdiff
path: root/lib/std/json.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2023-02-13 16:24:29 +0200
committerGitHub <noreply@github.com>2023-02-13 16:24:29 +0200
commitfc48467a97021cb872ff2a947f96e882274c39c1 (patch)
treefc86aeb23dd92fb36a15b33c4a228979f1e5e42b /lib/std/json.zig
parentc8dc00086e6622f3f29d7e18deb92ea102cf1074 (diff)
parentb1dd4b17d89633c4d26c39952f69d7ff2efb98ce (diff)
downloadzig-fc48467a97021cb872ff2a947f96e882274c39c1.tar.gz
zig-fc48467a97021cb872ff2a947f96e882274c39c1.zip
Merge pull request #14548 from schmee/std-json-fixes
Some std.json fixes
Diffstat (limited to 'lib/std/json.zig')
-rw-r--r--lib/std/json.zig43
1 files changed, 39 insertions, 4 deletions
diff --git a/lib/std/json.zig b/lib/std/json.zig
index ae8c4678a8..96e41e93c2 100644
--- a/lib/std/json.zig
+++ b/lib/std/json.zig
@@ -1163,11 +1163,12 @@ const ArrayList = std.ArrayList;
const StringArrayHashMap = std.StringArrayHashMap;
pub const ValueTree = struct {
- arena: ArenaAllocator,
+ arena: *ArenaAllocator,
root: Value,
pub fn deinit(self: *ValueTree) void {
self.arena.deinit();
+ self.arena.child_allocator.destroy(self.arena);
}
};
@@ -1639,7 +1640,7 @@ fn parseInternal(
const allocator = options.allocator orelse return error.AllocatorRequired;
switch (ptrInfo.size) {
.One => {
- const r: T = try allocator.create(ptrInfo.child);
+ const r: *ptrInfo.child = try allocator.create(ptrInfo.child);
errdefer allocator.destroy(r);
r.* = try parseInternal(ptrInfo.child, token, tokens, options);
return r;
@@ -1741,7 +1742,37 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
.Struct => |structInfo| {
inline for (structInfo.fields) |field| {
if (!field.is_comptime) {
- parseFree(field.type, @field(value, field.name), options);
+ var should_free = true;
+ if (field.default_value) |default| {
+ switch (@typeInfo(field.type)) {
+ // We must not attempt to free pointers to struct default values
+ .Pointer => |fieldPtrInfo| {
+ const field_value = @field(value, field.name);
+ const field_ptr = switch (fieldPtrInfo.size) {
+ .One => field_value,
+ .Slice => field_value.ptr,
+ else => unreachable, // Other pointer types are not parseable
+ };
+ const field_addr = @ptrToInt(field_ptr);
+
+ const casted_default = @ptrCast(*const field.type, @alignCast(@alignOf(field.type), default)).*;
+ const default_ptr = switch (fieldPtrInfo.size) {
+ .One => casted_default,
+ .Slice => casted_default.ptr,
+ else => unreachable, // Other pointer types are not parseable
+ };
+ const default_addr = @ptrToInt(default_ptr);
+
+ if (field_addr == default_addr) {
+ should_free = false;
+ }
+ },
+ else => {},
+ }
+ }
+ if (should_free) {
+ parseFree(field.type, @field(value, field.name), options);
+ }
}
}
},
@@ -1806,8 +1837,12 @@ pub const Parser = struct {
pub fn parse(p: *Parser, input: []const u8) !ValueTree {
var s = TokenStream.init(input);
- var arena = ArenaAllocator.init(p.allocator);
+ var arena = try p.allocator.create(ArenaAllocator);
+ errdefer p.allocator.destroy(arena);
+
+ arena.* = ArenaAllocator.init(p.allocator);
errdefer arena.deinit();
+
const allocator = arena.allocator();
while (try s.next()) |token| {