aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2018-12-22 16:52:06 +0100
committerJay Berkenbilt <ejb@ql.org>2018-12-22 17:42:38 +0100
commitae9455bf449a22329507efd01455d5e9322cf134 (patch)
tree980588e84f86393e9e0dfb15227ca3d4cadb70ae
parentce714ac9b87b6fa877e3f81e7eb2357f4170021c (diff)
downloadqpdf-ae9455bf449a22329507efd01455d5e9322cf134.tar.zst
Implement --json-objects
-rw-r--r--qpdf/qpdf.cc79
1 files 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<std::string> json_keys;
+ std::set<std::string> json_objects;
bool check;
std::vector<PageSpec> page_specs;
std::map<std::string, RotationSpec> rotations;
@@ -344,6 +345,26 @@ static JSON json_schema(std::set<std::string>* 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;
}
@@ -1207,6 +1217,12 @@ ArgParser::argJsonKey(char* parameter)
}
void
+ArgParser::argJsonObject(char* parameter)
+{
+ o.json_objects.insert(parameter);
+}
+
+void
ArgParser::argCheck()
{
o.check = true;
@@ -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<QPDFObjGen> wanted_og;
+ for (std::set<std::string>::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<QPDFObjectHandle> objects = pdf.getAllObjects();
for (std::vector<QPDFObjectHandle>::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));
+ }
}
}