2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-05 03:40:53 +00:00

Implement --json-objects

This commit is contained in:
Jay Berkenbilt 2018-12-22 10:52:06 -05:00
parent ce714ac9b8
commit ae9455bf44

View File

@ -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;
}
@ -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<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));
}
}
}