Commit 230f1ab29039c30c5974d17ddcb0667ceedccf79

Authored by Jay Berkenbilt
Committed by GitHub
2 parents f8e39253 41f79bed

Merge pull request #933 from m-holger/c_job

C-API : expose QPDFJob::createQPDF and writeQPDF
include/qpdf/qpdfjob-c.h
... ... @@ -32,6 +32,7 @@
32 32 */
33 33  
34 34 #include <qpdf/DLL.h>
  35 +#include <qpdf/qpdf-c.h>
35 36 #include <qpdf/qpdflogger-c.h>
36 37 #include <string.h>
37 38 #ifndef QPDF_NO_WCHAR_T
... ... @@ -138,6 +139,28 @@ extern &quot;C&quot; {
138 139 QPDF_DLL
139 140 int qpdfjob_run(qpdfjob_handle j);
140 141  
  142 + /* The following two functions allow a job to be run in two stages -
  143 + * creation of a qpdf_data object and writing of the qpdf_data object. This
  144 + * allows the qpdf_data object to be modified prior to writing it out. See
  145 + * examples/qpdfjob-remove-annotations for a C++ illustration of its use.
  146 + *
  147 + * This function wraps QPDFJob::createQPDF. It runs the first stage of the
  148 + * job. A nullptr is returned if the job did not produce any pdf file to be
  149 + * written.
  150 + */
  151 + QPDF_DLL
  152 + qpdf_data qpdfjob_create_qpdf(qpdfjob_handle j);
  153 +
  154 + /* This function wraps QPDFJob::writeQPDF. It returns the error code that
  155 + * qpdf would return with the equivalent command-line invocation. Exit code
  156 + * values are defined in Constants.h in the qpdf_exit_code_e type. NOTE it
  157 + * is the callers responsibility to clean up the resources associated
  158 + * qpdf_data object by calling qpdf_cleanup after the call to
  159 + * qpdfjob_write_qpdf.
  160 + */
  161 + QPDF_DLL
  162 + int qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf);
  163 +
