From 12d065c75120d68cb7dd8445be4620e003598d7d Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 31 Jul 2022 15:26:24 -0400 Subject: Provide a simpler QPDF::writeJSON --- TODO | 2 - include/qpdf/QPDF.hh | 32 +++++++++----- libqpdf/QPDF_json.cc | 25 +++++++++-- qpdf/qtest/qpdf-json.test | 6 +++ qpdf/qtest/qpdf/minimal-write-json.json | 75 +++++++++++++++++++++++++++++++++ qpdf/test_driver.cc | 11 ++++- 6 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 qpdf/qtest/qpdf/minimal-write-json.json diff --git a/TODO b/TODO index 38f0ea92..0a22ea5c 100644 --- a/TODO +++ b/TODO @@ -69,8 +69,6 @@ Soon: Break ground on "Document-level work" JSON v2 fixes ============= -* Rethink QPDF::writeJSON. Maybe provide a simpler overload? - * Support json v2 in the C API. At a minimum, write_json, create_from_json, and update_from_json need to be there and should take the same kinds of functions as the C API for logger. diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index f0a5f31c..fcc17522 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -134,16 +134,8 @@ class QPDF void updateFromJSON(std::shared_ptr); // Write qpdf JSON format to the pipeline "p". The only supported - // version is 2. - // - // If the value of "complete" is true, a complete JSON object - // containing only the "qpdf" key is written to the pipeline, and - // finish() is called on the pipeline at the end. If the value of - // "complete" is false, the "qpdf" key and its value are written - // to the pipeline assuming that a dictionary is already open, and - // finish() is not called. The parameter first_key indicates - // whether this is the first key in an in-progress dictionary. It - // will be set to false by writeJSON. + // version is 2. The finish() method is not called on the + // pipeline. // // The decode_level parameter controls which streams are // uncompressed in the JSON. Use qpdf_dl_none to preserve all @@ -165,6 +157,26 @@ class QPDF // output in memory, but do so with caution as this will allocate // enough memory to hold the entire PDF file. QPDF_DLL + void 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 wanted_objects); + + // This version of writeJSON enables writing only the "qpdf" key + // of an in-progress dictionary. If the value of "complete" is + // true, a complete JSON object containing only the "qpdf" key is + // written to the pipeline. If the value of "complete" is false, + // the "qpdf" key and its value are written to the pipeline + // assuming that a dictionary is already open. The parameter + // first_key indicates whether this is the first key in an + // in-progress dictionary. It will be set to false by writeJSON. + // The "qpdf" key and value are written as if at depth 1 in a + // prettified JSON output. Remaining arguments are the same as the + // above version. + QPDF_DLL void writeJSON( int version, Pipeline* p, diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index 213aa209..a3d50cfb 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -493,9 +493,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) } } else { QTC::TC("qpdf", "QPDF_json bad calledgetallpages"); - error( - value.getStart(), - "calledgetallpages must be a boolean"); + error(value.getStart(), "calledgetallpages must be a boolean"); } } else { // ignore unknown keys for forward compatibility and to @@ -821,6 +819,27 @@ QPDF::writeJSONObject( JSON::writeDictionaryItem(p, first, key, j, 3); } +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 wanted_objects) +{ + bool first = true; + writeJSON( + version, + p, + true, + first, + decode_level, + json_stream_data, + file_prefix, + wanted_objects); +} + void QPDF::writeJSON( int version, diff --git a/qpdf/qtest/qpdf-json.test b/qpdf/qtest/qpdf-json.test index 481cdca9..553a84e2 100644 --- a/qpdf/qtest/qpdf-json.test +++ b/qpdf/qtest/qpdf-json.test @@ -282,5 +282,11 @@ $td->runtest("check PDF (2)", {$td->FILE => "a.pdf"}, {$td->FILE => "duplicate-page-inherited-2-fixed.pdf"}); +$n_tests += 1; +$td->runtest("simple version of writeJSON", + {$td->COMMAND => "test_driver 91 minimal.pdf"}, + {$td->FILE => "minimal-write-json.json", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + cleanup(); $td->report($n_tests); diff --git a/qpdf/qtest/qpdf/minimal-write-json.json b/qpdf/qtest/qpdf/minimal-write-json.json new file mode 100644 index 00000000..7e86a841 --- /dev/null +++ b/qpdf/qtest/qpdf/minimal-write-json.json @@ -0,0 +1,75 @@ +{ + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 6 + }, + { + "obj:1 0 R": { + "value": { + "/Pages": "2 0 R", + "/Type": "/Catalog" + } + }, + "obj:2 0 R": { + "value": { + "/Count": 1, + "/Kids": [ + "3 0 R" + ], + "/Type": "/Pages" + } + }, + "obj:3 0 R": { + "value": { + "/Contents": "4 0 R", + "/MediaBox": [ + 0, + 0, + 612, + 792 + ], + "/Parent": "2 0 R", + "/Resources": { + "/Font": { + "/F1": "6 0 R" + }, + "/ProcSet": "5 0 R" + }, + "/Type": "/Page" + } + }, + "obj:4 0 R": { + "stream": { + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", + "dict": {} + } + }, + "obj:5 0 R": { + "value": [ + "/PDF", + "/Text" + ] + }, + "obj:6 0 R": { + "value": { + "/BaseFont": "/Helvetica", + "/Encoding": "/WinAnsiEncoding", + "/Name": "/F1", + "/Subtype": "/Type1", + "/Type": "/Font" + } + }, + "trailer": { + "value": { + "/Root": "1 0 R", + "/Size": 7 + } + } + } + ] +} +test 91 done diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 8378c8fa..aa4f9ce5 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3249,6 +3249,15 @@ test_90(QPDF& pdf, char const* arg2) pdf.getRoot().appendItem(QPDFObjectHandle::newNull()); } +static void +test_91(QPDF& pdf, char const* arg2) +{ + // Exercise the simpler version of writeJSON. + Pl_StdioFile p("stdout", stdout); + pdf.writeJSON( + 2, &p, qpdf_dl_none, qpdf_sj_inline, "", std::set()); +} + void runtest(int n, char const* filename1, char const* arg2) { @@ -3353,7 +3362,7 @@ runtest(int n, char const* filename1, char const* arg2) {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, {84, test_84}, {85, test_85}, {86, test_86}, {87, test_87}, - {88, test_88}, {89, test_89}, {90, test_90}}; + {88, test_88}, {89, test_89}, {90, test_90}, {91, test_91}}; auto fn = test_functions.find(n); if (fn == test_functions.end()) { -- cgit v1.2.3-54-g00ecf