Commit 126dd31cad27991d40805df9582d5546464310c1

Authored by m-holger
1 parent 6748bd33

In JSONParser combine stacks

Showing 1 changed file with 20 additions and 12 deletions
libqpdf/JSON.cc
... ... @@ -661,6 +661,18 @@ namespace
661 661 ls_comma,
662 662 };
663 663  
  664 + struct StackFrame
  665 + {
  666 + StackFrame(parser_state_e state, std::shared_ptr<JSON>& item) :
  667 + state(state),
  668 + item(item)
  669 + {
  670 + }
  671 +
  672 + parser_state_e state;
  673 + std::shared_ptr<JSON> item;
  674 + };
  675 +
664 676 InputSource& is;
665 677 JSON::Reactor* reactor;
666 678 lex_state_e lex_state;
... ... @@ -673,8 +685,7 @@ namespace
673 685 std::string token;
674 686 qpdf_offset_t token_start{0};
675 687 parser_state_e parser_state;
676   - std::vector<std::shared_ptr<JSON>> stack;
677   - std::vector<parser_state_e> ps_stack;
  688 + std::vector<StackFrame> stack;
678 689 std::string dict_key;
679 690 qpdf_offset_t dict_key_offset;
680 691 };
... ... @@ -1137,7 +1148,7 @@ JSONParser::handleToken()
1137 1148  
1138 1149 std::string s_value;
1139 1150 std::shared_ptr<JSON> item;
1140   - auto tos = stack.empty() ? nullptr : stack.back();
  1151 + auto tos = stack.empty() ? nullptr : stack.back().item;
1141 1152 auto ls = lex_state;
1142 1153 lex_state = ls_top;
1143 1154  
... ... @@ -1186,8 +1197,7 @@ JSONParser::handleToken()
1186 1197 "JSON: offset " + std::to_string(offset) +
1187 1198 ": unexpected array end delimiter");
1188 1199 }
1189   - parser_state = ps_stack.back();
1190   - ps_stack.pop_back();
  1200 + parser_state = stack.back().state;
1191 1201 tos->setEnd(offset);
1192 1202 if (reactor) {
1193 1203 reactor->containerEnd(*tos);
... ... @@ -1205,8 +1215,7 @@ JSONParser::handleToken()
1205 1215 "JSON: offset " + std::to_string(offset) +
1206 1216 ": unexpected dictionary end delimiter");
1207 1217 }
1208   - parser_state = ps_stack.back();
1209   - ps_stack.pop_back();
  1218 + parser_state = stack.back().state;
1210 1219 tos->setEnd(offset);
1211 1220 if (reactor) {
1212 1221 reactor->containerEnd(*tos);
... ... @@ -1293,7 +1302,7 @@ JSONParser::handleToken()
1293 1302  
1294 1303 case ps_top:
1295 1304 if (!(item->isDictionary() || item->isArray())) {
1296   - stack.push_back(item);
  1305 + stack.push_back({ps_done, item});
1297 1306 parser_state = ps_done;
1298 1307 return;
1299 1308 }
... ... @@ -1324,8 +1333,7 @@ JSONParser::handleToken()
1324 1333 }
1325 1334  
1326 1335 if (item->isDictionary() || item->isArray()) {
1327   - stack.push_back(item);
1328   - ps_stack.push_back(parser_state);
  1336 + stack.push_back({parser_state, item});
1329 1337 // Calling container start method is postponed until after
1330 1338 // adding the containers to their parent containers, if any.
1331 1339 // This makes it much easier to keep track of the current
... ... @@ -1342,7 +1350,7 @@ JSONParser::handleToken()
1342 1350 parser_state = ps_array_begin;
1343 1351 }
1344 1352  
1345   - if (ps_stack.size() > 500) {
  1353 + if (stack.size() > 500) {
1346 1354 throw std::runtime_error(
1347 1355 "JSON: offset " + std::to_string(offset) +
1348 1356 ": maximum object depth exceeded");
... ... @@ -1361,7 +1369,7 @@ JSONParser::parse()
1361 1369 QTC::TC("libtests", "JSON parse premature EOF");
1362 1370 throw std::runtime_error("JSON: premature end of input");
1363 1371 }
1364   - auto const& tos = stack.back();
  1372 + auto const& tos = stack.back().item;
1365 1373 if (reactor && tos.get() && !(tos->isArray() || tos->isDictionary())) {
1366 1374 reactor->topLevelScalar();
1367 1375 }
... ...