From a2edf27b76cf68474190229dad904ca661e9bb42 Mon Sep 17 00:00:00 2001 From: m-holger Date: Tue, 21 Mar 2023 16:18:28 +0000 Subject: Initialize _qpdf_data members --- libqpdf/qpdf-c.cc | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index cb104c73..7feabd1c 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -27,7 +27,7 @@ struct _qpdf_error struct _qpdf_data { - _qpdf_data(); + _qpdf_data() = default; ~_qpdf_data() = default; std::shared_ptr qpdf; @@ -39,31 +39,23 @@ struct _qpdf_data std::string tmp_string; // Parameters for functions we call - char const* filename; // or description - char const* buffer; - unsigned long long size; - char const* password; - bool write_memory; + char const* filename{nullptr}; // or description + char const* buffer{nullptr}; + unsigned long long size{0}; + char const* password{nullptr}; + bool write_memory{false}; std::shared_ptr output_buffer; // QPDFObjectHandle support - bool silence_errors; - bool oh_error_occurred; + bool silence_errors{false}; + bool oh_error_occurred{false}; std::map> oh_cache; - qpdf_oh next_oh; + qpdf_oh next_oh{0}; std::set cur_iter_dict_keys; std::set::const_iterator dict_iter; std::string cur_dict_key; }; -_qpdf_data::_qpdf_data() : - write_memory(false), - silence_errors(false), - oh_error_occurred(false), - next_oh(0) -{ -} - // must set qpdf->filename and qpdf->password static void call_read(qpdf_data qpdf) -- cgit v1.2.3-54-g00ecf From c78f44798a0b07e7a585c85c7b8bcc1907542cd4 Mon Sep 17 00:00:00 2001 From: m-holger Date: Tue, 21 Mar 2023 16:28:07 +0000 Subject: Add new _qpdf_data constructor taking a std::unique_ptr Also, move _qpdf_data and to new header filer _qpdf_error to new header file qpdf-c_impl.hh --- libqpdf/qpdf-c.cc | 37 +---------------------------------- libqpdf/qpdf/qpdf-c_impl.hh | 47 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 36 deletions(-) create mode 100644 libqpdf/qpdf/qpdf-c_impl.hh diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index 7feabd1c..01987365 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -20,42 +21,6 @@ #include #include -struct _qpdf_error -{ - std::shared_ptr exc; -}; - -struct _qpdf_data -{ - _qpdf_data() = default; - ~_qpdf_data() = default; - - std::shared_ptr qpdf; - std::shared_ptr qpdf_writer; - - std::shared_ptr error; - _qpdf_error tmp_error; - std::list warnings; - std::string tmp_string; - - // Parameters for functions we call - char const* filename{nullptr}; // or description - char const* buffer{nullptr}; - unsigned long long size{0}; - char const* password{nullptr}; - bool write_memory{false}; - std::shared_ptr output_buffer; - - // QPDFObjectHandle support - bool silence_errors{false}; - bool oh_error_occurred{false}; - std::map> oh_cache; - qpdf_oh next_oh{0}; - std::set cur_iter_dict_keys; - std::set::const_iterator dict_iter; - std::string cur_dict_key; -}; - // must set qpdf->filename and qpdf->password static void call_read(qpdf_data qpdf) diff --git a/libqpdf/qpdf/qpdf-c_impl.hh b/libqpdf/qpdf/qpdf-c_impl.hh new file mode 100644 index 00000000..0d52cf10 --- /dev/null +++ b/libqpdf/qpdf/qpdf-c_impl.hh @@ -0,0 +1,47 @@ +#include + +#include + +#include +#include +#include + +struct _qpdf_error +{ + std::shared_ptr exc; +}; + +struct _qpdf_data +{ + _qpdf_data() = default; + + _qpdf_data(std::unique_ptr&& qpdf) : + qpdf(std::move(qpdf)){}; + + ~_qpdf_data() = default; + + std::shared_ptr qpdf; + std::shared_ptr qpdf_writer; + + std::shared_ptr error; + _qpdf_error tmp_error; + std::list warnings; + std::string tmp_string; + + // Parameters for functions we call + char const* filename{nullptr}; // or description + char const* buffer{nullptr}; + unsigned long long size{0}; + char const* password{nullptr}; + bool write_memory{false}; + std::shared_ptr output_buffer; + + // QPDFObjectHandle support + bool silence_errors{false}; + bool oh_error_occurred{false}; + std::map> oh_cache; + qpdf_oh next_oh{0}; + std::set cur_iter_dict_keys; + std::set::const_iterator dict_iter; + std::string cur_dict_key; +}; -- cgit v1.2.3-54-g00ecf From 41f79bedbc1ebc2666471ec97b87999410242973 Mon Sep 17 00:00:00 2001 From: m-holger Date: Tue, 21 Mar 2023 18:54:36 +0000 Subject: Add new functions qpdfjob_create_qpdf and qpdfjob_write_qpdf --- include/qpdf/qpdfjob-c.h | 23 +++++++++++++++++++++++ libqpdf/qpdfjob-c.cc | 25 +++++++++++++++++++++++++ qpdf/qpdfjob-ctest.c | 27 +++++++++++++++++++++++++++ qpdf/qtest/qpdf/qpdfjob-ctest.out | 5 +++++ qpdf/qtest/qpdf/qpdfjob-ctest4.pdf | Bin 0 -> 799 bytes qpdf/qtest/qpdfjob.test | 4 ++-- 6 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 qpdf/qtest/qpdf/qpdfjob-ctest4.pdf diff --git a/include/qpdf/qpdfjob-c.h b/include/qpdf/qpdfjob-c.h index 8408f0d6..a251bd93 100644 --- a/include/qpdf/qpdfjob-c.h +++ b/include/qpdf/qpdfjob-c.h @@ -32,6 +32,7 @@ */ #include +#include #include #include #ifndef QPDF_NO_WCHAR_T @@ -138,6 +139,28 @@ extern "C" { QPDF_DLL int qpdfjob_run(qpdfjob_handle j); + /* The following two functions allow a job to be run in two stages - + * creation of a qpdf_data object and writing of the qpdf_data object. This + * allows the qpdf_data object to be modified prior to writing it out. See + * examples/qpdfjob-remove-annotations for a C++ illustration of its use. + * + * This function wraps QPDFJob::createQPDF. It runs the first stage of the + * job. A nullptr is returned if the job did not produce any pdf file to be + * written. + */ + QPDF_DLL + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j); + + /* This function wraps QPDFJob::writeQPDF. It returns the error code that + * qpdf would return with the equivalent command-line invocation. Exit code + * values are defined in Constants.h in the qpdf_exit_code_e type. NOTE it + * is the callers responsibility to clean up the resources associated + * qpdf_data object by calling qpdf_cleanup after the call to + * qpdfjob_write_qpdf. + */ + QPDF_DLL + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf); + /* Allow specification of a custom progress reporter. The progress * reporter is only used if progress is otherwise requested (with * the --progress option or "progress": "" in the JSON). diff --git a/libqpdf/qpdfjob-c.cc b/libqpdf/qpdfjob-c.cc index 889afec6..ddb33349 100644 --- a/libqpdf/qpdfjob-c.cc +++ b/libqpdf/qpdfjob-c.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,30 @@ qpdfjob_run(qpdfjob_handle j) }); } +qpdf_data +qpdfjob_create_qpdf(qpdfjob_handle j) +{ + QUtil::setLineBuf(stdout); + try { + auto qpdf = j->j.createQPDF(); + return qpdf ? new _qpdf_data(std::move(qpdf)) : nullptr; + } catch (std::exception& e) { + *j->j.getLogger()->getError() + << j->j.getMessagePrefix() << ": " << e.what() << "\n"; + } + return nullptr; +} + +int +qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf) +{ + QUtil::setLineBuf(stdout); + return wrap_qpdfjob(j, [qpdf](qpdfjob_handle jh) { + jh->j.writeQPDF(*(qpdf->qpdf)); + return jh->j.getExitCode(); + }); +} + static int run_with_handle(std::function fn) { diff --git a/qpdf/qpdfjob-ctest.c b/qpdf/qpdfjob-ctest.c index 708d5fa6..31f22d28 100644 --- a/qpdf/qpdfjob-ctest.c +++ b/qpdf/qpdfjob-ctest.c @@ -97,6 +97,33 @@ run_tests() assert(qpdfjob_run(j) == 2); qpdfjob_cleanup(&j); printf("json error test passed\n"); + + /* qpdfjob_create_qpdf and qpdfjob_write_qpdf test */ + argv[0] = "qpdfjob"; + argv[1] = "minimal.pdf"; + argv[2] = "d.pdf"; + argv[3] = "--deterministic-id"; + argv[4] = "--progress"; + argv[5] = NULL; + j = qpdfjob_init(); + assert(qpdfjob_initialize_from_argv(j, argv) == 0); + qpdf_data qpdf = qpdfjob_create_qpdf(j); + assert(qpdfjob_write_qpdf(j, qpdf) == 0); + qpdf_cleanup(&qpdf); + qpdfjob_cleanup(&j); + + /* Try to open a missing file to test case of QPDFJob::createQPDF returning + * nullptr. + */ + argv[0] = "qpdfjob"; + argv[1] = "m.pdf"; + argv[2] = "--check"; + argv[3] = NULL; + j = qpdfjob_init(); + assert(qpdfjob_initialize_from_argv(j, argv) == 0); + assert(qpdfjob_create_qpdf(j) == NULL); + qpdfjob_cleanup(&j); + printf("qpdfjob_create_qpdf and qpdfjob_write_qpdf test passed\n"); } int diff --git a/qpdf/qtest/qpdf/qpdfjob-ctest.out b/qpdf/qtest/qpdf/qpdfjob-ctest.out index 1778e70a..125e6257 100644 --- a/qpdf/qtest/qpdf/qpdfjob-ctest.out +++ b/qpdf/qtest/qpdf/qpdfjob-ctest.out @@ -9,3 +9,8 @@ json warn test passed |custom|qpdfjob json|custom|: |custom|an output file name is required; use - for standard output|custom| |custom|qpdfjob json|custom|: |custom|an output file name is required; use - for standard output|custom| json error test passed +qpdfjob: d.pdf: write progress: 0% +....other write progress.... +qpdfjob: d.pdf: write progress: 100% +qpdfjob: open m.pdf: No such file or directory +qpdfjob_create_qpdf and qpdfjob_write_qpdf test passed diff --git a/qpdf/qtest/qpdf/qpdfjob-ctest4.pdf b/qpdf/qtest/qpdf/qpdfjob-ctest4.pdf new file mode 100644 index 00000000..b2c4c2c0 Binary files /dev/null and b/qpdf/qtest/qpdf/qpdfjob-ctest4.pdf differ diff --git a/qpdf/qtest/qpdfjob.test b/qpdf/qtest/qpdfjob.test index 0724ba9f..2aea654b 100644 --- a/qpdf/qtest/qpdfjob.test +++ b/qpdf/qtest/qpdfjob.test @@ -43,7 +43,7 @@ my @good_json = ( "underlay-overlay-password", "misc-options", ); -my $n_tests = 10 + scalar(@bad_json) + (2 * scalar(@good_json)); +my $n_tests = 11 + scalar(@bad_json) + (2 * scalar(@good_json)); foreach my $i (@bad_json) @@ -104,7 +104,7 @@ $td->runtest("C job API", $td->FILTER => "perl filter-progress.pl"}, {$td->FILE => "qpdfjob-ctest.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); -foreach my $i (['a.pdf', 1], ['b.pdf', 2], ['c.pdf', 3]) +foreach my $i (['a.pdf', 1], ['b.pdf', 2], ['c.pdf', 3], ['d.pdf', 4]) { $td->runtest("check output", {$td->FILE => $i->[0]}, -- cgit v1.2.3-54-g00ecf