141 164 /* Allow specification of a custom progress reporter. The progress
142 165 * reporter is only used if progress is otherwise requested (with
143 166 * the --progress option or "progress": "" in the JSON).
... ...
libqpdf/qpdf-c.cc
... ... @@ -12,6 +12,7 @@
12 12 #include <qpdf/QPDFWriter.hh>
13 13 #include <qpdf/QTC.hh>
14 14 #include <qpdf/QUtil.hh>
  15 +#include <qpdf/qpdf-c_impl.hh>
15 16 #include <qpdf/qpdflogger-c_impl.hh>
16 17  
17 18 #include <cstring>
... ... @@ -20,50 +21,6 @@
20 21 #include <stdexcept>
21 22 #include <string>
22 23  
23   -struct _qpdf_error
24   -{
25   - std::shared_ptr<QPDFExc> exc;
26   -};
27   -
28   -struct _qpdf_data
29   -{
30   - _qpdf_data();
31   - ~_qpdf_data() = default;
32   -
33   - std::shared_ptr<QPDF> qpdf;
34   - std::shared_ptr<QPDFWriter> qpdf_writer;
35   -
36   - std::shared_ptr<QPDFExc> error;
37   - _qpdf_error tmp_error;
38   - std::list<QPDFExc> warnings;
39   - std::string tmp_string;
40   -
41   - // Parameters for functions we call
42   - char const* filename; // or description
43   - char const* buffer;
44   - unsigned long long size;
45   - char const* password;
46   - bool write_memory;
47   - std::shared_ptr<Buffer> output_buffer;
48   -
49   - // QPDFObjectHandle support
50   - bool silence_errors;
51   - bool oh_error_occurred;
52   - std::map<qpdf_oh, std::shared_ptr<QPDFObjectHandle>> oh_cache;
53   - qpdf_oh next_oh;
54   - std::set<std::string> cur_iter_dict_keys;
55   - std::set<std::string>::const_iterator dict_iter;
56   - std::string cur_dict_key;
57   -};
58   -
59   -_qpdf_data::_qpdf_data() :
60   - write_memory(false),
61   - silence_errors(false),
62   - oh_error_occurred(false),
63   - next_oh(0)
64   -{
65   -}
66   -
67 24 // must set qpdf->filename and qpdf->password
68 25 static void
69 26 call_read(qpdf_data qpdf)
... ...
libqpdf/qpdf/qpdf-c_impl.hh 0 → 100644
  1 +#include <qpdf/qpdf-c.h>
  2 +
  3 +#include <memory>
  4 +
  5 +#include <qpdf/QPDF.hh>
  6 +#include <qpdf/QPDFExc.hh>
  7 +#include <qpdf/QPDFWriter.hh>
  8 +
  9 +struct _qpdf_error
  10 +{
  11 + std::shared_ptr<QPDFExc> exc;
  12 +};
  13 +
  14 +struct _qpdf_data
  15 +{
  16 + _qpdf_data() = default;
  17 +
  18 + _qpdf_data(std::unique_ptr<QPDF>&& qpdf) :
  19 + qpdf(std::move(qpdf)){};
  20 +
  21 + ~_qpdf_data() = default;
  22 +
  23 + std::shared_ptr<QPDF> qpdf;
  24 + std::shared_ptr<QPDFWriter> qpdf_writer;
  25 +
  26 + std::shared_ptr<QPDFExc> error;
  27 + _qpdf_error tmp_error;
  28 + std::list<QPDFExc> warnings;
  29 + std::string tmp_string;
  30 +
  31 + // Parameters for functions we call
  32 + char const* filename{nullptr}; // or description
  33 + char const* buffer{nullptr};
  34 + unsigned long long size{0};
  35 + char const* password{nullptr};
  36 + bool write_memory{false};
  37 + std::shared_ptr<Buffer> output_buffer;
  38 +
  39 + // QPDFObjectHandle support
  40 + bool silence_errors{false};
  41 + bool oh_error_occurred{false};
  42 + std::map<qpdf_oh, std::shared_ptr<QPDFObjectHandle>> oh_cache;
  43 + qpdf_oh next_oh{0};
  44 + std::set<std::string> cur_iter_dict_keys;
  45 + std::set<std::string>::const_iterator dict_iter;
  46 + std::string cur_dict_key;
  47 +};
... ...
libqpdf/qpdfjob-c.cc
... ... @@ -4,6 +4,7 @@
4 4 #include <qpdf/QPDFLogger.hh>
5 5 #include <qpdf/QPDFUsage.hh>
6 6 #include <qpdf/QUtil.hh>
  7 +#include <qpdf/qpdf-c_impl.hh>
7 8 #include <qpdf/qpdflogger-c_impl.hh>
8 9  
9 10 #include <cstdio>
... ... @@ -98,6 +99,30 @@ qpdfjob_run(qpdfjob_handle j)
98 99 });
99 100 }
100 101  
  102 +qpdf_data
  103 +qpdfjob_create_qpdf(qpdfjob_handle j)
  104 +{
  105 + QUtil::setLineBuf(stdout);
  106 + try {
  107 + auto qpdf = j->j.createQPDF();
  108 + return qpdf ? new _qpdf_data(std::move(qpdf)) : nullptr;
  109 + } catch (std::exception& e) {
  110 + *j->j.getLogger()->getError()
  111 + << j->j.getMessagePrefix() << ": " << e.what() << "\n";
  112 + }
  113 + return nullptr;
  114 +}
  115 +
  116 +int
  117 +qpdfjob_write_qpdf(qpdfjob_handle j, qpdf_data qpdf)
  118 +{
  119 + QUtil::setLineBuf(stdout);
  120 + return wrap_qpdfjob(j, [qpdf](qpdfjob_handle jh) {
  121 + jh->j.writeQPDF(*(qpdf->qpdf));
  122 + return jh->j.getExitCode();
  123 + });
  124 +}
  125 +
101 126 static int
102 127 run_with_handle(std::function<int(qpdfjob_handle)> fn)
103 128 {
... ...
qpdf/qpdfjob-ctest.c
... ... @@ -97,6 +97,33 @@ run_tests()
97 97 assert(qpdfjob_run(j) == 2);
98 98 qpdfjob_cleanup(&j);
99 99 printf("json error test passed\n");
  100 +
  101 + /* qpdfjob_create_qpdf and qpdfjob_write_qpdf test */
  102 + argv[0] = "qpdfjob";
  103 + argv[1] = "minimal.pdf";
  104 + argv[2] = "d.pdf";
  105 + argv[3] = "--deterministic-id";
  106 + argv[4] = "--progress";
  107 + argv[5] = NULL;
  108 + j = qpdfjob_init();
  109 + assert(qpdfjob_initialize_from_argv(j, argv) == 0);
  110 + qpdf_data qpdf = qpdfjob_create_qpdf(j);
  111 + assert(qpdfjob_write_qpdf(j, qpdf) == 0);
  112 + qpdf_cleanup(&qpdf);
  113 + qpdfjob_cleanup(&j);
  114 +
  115 + /* Try to open a missing file to test case of QPDFJob::createQPDF returning
  116 + * nullptr.
  117 + */
  118 + argv[0] = "qpdfjob";
  119 + argv[1] = "m.pdf";
  120 + argv[2] = "--check";
  121 + argv[3] = NULL;
  122 + j = qpdfjob_init();
  123 + assert(qpdfjob_initialize_from_argv(j, argv) == 0);
  124 + assert(qpdfjob_create_qpdf(j) == NULL);
  125 + qpdfjob_cleanup(&j);
  126 + printf("qpdfjob_create_qpdf and qpdfjob_write_qpdf test passed\n");
