aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--include/qpdf/QPDFJob.hh2
-rw-r--r--include/qpdf/qpdfjob-c.h51
-rw-r--r--libqpdf/QPDFJob.cc6
-rw-r--r--libqpdf/qpdfjob-c.cc112
-rw-r--r--manual/release-notes.rst7
-rw-r--r--qpdf/qtest/qpdf/qpdfjob-ctest.out2
7 files changed, 157 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index f170a11b..97e8506c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
2022-06-18 Jay Berkenbilt <ejb@ql.org>
+ * Add additional qpdfjob C API functions take a handle.
+
* Add qpdf_exit_code_e to Constants.h so that exit codes from
QPDFJob are accessible to the C API.
diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh
index 39c7a612..16b1ab74 100644
--- a/include/qpdf/QPDFJob.hh
+++ b/include/qpdf/QPDFJob.hh
@@ -108,6 +108,8 @@ class QPDFJob
// and error streams on the caller's behalf. Defaults to "qpdf".
QPDF_DLL
void setMessagePrefix(std::string const&);
+ QPDF_DLL
+ std::string getMessagePrefix() const;
// To capture or redirect output, configure the logger returned by
// getLogger(). By default, all QPDF and QPDFJob objects share the
diff --git a/include/qpdf/qpdfjob-c.h b/include/qpdf/qpdfjob-c.h
index b9fe8ccb..e15c8fa5 100644
--- a/include/qpdf/qpdfjob-c.h
+++ b/include/qpdf/qpdfjob-c.h
@@ -45,6 +45,11 @@
#ifdef __cplusplus
extern "C" {
#endif
+ /* SHORT INTERFACE -- These functions are single calls that take
+ * care of the whole life cycle of QPDFJob. They can be used for
+ * one-shot ooperations where no additional configuration is
+ * needed. See FULL INTERFACE below. */
+
/* This function does the equivalent of running the qpdf
* command-line with the given arguments and returns the exit code
* that qpdf would use. argv must be a null-terminated array of
@@ -74,6 +79,52 @@ extern "C" {
QPDF_DLL
int qpdfjob_run_from_json(char const* json);
+ /* FULL INTERFACE -- new in qpdf11. Similar to the qpdf-c.h API,
+ * you must call qpdfjob_init to get a qpdfjob_handle and, when
+ * done, call qpdfjob_cleanup to free resources. Remaining methods
+ * take qpdfjob_handle as an argument. This interface requires
+ * more calls but also offers greater flexibility.
+ */
+ typedef struct _qpdfjob_handle* qpdfjob_handle;
+ QPDF_DLL
+ qpdfjob_handle qpdfjob_init();
+
+ QPDF_DLL
+ void qpdfjob_cleanup(qpdfjob_handle* j);
+
+ /* This function wraps QPDFJob::initializeFromArgv. The return
+ * value is the same as qpdfjob_run. If this returns an error, it
+ * is invalid to call any other functions this job handle.
+ */
+ QPDF_DLL
+ int
+ qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]);
+
+#ifndef QPDF_NO_WCHAR_T
+ /* This function is the same as qpdfjob_initialize_from_argv
+ * except argv is encoded with wide characters. This would be
+ * suitable for calling from a Windows wmain function.
+ */
+ QPDF_DLL
+ int qpdfjob_initialize_from_wide_argv(
+ qpdfjob_handle j, wchar_t const* const argv[]);
+#endif /* QPDF_NO_WCHAR_T */
+
+ /* This function wraps QPDFJob::initializeFromJson. The return
+ * value is the same as qpdfjob_run. If this returns an error, it
+ * is invalid to call any other functions this job handle.
+ */
+ QPDF_DLL
+ int qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json);
+
+ /* This function wraps QPDFJob::run. 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.
+ */
+ QPDF_DLL
+ int qpdfjob_run(qpdfjob_handle j);
+
#ifdef __cplusplus
}
#endif
diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc
index 9f76bdf4..b25257a1 100644
--- a/libqpdf/QPDFJob.cc
+++ b/libqpdf/QPDFJob.cc
@@ -438,6 +438,12 @@ QPDFJob::setMessagePrefix(std::string const& message_prefix)
this->m->message_prefix = message_prefix;
}
+std::string
+QPDFJob::getMessagePrefix() const
+{
+ return this->m->message_prefix;
+}
+
std::shared_ptr<QPDFLogger>
QPDFJob::getLogger()
{
diff --git a/libqpdf/qpdfjob-c.cc b/libqpdf/qpdfjob-c.cc
index 4e6666be..81433661 100644
--- a/libqpdf/qpdfjob-c.cc
+++ b/libqpdf/qpdfjob-c.cc
@@ -8,51 +8,115 @@
#include <cstdio>
#include <cstring>
-int
-qpdfjob_run_from_argv(char const* const argv[])
+struct _qpdfjob_handle
{
- auto whoami_p = QUtil::make_unique_cstr(argv[0]);
- auto whoami = QUtil::getWhoami(whoami_p.get());
- QUtil::setLineBuf(stdout);
+ _qpdfjob_handle() = default;
+ ~_qpdfjob_handle() = default;
QPDFJob j;
+};
+
+qpdfjob_handle
+qpdfjob_init()
+{
+ return new _qpdfjob_handle;
+}
+
+void
+qpdfjob_cleanup(qpdfjob_handle* j)
+{
+ delete *j;
+ *j = nullptr;
+}
+
+static int
+wrap_qpdfjob(qpdfjob_handle j, std::function<int(qpdfjob_handle j)> fn)
+{
try {
- j.initializeFromArgv(argv);
- j.run();
+ return fn(j);
} catch (std::exception& e) {
- *QPDFLogger::defaultLogger()->getError()
- << whoami << ": " << e.what() << "\n";
- return QPDFJob::EXIT_ERROR;
+ *j->j.getLogger()->getError()
+ << j->j.getMessagePrefix() << ": " << e.what() << "\n";
}
- return j.getExitCode();
+ return QPDFJob::EXIT_ERROR;
+}
+
+int
+qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[])
+{
+ return wrap_qpdfjob(j, [argv](qpdfjob_handle jh) {
+ jh->j.initializeFromArgv(argv);
+ return 0;
+ });
}
#ifndef QPDF_NO_WCHAR_T
int
-qpdfjob_run_from_wide_argv(wchar_t const* const argv[])
+qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[])
{
int argc = 0;
for (auto k = argv; *k; ++k) {
++argc;
}
return QUtil::call_main_from_wmain(
- argc, argv, [](int, char const* const new_argv[]) {
- return qpdfjob_run_from_argv(new_argv);
+ argc, argv, [j](int, char const* const new_argv[]) {
+ return qpdfjob_initialize_from_argv(j, new_argv);
});
}
#endif // QPDF_NO_WCHAR_T
int
-qpdfjob_run_from_json(char const* json)
+qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json)
{
- QPDFJob j;
- try {
- j.initializeFromJson(json);
- j.run();
- } catch (std::exception& e) {
- *QPDFLogger::defaultLogger()->getError()
- << "qpdfjob json: " << e.what() << "\n";
- return QPDFJob::EXIT_ERROR;
+ return wrap_qpdfjob(j, [json](qpdfjob_handle jh) {
+ jh->j.setMessagePrefix("qpdfjob json");
+ jh->j.initializeFromJson(json);
+ return 0;
+ });
+}
+
+int
+qpdfjob_run(qpdfjob_handle j)
+{
+ QUtil::setLineBuf(stdout);
+ return wrap_qpdfjob(j, [](qpdfjob_handle jh) {
+ jh->j.run();
+ return jh->j.getExitCode();
+ });
+}
+
+static int run_with_handle(std::function<int(qpdfjob_handle)> fn)
+{
+ auto j = qpdfjob_init();
+ int status = fn(j);
+ if (status == 0) {
+ status = qpdfjob_run(j);
}
- return j.getExitCode();
+ qpdfjob_cleanup(&j);
+ return status;
}
+
+int qpdfjob_run_from_argv(char const* const argv[])
+{
+ return run_with_handle([argv](qpdfjob_handle j) {
+ return qpdfjob_initialize_from_argv(j, argv);
+ });
+}
+
+#ifndef QPDF_NO_WCHAR_T
+int
+qpdfjob_run_from_wide_argv(wchar_t const* const argv[])
+{
+ return run_with_handle([argv](qpdfjob_handle j) {
+ return qpdfjob_initialize_from_wide_argv(j, argv);
+ });
+}
+#endif /* QPDF_NO_WCHAR_T */
+
+int qpdfjob_run_from_json(char const* json)
+{
+ return run_with_handle([json](qpdfjob_handle j) {
+ return qpdfjob_initialize_from_json(j, json);
+ });
+}
+
diff --git a/manual/release-notes.rst b/manual/release-notes.rst
index 780f541f..f7d673e7 100644
--- a/manual/release-notes.rst
+++ b/manual/release-notes.rst
@@ -188,6 +188,13 @@ For a detailed list of changes, please see the file
writing large amounts of data without having to keep everything
in memory.
+ - Add new functions to the C API for qpdfjob that use a
+ ``qpdfjob_handle``. Like with the regular C API for qpdf, you
+ have to call ``qpdfjob_init`` first, pass the handle to the
+ functions, and call ``qpdfjob_cleanup`` at the end. This
+ interface offers more flexibility than the old interface, which
+ remains available.
+
- Other changes
- In JSON v1 mode, the ``"objects"`` key now reflects the repaired
diff --git a/qpdf/qtest/qpdf/qpdfjob-ctest.out b/qpdf/qtest/qpdf/qpdfjob-ctest.out
index 1d7df741..ac2959f2 100644
--- a/qpdf/qtest/qpdf/qpdfjob-ctest.out
+++ b/qpdf/qtest/qpdf/qpdfjob-ctest.out
@@ -1,7 +1,7 @@
argv test passed
json test passed
WARNING: xref-with-short-size.pdf (xref stream, offset 16227): Cross-reference stream data has the wrong size; expected = 52; actual = 56
-qpdf: operation succeeded with warnings; resulting file may have some problems
+qpdfjob json: operation succeeded with warnings; resulting file may have some problems
json warn test passed
qpdfjob json: an output file name is required; use - for standard output
json error test passed