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