100 127 }
101 128  
102 129 int
... ...
qpdf/qtest/qpdf/qpdfjob-ctest.out
... ... @@ -9,3 +9,8 @@ json warn test passed
9 9 |custom|qpdfjob json|custom|: |custom|an output file name is required; use - for standard output|custom|
10 10 |custom|qpdfjob json|custom|: |custom|an output file name is required; use - for standard output|custom|
11 11 json error test passed
  12 +qpdfjob: d.pdf: write progress: 0%
  13 +....other write progress....
  14 +qpdfjob: d.pdf: write progress: 100%
  15 +qpdfjob: open m.pdf: No such file or directory
  16 +qpdfjob_create_qpdf and qpdfjob_write_qpdf test passed
... ...
qpdf/qtest/qpdf/qpdfjob-ctest4.pdf 0 → 100644
No preview for this file type
qpdf/qtest/qpdfjob.test
... ... @@ -43,7 +43,7 @@ my @good_json = (
43 43 "underlay-overlay-password",
44 44 "misc-options",
45 45 );
46   -my $n_tests = 10 + scalar(@bad_json) + (2 * scalar(@good_json));
  46 +my $n_tests = 11 + scalar(@bad_json) + (2 * scalar(@good_json));
47 47  
48 48  
49 49 foreach my $i (@bad_json)
... ... @@ -104,7 +104,7 @@ $td-&gt;runtest(&quot;C job API&quot;,
104 104 $td->FILTER => "perl filter-progress.pl"},
105 105 {$td->FILE => "qpdfjob-ctest.out", $td->EXIT_STATUS => 0},
106 106 $td->NORMALIZE_NEWLINES);
107   -foreach my $i (['a.pdf', 1], ['b.pdf', 2], ['c.pdf', 3])
  107 +foreach my $i (['a.pdf', 1], ['b.pdf', 2], ['c.pdf', 3], ['d.pdf', 4])
108 108 {
109 109 $td->runtest("check output",
110 110 {$td->FILE => $i->[0]},
... ...