aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF_json.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-05-19 00:22:57 +0200
committerJay Berkenbilt <ejb@ql.org>2022-05-20 15:16:25 +0200
commit6f43bf8de36b08c55b172b4f4133c79657651666 (patch)
treeec17bbf42d9ea78d44ab3b9d2cac363cc6b9bc68 /libqpdf/QPDF_json.cc
parent23fc6756f1894e1af35853eb2251f08d5b25cf30 (diff)
downloadqpdf-6f43bf8de36b08c55b172b4f4133c79657651666.tar.zst
Major rework -- see long comments
* Replace --create-from-json=file with --json-input, which causes the regular input to be treated as json. * Eliminate --to-json * In --json=2, bring back "objects" and eliminate "objectinfo". Stream data is never present. * In --json-output=2, write "qpdf-v2" with "objects" and include stream data.
Diffstat (limited to 'libqpdf/QPDF_json.cc')
-rw-r--r--libqpdf/QPDF_json.cc132
1 files changed, 114 insertions, 18 deletions
diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc
index 1037a2cf..c421ce41 100644
--- a/libqpdf/QPDF_json.cc
+++ b/libqpdf/QPDF_json.cc
@@ -2,6 +2,7 @@
#include <qpdf/FileInputSource.hh>
#include <qpdf/Pl_Base64.hh>
+#include <qpdf/Pl_StdioFile.hh>
#include <qpdf/QIntC.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>
@@ -13,7 +14,7 @@
// | st_initial
// { | -> st_top
-// "qpdf": { | -> st_qpdf
+// "qpdf-v2": { | -> st_qpdf
// "objects": { | -> st_objects
// "obj:1 0 R": { | -> st_object_top
// "value": { | -> st_object
@@ -93,7 +94,6 @@ QPDF::JSONReactor::JSONReactor(
parse_error(false),
saw_qpdf(false),
saw_objects(false),
- saw_json_version(false),
saw_pdf_version(false),
saw_trailer(false),
state(st_initial),
@@ -154,21 +154,17 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
QTC::TC("qpdf", "QPDF_json missing qpdf");
error(0, "\"qpdf\" object was not seen");
} else {
- if (!this->saw_json_version) {
- QTC::TC("qpdf", "QPDF_json missing json version");
- error(0, "\"qpdf.jsonversion\" was not seen");
- }
if (must_be_complete && !this->saw_pdf_version) {
QTC::TC("qpdf", "QPDF_json missing pdf version");
- error(0, "\"qpdf.pdfversion\" was not seen");
+ error(0, "\"qpdf-v2.pdfversion\" was not seen");
}
if (!this->saw_objects) {
QTC::TC("qpdf", "QPDF_json missing objects");
- error(0, "\"qpdf.objects\" was not seen");
+ error(0, "\"qpdf-v2.objects\" was not seen");
} else {
if (must_be_complete && !this->saw_trailer) {
QTC::TC("qpdf", "QPDF_json missing trailer");
- error(0, "\"qpdf.objects.trailer\" was not seen");
+ error(0, "\"qpdf-v2.objects.trailer\" was not seen");
}
}
}
@@ -279,7 +275,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
QTC::TC("qpdf", "QPDF_json ignoring in st_ignore");
// ignore
} else if (state == st_top) {
- if (key == "qpdf") {
+ if (key == "qpdf-v2") {
this->saw_qpdf = true;
nestedState(key, value, st_qpdf);
} else {
@@ -289,14 +285,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
next_state = st_ignore;
}
} else if (state == st_qpdf) {
- if (key == "jsonversion") {
- this->saw_json_version = true;
- std::string v;
- if (!(value.getNumber(v) && (v == "2"))) {
- QTC::TC("qpdf", "QPDF_json bad json version");
- error(value.getStart(), "only JSON version 2 is supported");
- }
- } else if (key == "pdfversion") {
+ if (key == "pdfversion") {
this->saw_pdf_version = true;
bool version_okay = false;
std::string v;
@@ -567,3 +556,110 @@ QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete)
// std::cout << oh.unparseResolved() << std::endl;
// }
}
+
+void
+QPDF::writeJSONStream(
+ int version,
+ Pipeline* p,
+ bool& first,
+ std::string const& key,
+ QPDFObjectHandle& obj,
+ qpdf_stream_decode_level_e decode_level,
+ qpdf_json_stream_data_e json_stream_data,
+ std::string const& file_prefix)
+{
+ Pipeline* stream_p = nullptr;
+ FILE* f = nullptr;
+ std::shared_ptr<Pl_StdioFile> f_pl;
+ std::string filename;
+ if (json_stream_data == qpdf_sj_file) {
+ filename = file_prefix + "-" + QUtil::int_to_string(obj.getObjectID());
+ f = QUtil::safe_fopen(filename.c_str(), "wb");
+ f_pl = std::make_shared<Pl_StdioFile>("stream data", f);
+ stream_p = f_pl.get();
+ }
+ auto j = JSON::makeDictionary();
+ j.addDictionaryMember(
+ "stream",
+ obj.getStreamJSON(
+ version, json_stream_data, decode_level, stream_p, filename));
+
+ JSON::writeDictionaryItem(p, first, key, j, 2);
+ if (f) {
+ f_pl->finish();
+ f_pl = nullptr;
+ fclose(f);
+ }
+}
+
+void
+QPDF::writeJSONObject(
+ int version,
+ Pipeline* p,
+ bool& first,
+ std::string const& key,
+ QPDFObjectHandle& obj)
+{
+ auto j = JSON::makeDictionary();
+ j.addDictionaryMember("value", obj.getJSON(version, true));
+ JSON::writeDictionaryItem(p, first, key, j, 2);
+}
+
+void
+QPDF::writeJSON(
+ int version,
+ Pipeline* p,
+ qpdf_stream_decode_level_e decode_level,
+ qpdf_json_stream_data_e json_stream_data,
+ std::string const& file_prefix,
+ std::set<std::string> wanted_objects)
+{
+ if (version != 2) {
+ throw std::runtime_error(
+ "QPDF::writeJSON: only version 2 is supported");
+ }
+ bool first = true;
+ JSON::writeDictionaryOpen(p, first, 0);
+ JSON::writeDictionaryKey(p, first, "qpdf-v2", 0);
+ bool first_qpdf = true;
+ JSON::writeDictionaryOpen(p, first_qpdf, 1);
+ JSON::writeDictionaryItem(
+ p, first_qpdf, "pdfversion", JSON::makeString(getPDFVersion()), 1);
+ JSON::writeDictionaryItem(
+ p,
+ first_qpdf,
+ "maxobjectid",
+ JSON::makeInt(QIntC::to_longlong(getObjectCount())),
+ 1);
+ JSON::writeDictionaryKey(p, first_qpdf, "objects", 1);
+ bool first_object = true;
+ JSON::writeDictionaryOpen(p, first_object, 2);
+ bool all_objects = wanted_objects.empty();
+ std::vector<QPDFObjectHandle> objects = getAllObjects();
+ for (auto& obj: objects) {
+ std::string key = "obj:" + obj.unparse();
+ if (all_objects || wanted_objects.count(key)) {
+ if (obj.isStream()) {
+ writeJSONStream(
+ version,
+ p,
+ first_object,
+ key,
+ obj,
+ decode_level,
+ json_stream_data,
+ file_prefix);
+ } else {
+ writeJSONObject(version, p, first_object, key, obj);
+ }
+ }
+ }
+ if (all_objects || wanted_objects.count("trailer")) {
+ auto trailer = getTrailer();
+ writeJSONObject(version, p, first_object, "trailer", trailer);
+ }
+ JSON::writeDictionaryClose(p, first_object, 2);
+ JSON::writeDictionaryClose(p, first_qpdf, 1);
+ JSON::writeDictionaryClose(p, first, 0);
+ *p << "\n";
+}