| ... | @@ -1017,9 +1017,7 @@ const JsonParser = struct { | ... | @@ -1017,9 +1017,7 @@ const JsonParser = struct { |
| 1017 | state: State, | 1017 | state: State, |
| 1018 | copy_strings: bool, | 1018 | copy_strings: bool, |
| 1019 | // Stores parent nodes and un-combined Values. | 1019 | // Stores parent nodes and un-combined Values. |
| 1020 | // Worst case scenario we have nested key, values and so need two times the stack size. | 1020 | stack: ArrayList(Value), |
| 1021 | stack: [2 * StreamingJsonParser.max_stack_size]Value, | | |
| 1022 | stack_used: u16, | | |
| 1023 | | 1021 | |
| 1024 | const State = enum { | 1022 | const State = enum { |
| 1025 | ObjectKey, | 1023 | ObjectKey, |
| ... | @@ -1033,14 +1031,17 @@ const JsonParser = struct { | ... | @@ -1033,14 +1031,17 @@ const JsonParser = struct { |
| 1033 | .allocator = allocator, | 1031 | .allocator = allocator, |
| 1034 | .state = State.Simple, | 1032 | .state = State.Simple, |
| 1035 | .copy_strings = copy_strings, | 1033 | .copy_strings = copy_strings, |
| 1036 | .stack = undefined, | 1034 | .stack = ArrayList(Value).init(allocator), |
| 1037 | .stack_used = 0, | | |
| 1038 | }; | 1035 | }; |
| 1039 | } | 1036 | } |
| 1040 | | 1037 | |
| | 1038 | pub fn deinit(p: &JsonParser) void { |
| | 1039 | p.stack.deinit(); |
| | 1040 | } |
| | 1041 | |
| 1041 | pub fn reset(p: &JsonParser) void { | 1042 | pub fn reset(p: &JsonParser) void { |
| 1042 | p.state = State.Simple; | 1043 | p.state = State.Simple; |
| 1043 | p.stack_used = 0; | 1044 | p.stack.shrink(0); |
| 1044 | } | 1045 | } |
| 1045 | | 1046 | |
| 1046 | pub fn parse(p: &JsonParser, input: []const u8) !ValueTree { | 1047 | pub fn parse(p: &JsonParser, input: []const u8) !ValueTree { |
| ... | @@ -1079,11 +1080,11 @@ const JsonParser = struct { | ... | @@ -1079,11 +1080,11 @@ const JsonParser = struct { |
| 1079 | return error.IncompleteJsonInput; | 1080 | return error.IncompleteJsonInput; |
| 1080 | } | 1081 | } |
| 1081 | | 1082 | |
| 1082 | std.debug.assert(p.stack_used == 1); | 1083 | std.debug.assert(p.stack.len == 1); |
| 1083 | | 1084 | |
| 1084 | return ValueTree { | 1085 | return ValueTree { |
| 1085 | .arena = arena, | 1086 | .arena = arena, |
| 1086 | .root = p.stack[0], | 1087 | .root = p.stack.at(0), |
| 1087 | }; | 1088 | }; |
| 1088 | } | 1089 | } |
| 1089 | | 1090 | |
| ... | @@ -1093,16 +1094,15 @@ const JsonParser = struct { | ... | @@ -1093,16 +1094,15 @@ const JsonParser = struct { |
| 1093 | switch (p.state) { | 1094 | switch (p.state) { |
| 1094 | State.ObjectKey => switch (token.id) { | 1095 | State.ObjectKey => switch (token.id) { |
| 1095 | Token.Id.ObjectEnd => { | 1096 | Token.Id.ObjectEnd => { |
| 1096 | if (p.stack_used == 1) { | 1097 | if (p.stack.len == 1) { |
| 1097 | return; | 1098 | return; |
| 1098 | } | 1099 | } |
| 1099 | | 1100 | |
| 1100 | var value = p.stack[p.stack_used - 1]; | 1101 | var value = p.stack.pop(); |
| 1101 | p.stack_used -= 1; | | |
| 1102 | try p.pushToParent(value); | 1102 | try p.pushToParent(value); |
| 1103 | }, | 1103 | }, |
| 1104 | Token.Id.String => { | 1104 | 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)); |
| 1106 | p.state = State.ObjectValue; | 1106 | p.state = State.ObjectValue; |
| 1107 | }, | 1107 | }, |
| 1108 | else => { | 1108 | else => { |
| ... | @@ -1110,41 +1110,41 @@ const JsonParser = struct { | ... | @@ -1110,41 +1110,41 @@ const JsonParser = struct { |
| 1110 | }, | 1110 | }, |
| 1111 | }, | 1111 | }, |
| 1112 | State.ObjectValue => { | 1112 | State.ObjectValue => { |
| 1113 | var object = &p.stack[p.stack_used - 2].Object; | 1113 | var object = &p.stack.items[p.stack.len - 2].Object; |
| 1114 | var key = p.stack[p.stack_used - 1].String; | 1114 | var key = p.stack.items[p.stack.len - 1].String; |
| 1115 | | 1115 | |
| 1116 | switch (token.id) { | 1116 | switch (token.id) { |
| 1117 | Token.Id.ObjectBegin => { | 1117 | Token.Id.ObjectBegin => { |
| 1118 | p.pushStack(Value { .Object = ObjectMap.init(allocator) }); | 1118 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); |
| 1119 | p.state = State.ObjectKey; | 1119 | p.state = State.ObjectKey; |
| 1120 | }, | 1120 | }, |
| 1121 | Token.Id.ArrayBegin => { | 1121 | Token.Id.ArrayBegin => { |
| 1122 | p.pushStack(Value { .Array = ArrayList(Value).init(allocator) }); | 1122 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); |
| 1123 | p.state = State.ArrayValue; | 1123 | p.state = State.ArrayValue; |
| 1124 | }, | 1124 | }, |
| 1125 | Token.Id.String => { | 1125 | Token.Id.String => { |
| 1126 | _ = try object.put(key, try p.parseString(allocator, token, input, i)); | 1126 | _ = try object.put(key, try p.parseString(allocator, token, input, i)); |
| 1127 | p.stack_used -= 1; | 1127 | _ = p.stack.pop(); |
| 1128 | p.state = State.ObjectKey; | 1128 | p.state = State.ObjectKey; |
| 1129 | }, | 1129 | }, |
| 1130 | Token.Id.Number => { | 1130 | Token.Id.Number => { |
| 1131 | _ = try object.put(key, try p.parseNumber(token, input, i)); | 1131 | _ = try object.put(key, try p.parseNumber(token, input, i)); |
| 1132 | p.stack_used -= 1; | 1132 | _ = p.stack.pop(); |
| 1133 | p.state = State.ObjectKey; | 1133 | p.state = State.ObjectKey; |
| 1134 | }, | 1134 | }, |
| 1135 | Token.Id.True => { | 1135 | Token.Id.True => { |
| 1136 | _ = try object.put(key, Value { .Bool = true }); | 1136 | _ = try object.put(key, Value { .Bool = true }); |
| 1137 | p.stack_used -= 1; | 1137 | _ = p.stack.pop(); |
| 1138 | p.state = State.ObjectKey; | 1138 | p.state = State.ObjectKey; |
| 1139 | }, | 1139 | }, |
| 1140 | Token.Id.False => { | 1140 | Token.Id.False => { |
| 1141 | _ = try object.put(key, Value { .Bool = false }); | 1141 | _ = try object.put(key, Value { .Bool = false }); |
| 1142 | p.stack_used -= 1; | 1142 | _ = p.stack.pop(); |
| 1143 | p.state = State.ObjectKey; | 1143 | p.state = State.ObjectKey; |
| 1144 | }, | 1144 | }, |
| 1145 | Token.Id.Null => { | 1145 | Token.Id.Null => { |
| 1146 | _ = try object.put(key, Value.Null); | 1146 | _ = try object.put(key, Value.Null); |
| 1147 | p.stack_used -= 1; | 1147 | _ = p.stack.pop(); |
| 1148 | p.state = State.ObjectKey; | 1148 | p.state = State.ObjectKey; |
| 1149 | }, | 1149 | }, |
| 1150 | else => { | 1150 | else => { |
| ... | @@ -1153,24 +1153,23 @@ const JsonParser = struct { | ... | @@ -1153,24 +1153,23 @@ const JsonParser = struct { |
| 1153 | } | 1153 | } |
| 1154 | }, | 1154 | }, |
| 1155 | State.ArrayValue => { | 1155 | State.ArrayValue => { |
| 1156 | var array = &p.stack[p.stack_used - 1].Array; | 1156 | var array = &p.stack.items[p.stack.len - 1].Array; |
| 1157 | | 1157 | |
| 1158 | switch (token.id) { | 1158 | switch (token.id) { |
| 1159 | Token.Id.ArrayEnd => { | 1159 | Token.Id.ArrayEnd => { |
| 1160 | if (p.stack_used == 1) { | 1160 | if (p.stack.len == 1) { |
| 1161 | return; | 1161 | return; |
| 1162 | } | 1162 | } |
| 1163 | | 1163 | |
| 1164 | var value = p.stack[p.stack_used - 1]; | 1164 | var value = p.stack.pop(); |
| 1165 | p.stack_used -= 1; | | |
| 1166 | try p.pushToParent(value); | 1165 | try p.pushToParent(value); |
| 1167 | }, | 1166 | }, |
| 1168 | Token.Id.ObjectBegin => { | 1167 | Token.Id.ObjectBegin => { |
| 1169 | p.pushStack(Value { .Object = ObjectMap.init(allocator) }); | 1168 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); |
| 1170 | p.state = State.ObjectKey; | 1169 | p.state = State.ObjectKey; |
| 1171 | }, | 1170 | }, |
| 1172 | Token.Id.ArrayBegin => { | 1171 | Token.Id.ArrayBegin => { |
| 1173 | p.pushStack(Value { .Array = ArrayList(Value).init(allocator) }); | 1172 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); |
| 1174 | p.state = State.ArrayValue; | 1173 | p.state = State.ArrayValue; |
| 1175 | }, | 1174 | }, |
| 1176 | Token.Id.String => { | 1175 | Token.Id.String => { |
| ... | @@ -1195,27 +1194,27 @@ const JsonParser = struct { | ... | @@ -1195,27 +1194,27 @@ const JsonParser = struct { |
| 1195 | }, | 1194 | }, |
| 1196 | State.Simple => switch (token.id) { | 1195 | State.Simple => switch (token.id) { |
| 1197 | Token.Id.ObjectBegin => { | 1196 | Token.Id.ObjectBegin => { |
| 1198 | p.pushStack(Value { .Object = ObjectMap.init(allocator) }); | 1197 | try p.stack.append(Value { .Object = ObjectMap.init(allocator) }); |
| 1199 | p.state = State.ObjectKey; | 1198 | p.state = State.ObjectKey; |
| 1200 | }, | 1199 | }, |
| 1201 | Token.Id.ArrayBegin => { | 1200 | Token.Id.ArrayBegin => { |
| 1202 | p.pushStack(Value { .Array = ArrayList(Value).init(allocator) }); | 1201 | try p.stack.append(Value { .Array = ArrayList(Value).init(allocator) }); |
| 1203 | p.state = State.ArrayValue; | 1202 | p.state = State.ArrayValue; |
| 1204 | }, | 1203 | }, |
| 1205 | Token.Id.String => { | 1204 | 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)); |
| 1207 | }, | 1206 | }, |
| 1208 | Token.Id.Number => { | 1207 | Token.Id.Number => { |
| 1209 | p.pushStack(try p.parseNumber(token, input, i)); | 1208 | try p.stack.append(try p.parseNumber(token, input, i)); |
| 1210 | }, | 1209 | }, |
| 1211 | Token.Id.True => { | 1210 | Token.Id.True => { |
| 1212 | p.pushStack(Value { .Bool = true }); | 1211 | try p.stack.append(Value { .Bool = true }); |
| 1213 | }, | 1212 | }, |
| 1214 | Token.Id.False => { | 1213 | Token.Id.False => { |
| 1215 | p.pushStack(Value { .Bool = false }); | 1214 | try p.stack.append(Value { .Bool = false }); |
| 1216 | }, | 1215 | }, |
| 1217 | Token.Id.Null => { | 1216 | Token.Id.Null => { |
| 1218 | p.pushStack(Value.Null); | 1217 | try p.stack.append(Value.Null); |
| 1219 | }, | 1218 | }, |
| 1220 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { | 1219 | Token.Id.ObjectEnd, Token.Id.ArrayEnd => { |
| 1221 | unreachable; | 1220 | unreachable; |
| ... | @@ -1225,12 +1224,12 @@ const JsonParser = struct { | ... | @@ -1225,12 +1224,12 @@ const JsonParser = struct { |
| 1225 | } | 1224 | } |
| 1226 | | 1225 | |
| 1227 | fn pushToParent(p: &JsonParser, value: &const Value) !void { | 1226 | 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)) { |
| 1229 | // Object Parent -> [ ..., object, <key>, value ] | 1228 | // Object Parent -> [ ..., object, <key>, value ] |
| 1230 | Value.String => |key| { | 1229 | Value.String => |key| { |
| 1231 | p.stack_used -= 1; | 1230 | _ = p.stack.pop(); |
| 1232 | | 1231 | |
| 1233 | var object = &p.stack[p.stack_used - 1].Object; | 1232 | var object = &p.stack.items[p.stack.len - 1].Object; |
| 1234 | _ = try object.put(key, value); | 1233 | _ = try object.put(key, value); |
| 1235 | p.state = State.ObjectKey; | 1234 | p.state = State.ObjectKey; |
| 1236 | }, | 1235 | }, |
| ... | @@ -1245,11 +1244,6 @@ const JsonParser = struct { | ... | @@ -1245,11 +1244,6 @@ const JsonParser = struct { |
| 1245 | } | 1244 | } |
| 1246 | } | 1245 | } |
| 1247 | | 1246 | |
| 1248 | fn pushStack(p: &JsonParser, value: &const Value) void { | | |
| 1249 | p.stack[p.stack_used] = *value; | | |
| 1250 | p.stack_used += 1; | | |
| 1251 | } | | |
| 1252 | | | |
| 1253 | fn parseString(p: &JsonParser, allocator: &Allocator, token: &const Token, input: []const u8, i: usize) !Value { | 1247 | fn parseString(p: &JsonParser, allocator: &Allocator, token: &const Token, input: []const u8, i: usize) !Value { |
| 1254 | // TODO: We don't strictly have to copy values which do not contain any escape | 1248 | // TODO: We don't strictly have to copy values which do not contain any escape |
| 1255 | // characters if flagged with the option. | 1249 | // characters if flagged with the option. |
| ... | @@ -1270,6 +1264,7 @@ const debug = std.debug; | ... | @@ -1270,6 +1264,7 @@ const debug = std.debug; |
| 1270 | | 1264 | |
| 1271 | test "json parser dynamic" { | 1265 | test "json parser dynamic" { |
| 1272 | var p = JsonParser.init(std.debug.global_allocator, false); | 1266 | var p = JsonParser.init(std.debug.global_allocator, false); |
| | 1267 | defer p.deinit(); |
| 1273 | | 1268 | |
| 1274 | const s = | 1269 | const s = |
| 1275 | \\{ | 1270 | \\{ |
| ... | @@ -1289,7 +1284,8 @@ test "json parser dynamic" { | ... | @@ -1289,7 +1284,8 @@ test "json parser dynamic" { |
| 1289 | ; | 1284 | ; |
| 1290 | | 1285 | |
| 1291 | var tree = try p.parse(s); | 1286 | var tree = try p.parse(s); |
| 1292 | tree.deinit(); | 1287 | defer tree.deinit(); |
| | 1288 | |
| 1293 | var root = tree.root; | 1289 | var root = tree.root; |
| 1294 | | 1290 | |
| 1295 | var image = (??root.Object.get("Image")).value; | 1291 | var image = (??root.Object.get("Image")).value; |