Commit b6f048546f7ffdd228bd9360c647b3064dfa1bf3

Authored by m-holger
1 parent f6c90195

Eliminate the use of shared pointers in JSONParser

include/qpdf/JSON.hh
... ... @@ -54,6 +54,7 @@ class JSON
54 54 {
55 55 public:
56 56 static int constexpr LATEST = 2;
  57 + JSON() = default;
57 58  
58 59 QPDF_DLL
59 60 std::string unparse() const;
... ...
libqpdf/JSON.cc
... ... @@ -602,7 +602,7 @@ namespace
602 602 {
603 603 }
604 604  
605   - std::shared_ptr<JSON> parse();
  605 + JSON parse();
606 606  
607 607 private:
608 608 enum parser_state_e {
... ... @@ -642,14 +642,14 @@ namespace
642 642  
643 643 struct StackFrame
644 644 {
645   - StackFrame(parser_state_e state, std::shared_ptr<JSON>& item) :
  645 + StackFrame(parser_state_e state, JSON& item) :
646 646 state(state),
647 647 item(item)
648 648 {
649 649 }
650 650  
651 651 parser_state_e state;
652   - std::shared_ptr<JSON> item;
  652 + JSON item;
653 653 };
654 654  
655 655 void getToken();
... ... @@ -860,6 +860,7 @@ JSONParser::getToken()
860 860 } else {
861 861 break;
862 862 }
  863 +
863 864 } else {
864 865 QTC::TC("libtests", "JSON parse null character");
865 866 throw std::runtime_error(
... ... @@ -1169,18 +1170,19 @@ JSONParser::handleToken()
1169 1170 ": material follows end of object: " + token);
1170 1171 }
1171 1172  
1172   - std::shared_ptr<JSON> item;
1173   - auto tos = stack.empty() ? nullptr : stack.back().item;
  1173 + const static JSON null_item = JSON::makeNull();
  1174 + JSON item;
  1175 + auto tos = stack.empty() ? null_item : stack.back().item;
1174 1176 auto ls = lex_state;
1175 1177 lex_state = ls_top;
1176 1178  
1177 1179 switch (ls) {
1178 1180 case ls_begin_dict:
1179   - item = std::make_shared<JSON>(JSON::makeDictionary());
  1181 + item = JSON::makeDictionary();
1180 1182 break;
1181 1183  
1182 1184 case ls_begin_array:
1183   - item = std::make_shared<JSON>(JSON::makeArray());
  1185 + item = JSON::makeArray();
1184 1186 break;
1185 1187  
1186 1188 case ls_colon:
... ... @@ -1220,9 +1222,9 @@ JSONParser::handleToken()
1220 1222 ": unexpected array end delimiter");
1221 1223 }
1222 1224 parser_state = stack.back().state;
1223   - tos->setEnd(offset);
  1225 + tos.setEnd(offset);
1224 1226 if (reactor) {
1225   - reactor->containerEnd(*tos);
  1227 + reactor->containerEnd(tos);
1226 1228 }
1227 1229 if (parser_state != ps_done) {
1228 1230 stack.pop_back();
... ... @@ -1238,9 +1240,9 @@ JSONParser::handleToken()
1238 1240 ": unexpected dictionary end delimiter");
1239 1241 }
1240 1242 parser_state = stack.back().state;
1241   - tos->setEnd(offset);
  1243 + tos.setEnd(offset);
