From ae9455bf449a22329507efd01455d5e9322cf134 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 22 Dec 2018 10:52:06 -0500 Subject: Implement --json-objects --- qpdf/qpdf.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 6cae61f1..acb2a948 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -195,6 +195,7 @@ struct Options bool show_page_images; bool json; std::set json_keys; + std::set json_objects; bool check; std::vector page_specs; std::map rotations; @@ -344,6 +345,26 @@ static JSON json_schema(std::set* keys = 0) return schema; } +static void parse_object_id(std::string const& objspec, + bool& trailer, int& obj, int& gen) +{ + if (objspec == "trailer") + { + trailer = true; + } + else + { + trailer = false; + obj = QUtil::string_to_int(objspec.c_str()); + size_t comma = objspec.find(','); + if ((comma != std::string::npos) && (comma + 1 < objspec.length())) + { + gen = QUtil::string_to_int( + objspec.substr(1 + comma, std::string::npos).c_str()); + } + } +} + // This is not a general-purpose argument parser. It is tightly // crafted to work with qpdf. qpdf's command-line syntax is very // complex because of its long history, and it doesn't really follow @@ -437,6 +458,7 @@ class ArgParser void argWithImages(); void argJson(); void argJsonKey(char* parameter); + void argJsonObject(char* parameter); void argCheck(); void arg40Print(char* parameter); void arg40Modify(char* parameter); @@ -638,6 +660,8 @@ ArgParser::initOptionTable() char const* jsonKeyChoices[] = {"objects", "pages", "pagelabels", 0}; (*t)["json-key"] = oe_requiredChoices( &ArgParser::argJsonKey, jsonKeyChoices); + (*t)["json-object"] = oe_requiredParameter( + &ArgParser::argJsonObject, "trailer|obj[,gen]"); (*t)["check"] = oe_bare(&ArgParser::argCheck); t = &this->encrypt40_option_table; @@ -1143,21 +1167,7 @@ ArgParser::argShowXref() void ArgParser::argShowObject(char* parameter) { - if (strcmp(parameter, "trailer") == 0) - { - o.show_trailer = true; - } - else - { - char* obj = parameter; - char* gen = obj; - if ((gen = strchr(obj, ',')) != 0) - { - *gen++ = 0; - o.show_gen = QUtil::string_to_int(gen); - } - o.show_obj = QUtil::string_to_int(obj); - } + parse_object_id(parameter, o.show_trailer, o.show_obj, o.show_gen); o.require_outfile = false; } @@ -1206,6 +1216,12 @@ ArgParser::argJsonKey(char* parameter) o.json_keys.insert(parameter); } +void +ArgParser::argJsonObject(char* parameter) +{ + o.json_objects.insert(parameter); +} + void ArgParser::argCheck() { @@ -1691,7 +1707,11 @@ automated test suites for software that uses the qpdf library.\n\ --json generate a json representation of the file\n\ --json-help describe the format of the json representation\n\ --json-key=key repeatable; prune json structure to include only\n\ - specified keys\n\ + specified keys. If absent, all keys are shown\n\ +--json-object=trailer|[obj,gen]\n\ + repeatable; include only specified objects in the\n\ + \"objects\" section of the json. If absent, all\n\ + objects are shown\n\ \n\ The json representation generated by qpdf is designed to facilitate\n\ processing of qpdf from other programming languages that have a hard\n\ @@ -2586,14 +2606,35 @@ static void do_json_objects(QPDF& pdf, Options& o, JSON& j) // Add all objects. Do this first before other code below modifies // things by doing stuff like calling // pushInheritedAttributesToPage. + bool all_objects = o.json_objects.empty(); + std::set wanted_og; + for (std::set::iterator iter = o.json_objects.begin(); + iter != o.json_objects.end(); ++iter) + { + bool trailer; + int obj = 0; + int gen = 0; + parse_object_id(*iter, trailer, obj, gen); + if (obj) + { + wanted_og.insert(QPDFObjGen(obj, gen)); + } + } JSON j_objects = j.addDictionaryMember("objects", JSON::makeDictionary()); - j_objects.addDictionaryMember("trailer", pdf.getTrailer().getJSON(true)); + if (all_objects || o.json_objects.count("trailer")) + { + j_objects.addDictionaryMember( + "trailer", pdf.getTrailer().getJSON(true)); + } std::vector objects = pdf.getAllObjects(); for (std::vector::iterator iter = objects.begin(); iter != objects.end(); ++iter) { - j_objects.addDictionaryMember( - (*iter).unparse(), (*iter).getJSON(true)); + if (all_objects || wanted_og.count((*iter).getObjGen())) + { + j_objects.addDictionaryMember( + (*iter).unparse(), (*iter).getJSON(true)); + } } } -- cgit v1.2.3-54-g00ecf