2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-24 07:38:28 +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 show_page_images;
bool json; bool json;
std::set<std::string> json_keys; std::set<std::string> json_keys;
std::set<std::string> json_objects;
bool check; bool check;
std::vector<PageSpec> page_specs; std::vector<PageSpec> page_specs;
std::map<std::string, RotationSpec> rotations; std::map<std::string, RotationSpec> rotations;
@ -344,6 +345,26 @@ static JSON json_schema(std::set<std::string>* keys = 0)
return schema; 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 // This is not a general-purpose argument parser. It is tightly
// crafted to work with qpdf. qpdf's command-line syntax is very // crafted to work with qpdf. qpdf's command-line syntax is very
// complex because of its long history, and it doesn't really follow // complex because of its long history, and it doesn't really follow
@ -437,6 +458,7 @@ class ArgParser
void argWithImages(); void argWithImages();
void argJson(); void argJson();
void argJsonKey(char* parameter); void argJsonKey(char* parameter);
void argJsonObject(char* parameter);
void argCheck(); void argCheck();
void arg40Print(char* parameter); void arg40Print(char* parameter);
void arg40Modify(char* parameter); void arg40Modify(char* parameter);
@ -638,6 +660,8 @@ ArgParser::initOptionTable()
char const* jsonKeyChoices[] = {"objects", "pages", "pagelabels", 0}; char const* jsonKeyChoices[] = {"objects", "pages", "pagelabels", 0};
(*t)["json-key"] = oe_requiredChoices( (*t)["json-key"] = oe_requiredChoices(
&ArgParser::argJsonKey, jsonKeyChoices); &ArgParser::argJsonKey, jsonKeyChoices);
(*t)["json-object"] = oe_requiredParameter(
&ArgParser::argJsonObject, "trailer|obj[,gen]");
(*t)["check"] = oe_bare(&ArgParser::argCheck); (*t)["check"] = oe_bare(&ArgParser::argCheck);
t = &this->encrypt40_option_table; t = &this->encrypt40_option_table;
@ -1143,21 +1167,7 @@ ArgParser::argShowXref()
void void
ArgParser::argShowObject(char* parameter) ArgParser::argShowObject(char* parameter)
{ {
if (strcmp(parameter, "trailer") == 0) parse_object_id(parameter, o.show_trailer, o.show_obj, o.show_gen);
{
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);
}
o.require_outfile = false; o.require_outfile = false;
} }
@ -1206,6 +1216,12 @@ ArgParser::argJsonKey(char* parameter)
o.json_keys.insert(parameter); o.json_keys.insert(parameter);
} }
void
ArgParser::argJsonObject(char* parameter)
{
o.json_objects.insert(parameter);
}
void void
ArgParser::argCheck() 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 generate a json representation of the file\n\
--json-help describe the format of the json representation\n\ --json-help describe the format of the json representation\n\
--json-key=key repeatable; prune json structure to include only\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\ \n\
The json representation generated by qpdf is designed to facilitate\n\ The json representation generated by qpdf is designed to facilitate\n\
processing of qpdf from other programming languages that have a hard\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 // Add all objects. Do this first before other code below modifies
// things by doing stuff like calling // things by doing stuff like calling
// pushInheritedAttributesToPage. // 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()); 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(); std::vector<QPDFObjectHandle> objects = pdf.getAllObjects();
for (std::vector<QPDFObjectHandle>::iterator iter = objects.begin(); for (std::vector<QPDFObjectHandle>::iterator iter = objects.begin();
iter != objects.end(); ++iter) iter != objects.end(); ++iter)
{ {
j_objects.addDictionaryMember( if (all_objects || wanted_og.count((*iter).getObjGen()))
(*iter).unparse(), (*iter).getJSON(true)); {
j_objects.addDictionaryMember(
(*iter).unparse(), (*iter).getJSON(true));
}
} }
} }