From 41f79bedbc1ebc2666471ec97b87999410242973 Mon Sep 17 00:00:00 2001 From: m-holger Date: Tue, 21 Mar 2023 18:54:36 +0000 Subject: [PATCH] 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 0000000000000000000000000000000000000000..b2c4c2c0f64569441bba218f4185a62cbc82326d GIT binary patch literal 799 zcmah{&2G~`5C$rwuoCYuNaP0iXJb2&A`9BoYQ$eiB5{av*w~X`vq8! zhy@nl5;6p9{NV(_IuKf9Y5`%$P$nkOTvvnxwUinhu%4z#0TbXQby|@(`D&`UuBlR^ z)CIIQ<(^}bihZ@BEH*v9<3iAJfpQH*PJxxIAr@+x$E4FJjuhRL9}akBqA(;zuHq4D z@VCgO8KdW~PE6%W&NGw?{RUcX%9&;wb9!e&V-I7Ml%zuED300cW5KS5gKzKo*mhqv z`g<2&&(GG6@7=$>{@z$y{Rfvn#*NFL`Q58qH@@7wvnJQBnb-aqnN`(&QDE7Eb%fbF z)M+fhI+Rp0l?$+5r}Bv`(i(Unj%g+l89rLhbU7f?8U1e>EOXU? zrqv)Z~x0}b!Z2xIGu|$ zBlpcrhf0~{Dz|Zzo+1Qb^?NYs+Md%2Vno3c!TGF%v-X^eAg}{2{6zTS|0AYm4+<@E PUE1Ke4r?|KUqruntest("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]},