1242 1244 if (reactor) {
1243   - reactor->containerEnd(*tos);
  1245 + reactor->containerEnd(tos);
1244 1246 }
1245 1247 if (parser_state != ps_done) {
1246 1248 stack.pop_back();
... ... @@ -1248,16 +1250,16 @@ JSONParser::handleToken()
1248 1250 return;
1249 1251  
1250 1252 case ls_number:
1251   - item = std::make_shared<JSON>(JSON::makeNumber(token));
  1253 + item = JSON::makeNumber(token);
1252 1254 break;
1253 1255  
1254 1256 case ls_alpha:
1255 1257 if (token == "true") {
1256   - item = std::make_shared<JSON>(JSON::makeBool(true));
  1258 + item = JSON::makeBool(true);
1257 1259 } else if (token == "false") {
1258   - item = std::make_shared<JSON>(JSON::makeBool(false));
  1260 + item = JSON::makeBool(false);
1259 1261 } else if (token == "null") {
1260   - item = std::make_shared<JSON>(JSON::makeNull());
  1262 + item = JSON::makeNull();
1261 1263 } else {
1262 1264 QTC::TC("libtests", "JSON parse invalid keyword");
1263 1265 throw std::runtime_error(
... ... @@ -1274,7 +1276,7 @@ JSONParser::handleToken()
1274 1276 parser_state = ps_dict_after_key;
1275 1277 return;
1276 1278 } else {
1277   - item = std::make_shared<JSON>(JSON::makeString(token));
  1279 + item = JSON::makeString(token);
1278 1280 }
1279 1281 break;
1280 1282  
... ... @@ -1284,8 +1286,8 @@ JSONParser::handleToken()
1284 1286 break;
1285 1287 }
1286 1288  
1287   - item->setStart(token_start);
1288   - item->setEnd(offset);
  1289 + item.setStart(token_start);
  1290 + item.setEnd(offset);
1289 1291  
1290 1292 switch (parser_state) {
1291 1293 case ps_dict_begin:
... ... @@ -1297,28 +1299,28 @@ JSONParser::handleToken()
1297 1299 break;
1298 1300  
1299 1301 case ps_dict_after_colon:
1300   - if (tos->checkDictionaryKeySeen(dict_key)) {
  1302 + if (tos.checkDictionaryKeySeen(dict_key)) {
1301 1303 QTC::TC("libtests", "JSON parse duplicate key");
1302 1304 throw std::runtime_error(
1303 1305 "JSON: offset " + std::to_string(dict_key_offset) +
1304 1306 ": duplicated dictionary key");
1305 1307 }
1306   - if (!reactor || !reactor->dictionaryItem(dict_key, *item)) {
1307   - tos->addDictionaryMember(dict_key, *item);
  1308 + if (!reactor || !reactor->dictionaryItem(dict_key, item)) {
  1309 + tos.addDictionaryMember(dict_key, item);
1308 1310 }
1309 1311 parser_state = ps_dict_after_item;
1310 1312 break;
1311 1313  
1312 1314 case ps_array_begin:
1313 1315 case ps_array_after_comma:
1314   - if (!reactor || !reactor->arrayItem(*item)) {
1315   - tos->addArrayElement(*item);
  1316 + if (!reactor || !reactor->arrayItem(item)) {
  1317 + tos.addArrayElement(item);
1316 1318 }
1317 1319 parser_state = ps_array_after_item;
1318 1320 break;
1319 1321  
1320 1322 case ps_top:
1321   - if (!(item->isDictionary() || item->isArray())) {
  1323 + if (!(item.isDictionary() || item.isArray())) {
1322 1324 stack.push_back({ps_done, item});
1323 1325 parser_state = ps_done;
1324 1326 return;
... ... @@ -1349,18 +1351,18 @@ JSONParser::handleToken()
1349 1351 "JSONParser::handleToken: unexpected parser state");
1350 1352 }
1351 1353  
1352   - if (item->isDictionary() || item->isArray()) {
  1354 + if (item.isDictionary() || item.isArray()) {
1353 1355 stack.push_back({parser_state, item});
1354 1356 // Calling container start method is postponed until after
1355 1357 // adding the containers to their parent containers, if any.
1356 1358 // This makes it much easier to keep track of the current
1357 1359 // nesting level.
1358   - if (item->isDictionary()) {
  1360 + if (item.isDictionary()) {
1359 1361 if (reactor) {
1360 1362 reactor->dictionaryStart();
1361 1363 }
1362 1364 parser_state = ps_dict_begin;
1363   - } else if (item->isArray()) {
  1365 + } else if (item.isArray()) {
1364 1366 if (reactor) {
1365 1367 reactor->arrayStart();
1366 1368 }
... ... @@ -1375,7 +1377,7 @@ JSONParser::handleToken()
1375 1377 }
1376 1378 }
1377 1379  
1378   -std::shared_ptr<JSON>
  1380 +JSON
1379 1381 JSONParser::parse()
1380 1382 {
1381 1383 while (!done) {
... ... @@ -1387,7 +1389,7 @@ JSONParser::parse()
1387 1389 throw std::runtime_error("JSON: premature end of input");
1388 1390 }
1389 1391 auto const& tos = stack.back().item;
1390   - if (reactor && tos.get() && !(tos->isArray() || tos->isDictionary())) {
  1392 + if (reactor && !(tos.isArray() || tos.isDictionary())) {
1391 1393 reactor->topLevelScalar();
1392 1394 }
1393 1395 return tos;
... ... @@ -1397,7 +1399,7 @@ JSON
1397 1399 JSON::parse(InputSource& is, Reactor* reactor)
1398 1400 {
1399 1401 JSONParser jp(is, reactor);
1400   - return *jp.parse();
  1402 + return jp.parse();
1401 1403 }
1402 1404  
1403 1405 JSON
... ... @@ -1405,7 +1407,7 @@ JSON::parse(std::string const&amp; s)
1405 1407 {
1406 1408 BufferInputSource bis("json input", s);
1407 1409 JSONParser jp(bis, nullptr);
1408   - return *jp.parse();
  1410 + return jp.parse();
1409 1411 }
1410 1412  
1411 1413 void
... ...