Commit ae9455bf449a22329507efd01455d5e9322cf134

Authored by Jay Berkenbilt
1 parent ce714ac9

Implement --json-objects

Showing 1 changed file with 60 additions and 19 deletions
qpdf/qpdf.cc
... ... @@ -195,6 +195,7 @@ struct Options
195 195 bool show_page_images;
196 196 bool json;
197 197 std::set<std::string> json_keys;
  198 + std::set<std::string> json_objects;
198 199 bool check;
199 200 std::vector<PageSpec> page_specs;
200 201 std::map<std::string, RotationSpec> rotations;
... ... @@ -344,6 +345,26 @@ static JSON json_schema(std::set&lt;std::string&gt;* keys = 0)
344 345 return schema;
345 346 }
346 347  
  348 +static void parse_object_id(std::string const& objspec,
  349 + bool& trailer, int& obj, int& gen)
  350 +{
  351 + if (objspec == "trailer")
  352 + {
  353 + trailer = true;
  354 + }
  355 + else
  356 + {
  357 + trailer = false;
  358 + obj = QUtil::string_to_int(objspec.c_str());
  359 + size_t comma = objspec.find(',');
  360 + if ((comma != std::string::npos) && (comma + 1 < objspec.length()))
  361 + {
  362 + gen = QUtil::string_to_int(
  363 + objspec.substr(1 + comma, std::string::npos).c_str());
  364 + }
  365 + }
  366 +}
  367 +
347 368 // This is not a general-purpose argument parser. It is tightly
348 369 // crafted to work with qpdf. qpdf's command-line syntax is very
349 370 // complex because of its long history, and it doesn't really follow
... ... @@ -437,6 +458,7 @@ class ArgParser
437 458 void argWithImages();
438 459 void argJson();
439 460 void argJsonKey(char* parameter);
  461 + void argJsonObject(char* parameter);
440 462 void argCheck();
441 463 void arg40Print(char* parameter);
442 464 void arg40Modify(char* parameter);
... ... @@ -638,6 +660,8 @@ ArgParser::initOptionTable()
638 660 char const* jsonKeyChoices[] = {"objects", "pages", "pagelabels", 0};
639 661 (*t)["json-key"] = oe_requiredChoices(
640 662 &ArgParser::argJsonKey, jsonKeyChoices);
  663 + (*t)["json-object"] = oe_requiredParameter(
  664 + &ArgParser::argJsonObject, "trailer|obj[,gen]");
641 665 (*t)["check"] = oe_bare(&ArgParser::argCheck);
642 666  
643 667 t = &this->encrypt40_option_table;
... ... @@ -1143,21 +1167,7 @@ ArgParser::argShowXref()
1143 1167 void
1144 1168 ArgParser::argShowObject(char* parameter)
1145 1169 {
1146   - if (strcmp(parameter, "trailer") == 0)
1147   - {
1148   - o.show_trailer = true;
1149   - }
1150   - else
1151   - {
1152   - char* obj = parameter;
1153   - char* gen = obj;
1154   - if ((gen = strchr(obj, ',')) != 0)
1155   - {
1156   - *gen++ = 0;
1157   - o.show_gen = QUtil::string_to_int(gen);
1158   - }
1159   - o.show_obj = QUtil::string_to_int(obj);
1160   - }
  1170 + parse_object_id(parameter, o.show_trailer, o.show_obj, o.show_gen);
1161 1171 o.require_outfile = false;
1162 1172 }
1163 1173  
... ... @@ -1207,6 +1217,12 @@ ArgParser::argJsonKey(char* parameter)
1207 1217 }
1208 1218  
1209 1219 void
  1220 +ArgParser::argJsonObject(char* parameter)
  1221 +{
  1222 + o.json_objects.insert(parameter);
  1223 +}
  1224 +
  1225 +void
1210 1226 ArgParser::argCheck()
1211 1227 {
1212 1228 o.check = true;
... ... @@ -1691,7 +1707,11 @@ automated test suites for software that uses the qpdf library.\n\
1691 1707 --json generate a json representation of the file\n\
1692 1708 --json-help describe the format of the json representation\n\
1693 1709 --json-key=key repeatable; prune json structure to include only\n\
1694   - specified keys\n\
  1710 + specified keys. If absent, all keys are shown\n\
  1711 +--json-object=trailer|[obj,gen]\n\
  1712 + repeatable; include only specified objects in the\n\
  1713 + \"objects\" section of the json. If absent, all\n\
  1714 + objects are shown\n\
1695 1715 \n\
1696 1716 The json representation generated by qpdf is designed to facilitate\n\
1697 1717 processing of qpdf from other programming languages that have a hard\n\
... ... @@ -2586,14 +2606,35 @@ static void do_json_objects(QPDF&amp; pdf, Options&amp; o, JSON&amp; j)
2586 2606 // Add all objects. Do this first before other code below modifies
2587 2607 // things by doing stuff like calling
2588 2608 // pushInheritedAttributesToPage.
  2609 + bool all_objects = o.json_objects.empty();
  2610 + std::set<QPDFObjGen> wanted_og;
  2611 + for (std::set<std::string>::iterator iter = o.json_objects.begin();
  2612 + iter != o.json_objects.end(); ++iter)
  2613 + {
  2614 + bool trailer;
  2615 + int obj = 0;
  2616 + int gen = 0;
  2617 + parse_object_id(*iter, trailer, obj, gen);
  2618 + if (obj)
  2619 + {
  2620 + wanted_og.insert(QPDFObjGen(obj, gen));
  2621 + }
  2622 + }
2589 2623 JSON j_objects = j.addDictionaryMember("objects", JSON::makeDictionary());
2590   - j_objects.addDictionaryMember("trailer", pdf.getTrailer().getJSON(true));
  2624 + if (all_objects || o.json_objects.count("trailer"))
  2625 + {
  2626 + j_objects.addDictionaryMember(
  2627 + "trailer", pdf.getTrailer().getJSON(true));
  2628 + }
2591 2629 std::vector<QPDFObjectHandle> objects = pdf.getAllObjects();
2592 2630 for (std::vector<QPDFObjectHandle>::iterator iter = objects.begin();
2593 2631 iter != objects.end(); ++iter)
2594 2632 {
2595   - j_objects.addDictionaryMember(
2596   - (*iter).unparse(), (*iter).getJSON(true));
  2633 + if (all_objects || wanted_og.count((*iter).getObjGen()))
  2634 + {
  2635 + j_objects.addDictionaryMember(
  2636 + (*iter).unparse(), (*iter).getJSON(true));
  2637 + }
2597 2638 }
2598 2639 }
2599 2640  
... ...