Skip to content

Commit e9c9538

Browse files
committed
Use allocator backed array for json value decoder
1 parent b92010c commit e9c9538

File tree

1 file changed

+39
-43
lines changed

1 file changed

+39
-43
lines changed

std/json.zig

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,9 +1017,7 @@ const JsonParser = struct {
10171017
state: State,
10181018
copy_strings: bool,
10191019
// Stores parent nodes and un-combined Values.
1020-
// Worst case scenario we have nested key, values and so need two times the stack size.
1021-
stack: [2 * StreamingJsonParser.max_stack_size]Value,
1022-
stack_used: u16,
1020+
stack: ArrayList(Value),
10231021

10241022
const State = enum {
10251023
ObjectKey,
@@ -1033,14 +1031,17 @@ const JsonParser = struct {
10331031
.allocator = allocator,
10341032
.state = State.Simple,
10351033
.copy_strings = copy_strings,
1036-
.stack = undefined,
1037-
.stack_used = 0,
1034+
.stack = ArrayList(Value).init(allocator),
10381035
};
10391036
}
10401037

1038+
pub fn deinit(p: &JsonParser) void {
1039+
p.stack.deinit();
1040+
}
1041+
10411042
pub fn reset(p: &JsonParser) void {
10421043
p.state = State.Simple;
1043-
p.stack_used = 0;
1044+
p.stack.shrink(0);
10441045
}
10451046

10461047
pub fn parse(p: &JsonParser, input: []const u8) !ValueTree {
@@ -1079,11 +1080,11 @@ const JsonParser = struct {
10791080
return error.IncompleteJsonInput;
10801081
}
10811082

1082-
std.debug.assert(p.stack_used == 1);
1083+
std.debug.assert(p.stack.len == 1);
10831084

10841085
return ValueTree {
10851086
.arena = arena,
1086-
.root = p.stack[0],
1087+
.root = p.stack.at(0),
10871088
};
10881089
}
10891090

@@ -1093,58 +1094,57 @@ const JsonParser = struct {
10931094
switch (p.state) {
10941095
State.ObjectKey => switch (token.id) {
10951096
Token.Id.ObjectEnd => {
1096-
if (p.stack_used == 1) {
1097+
if (p.stack.len == 1) {
10971098
return;
10981099
}
10991100

1100-
var value = p.stack[p.stack_used - 1];
1101-
p.stack_used -= 1;
1101+
var value = p.stack.pop();
11021102
try p.pushToParent(value);
11031103
},
11041104
Token.Id.String => {
1105-
p.pushStack(try p.parseString(allocator, token, input, i));
1105+
try p.stack.append(try p.parseString(allocator, token, input, i));
11061106
p.state = State.ObjectValue;
11071107
},
11081108
else => {
11091109
unreachable;
11101110
},
11111111
},
11121112
State.ObjectValue => {
1113-
var object = &p.stack[p.stack_used - 2].Object;
1114-
var key = p.stack[p.stack_used - 1].String;
1113+
var object = &p.stack.items[p.stack.len - 2].Object;
1114+
var key = p.stack.items[p.stack.len - 1].String;
11151115

11161116
switch (token.id) {
11171117
Token.Id.ObjectBegin => {
1118-
p.pushStack(Value { .Object = ObjectMap.init(allocator) });
1118+
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
11191119
p.state = State.ObjectKey;
11201120
},
11211121
Token.Id.ArrayBegin => {
1122-
p.pushStack(Value { .Array = ArrayList(Value).init(allocator) });
1122+
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
11231123
p.state = State.ArrayValue;
11241124
},
11251125
Token.Id.String => {
11261126
_ = try object.put(key, try p.parseString(allocator, token, input, i));
1127-
p.stack_used -= 1;
1127+
_ = p.stack.pop();
11281128
p.state = State.ObjectKey;
11291129
},
11301130
Token.Id.Number => {
11311131
_ = try object.put(key, try p.parseNumber(token, input, i));
1132-
p.stack_used -= 1;
1132+
_ = p.stack.pop();
11331133
p.state = State.ObjectKey;
11341134
},
11351135
Token.Id.True => {
11361136
_ = try object.put(key, Value { .Bool = true });
1137-
p.stack_used -= 1;
1137+
_ = p.stack.pop();
11381138
p.state = State.ObjectKey;
11391139
},
11401140
Token.Id.False => {
11411141
_ = try object.put(key, Value { .Bool = false });
1142-
p.stack_used -= 1;
1142+
_ = p.stack.pop();
11431143
p.state = State.ObjectKey;
11441144
},
11451145
Token.Id.Null => {
11461146
_ = try object.put(key, Value.Null);
1147-
p.stack_used -= 1;
1147+
_ = p.stack.pop();
11481148
p.state = State.ObjectKey;
11491149
},
11501150
else => {
@@ -1153,24 +1153,23 @@ const JsonParser = struct {
11531153
}
11541154
},
11551155
State.ArrayValue => {
1156-
var array = &p.stack[p.stack_used - 1].Array;
1156+
var array = &p.stack.items[p.stack.len - 1].Array;
11571157

11581158
switch (token.id) {
11591159
Token.Id.ArrayEnd => {
1160-
if (p.stack_used == 1) {
1160+
if (p.stack.len == 1) {
11611161
return;
11621162
}
11631163

1164-
var value = p.stack[p.stack_used - 1];
1165-
p.stack_used -= 1;
1164+
var value = p.stack.pop();
11661165
try p.pushToParent(value);
11671166
},
11681167
Token.Id.ObjectBegin => {
1169-
p.pushStack(Value { .Object = ObjectMap.init(allocator) });
1168+
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
11701169
p.state = State.ObjectKey;
11711170
},
11721171
Token.Id.ArrayBegin => {
1173-
p.pushStack(Value { .Array = ArrayList(Value).init(allocator) });
1172+
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
11741173
p.state = State.ArrayValue;
11751174
},
11761175
Token.Id.String => {
@@ -1195,27 +1194,27 @@ const JsonParser = struct {
11951194
},
11961195
State.Simple => switch (token.id) {
11971196
Token.Id.ObjectBegin => {
1198-
p.pushStack(Value { .Object = ObjectMap.init(allocator) });
1197+
try p.stack.append(Value { .Object = ObjectMap.init(allocator) });
11991198
p.state = State.ObjectKey;
12001199
},
12011200
Token.Id.ArrayBegin => {
1202-
p.pushStack(Value { .Array = ArrayList(Value).init(allocator) });
1201+
try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) });
12031202
p.state = State.ArrayValue;
12041203
},
12051204
Token.Id.String => {
1206-
p.pushStack(try p.parseString(allocator, token, input, i));
1205+
try p.stack.append(try p.parseString(allocator, token, input, i));
12071206
},
12081207
Token.Id.Number => {
1209-
p.pushStack(try p.parseNumber(token, input, i));
1208+
try p.stack.append(try p.parseNumber(token, input, i));
12101209
},
12111210
Token.Id.True => {
1212-
p.pushStack(Value { .Bool = true });
1211+
try p.stack.append(Value { .Bool = true });
12131212
},
12141213
Token.Id.False => {
1215-
p.pushStack(Value { .Bool = false });
1214+
try p.stack.append(Value { .Bool = false });
12161215
},
12171216
Token.Id.Null => {
1218-
p.pushStack(Value.Null);
1217+
try p.stack.append(Value.Null);
12191218
},
12201219
Token.Id.ObjectEnd, Token.Id.ArrayEnd => {
12211220
unreachable;
@@ -1225,12 +1224,12 @@ const JsonParser = struct {
12251224
}
12261225

12271226
fn pushToParent(p: &JsonParser, value: &const Value) !void {
1228-
switch (p.stack[p.stack_used - 1]) {
1227+
switch (p.stack.at(p.stack.len - 1)) {
12291228
// Object Parent -> [ ..., object, <key>, value ]
12301229
Value.String => |key| {
1231-
p.stack_used -= 1;
1230+
_ = p.stack.pop();
12321231

1233-
var object = &p.stack[p.stack_used - 1].Object;
1232+
var object = &p.stack.items[p.stack.len - 1].Object;
12341233
_ = try object.put(key, value);
12351234
p.state = State.ObjectKey;
12361235
},
@@ -1245,11 +1244,6 @@ const JsonParser = struct {
12451244
}
12461245
}
12471246

1248-
fn pushStack(p: &JsonParser, value: &const Value) void {
1249-
p.stack[p.stack_used] = *value;
1250-
p.stack_used += 1;
1251-
}
1252-
12531247
fn parseString(p: &JsonParser, allocator: &Allocator, token: &const Token, input: []const u8, i: usize) !Value {
12541248
// TODO: We don't strictly have to copy values which do not contain any escape
12551249
// characters if flagged with the option.
@@ -1270,6 +1264,7 @@ const debug = std.debug;
12701264

12711265
test "json parser dynamic" {
12721266
var p = JsonParser.init(std.debug.global_allocator, false);
1267+
defer p.deinit();
12731268

12741269
const s =
12751270
\\{
@@ -1289,7 +1284,8 @@ test "json parser dynamic" {
12891284
;
12901285

12911286
var tree = try p.parse(s);
1292-
tree.deinit();
1287+
defer tree.deinit();
1288+
12931289
var root = tree.root;
12941290

12951291
var image = (??root.Object.get("Image")).value;

0 commit comments

Comments
 (0)