mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
std.json: fix key allocation in HashMap for streaming json parsing (#16422)
This commit is contained in:
parent
32a175740c
commit
04c7b55de4
@ -24,15 +24,10 @@ pub fn ArrayHashMap(comptime T: type) type {
|
|||||||
|
|
||||||
if (.object_begin != try source.next()) return error.UnexpectedToken;
|
if (.object_begin != try source.next()) return error.UnexpectedToken;
|
||||||
while (true) {
|
while (true) {
|
||||||
const token = try source.nextAlloc(allocator, .alloc_if_needed);
|
const token = try source.nextAlloc(allocator, options.allocate.?);
|
||||||
switch (token) {
|
switch (token) {
|
||||||
inline .string, .allocated_string => |k| {
|
inline .string, .allocated_string => |k| {
|
||||||
const gop = try map.getOrPut(allocator, k);
|
const gop = try map.getOrPut(allocator, k);
|
||||||
if (token == .allocated_string) {
|
|
||||||
// Free the key before recursing in case we're using an allocator
|
|
||||||
// that optimizes freeing the last allocated object.
|
|
||||||
allocator.free(k);
|
|
||||||
}
|
|
||||||
if (gop.found_existing) {
|
if (gop.found_existing) {
|
||||||
switch (options.duplicate_field_behavior) {
|
switch (options.duplicate_field_behavior) {
|
||||||
.use_first => {
|
.use_first => {
|
||||||
|
|||||||
@ -5,10 +5,13 @@ const ArrayHashMap = @import("hashmap.zig").ArrayHashMap;
|
|||||||
|
|
||||||
const parseFromSlice = @import("static.zig").parseFromSlice;
|
const parseFromSlice = @import("static.zig").parseFromSlice;
|
||||||
const parseFromSliceLeaky = @import("static.zig").parseFromSliceLeaky;
|
const parseFromSliceLeaky = @import("static.zig").parseFromSliceLeaky;
|
||||||
|
const parseFromTokenSource = @import("static.zig").parseFromTokenSource;
|
||||||
const parseFromValue = @import("static.zig").parseFromValue;
|
const parseFromValue = @import("static.zig").parseFromValue;
|
||||||
const stringifyAlloc = @import("stringify.zig").stringifyAlloc;
|
const stringifyAlloc = @import("stringify.zig").stringifyAlloc;
|
||||||
const Value = @import("dynamic.zig").Value;
|
const Value = @import("dynamic.zig").Value;
|
||||||
|
|
||||||
|
const jsonReader = @import("./scanner.zig").reader;
|
||||||
|
|
||||||
const T = struct {
|
const T = struct {
|
||||||
i: i32,
|
i: i32,
|
||||||
s: []const u8,
|
s: []const u8,
|
||||||
@ -29,6 +32,31 @@ test "parse json hashmap" {
|
|||||||
try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i);
|
try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "parse json hashmap while streaming" {
|
||||||
|
const doc =
|
||||||
|
\\{
|
||||||
|
\\ "abc": {"i": 0, "s": "d"},
|
||||||
|
\\ "xyz": {"i": 1, "s": "w"}
|
||||||
|
\\}
|
||||||
|
;
|
||||||
|
var stream = std.io.fixedBufferStream(doc);
|
||||||
|
var json_reader = jsonReader(testing.allocator, stream.reader());
|
||||||
|
|
||||||
|
var parsed = try parseFromTokenSource(
|
||||||
|
ArrayHashMap(T),
|
||||||
|
testing.allocator,
|
||||||
|
&json_reader,
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
defer parsed.deinit();
|
||||||
|
// Deinit our reader to invalidate its buffer
|
||||||
|
json_reader.deinit();
|
||||||
|
|
||||||
|
try testing.expectEqual(@as(usize, 2), parsed.value.map.count());
|
||||||
|
try testing.expectEqualStrings("d", parsed.value.map.get("abc").?.s);
|
||||||
|
try testing.expectEqual(@as(i32, 1), parsed.value.map.get("xyz").?.i);
|
||||||
|
}
|
||||||
|
|
||||||
test "parse json hashmap duplicate fields" {
|
test "parse json hashmap duplicate fields" {
|
||||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user