2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 19:08:59 +00:00

Add more flexible funtions to qpdfjob C API

This commit is contained in:
Jay Berkenbilt 2022-06-19 08:20:43 -04:00
parent 28cc3692e3
commit daef4e8fb8
7 changed files with 158 additions and 26 deletions

View File

@ -1,5 +1,7 @@
2022-06-18 Jay Berkenbilt <ejb@ql.org> 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 * Add qpdf_exit_code_e to Constants.h so that exit codes from
QPDFJob are accessible to the C API. QPDFJob are accessible to the C API.

View File

@ -108,6 +108,8 @@ class QPDFJob
// and error streams on the caller's behalf. Defaults to "qpdf". // and error streams on the caller's behalf. Defaults to "qpdf".
QPDF_DLL QPDF_DLL
void setMessagePrefix(std::string const&); void setMessagePrefix(std::string const&);
QPDF_DLL
std::string getMessagePrefix() const;
// To capture or redirect output, configure the logger returned by // To capture or redirect output, configure the logger returned by
// getLogger(). By default, all QPDF and QPDFJob objects share the // getLogger(). By default, all QPDF and QPDFJob objects share the

View File

@ -45,6 +45,11 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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 /* This function does the equivalent of running the qpdf
* command-line with the given arguments and returns the exit code * command-line with the given arguments and returns the exit code
* that qpdf would use. argv must be a null-terminated array of * that qpdf would use. argv must be a null-terminated array of
@ -74,6 +79,52 @@ extern "C" {
QPDF_DLL QPDF_DLL
int qpdfjob_run_from_json(char const* json); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -438,6 +438,12 @@ QPDFJob::setMessagePrefix(std::string const& message_prefix)
this->m->message_prefix = message_prefix; this->m->message_prefix = message_prefix;
} }
std::string
QPDFJob::getMessagePrefix() const
{
return this->m->message_prefix;
}
std::shared_ptr<QPDFLogger> std::shared_ptr<QPDFLogger>
QPDFJob::getLogger() QPDFJob::getLogger()
{ {

View File

@ -8,51 +8,115 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
int struct _qpdfjob_handle
qpdfjob_run_from_argv(char const* const argv[])
{ {
auto whoami_p = QUtil::make_unique_cstr(argv[0]); _qpdfjob_handle() = default;
auto whoami = QUtil::getWhoami(whoami_p.get()); ~_qpdfjob_handle() = default;
QUtil::setLineBuf(stdout);
QPDFJob j; 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 { try {
j.initializeFromArgv(argv); return fn(j);
j.run();
} catch (std::exception& e) { } catch (std::exception& e) {
*QPDFLogger::defaultLogger()->getError() *j->j.getLogger()->getError()
<< whoami << ": " << e.what() << "\n"; << j->j.getMessagePrefix() << ": " << e.what() << "\n";
return QPDFJob::EXIT_ERROR;
} }
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 #ifndef QPDF_NO_WCHAR_T
int 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; int argc = 0;
for (auto k = argv; *k; ++k) { for (auto k = argv; *k; ++k) {
++argc; ++argc;
} }
return QUtil::call_main_from_wmain( return QUtil::call_main_from_wmain(
argc, argv, [](int, char const* const new_argv[]) { argc, argv, [j](int, char const* const new_argv[]) {
return qpdfjob_run_from_argv(new_argv); return qpdfjob_initialize_from_argv(j, new_argv);
}); });
} }
#endif // QPDF_NO_WCHAR_T #endif // QPDF_NO_WCHAR_T
int int
qpdfjob_run_from_json(char const* json) qpdfjob_initialize_from_json(qpdfjob_handle j, char const* json)
{ {
QPDFJob j; return wrap_qpdfjob(j, [json](qpdfjob_handle jh) {
try { jh->j.setMessagePrefix("qpdfjob json");
j.initializeFromJson(json); jh->j.initializeFromJson(json);
j.run(); return 0;
} catch (std::exception& e) { });
*QPDFLogger::defaultLogger()->getError()
<< "qpdfjob json: " << e.what() << "\n";
return QPDFJob::EXIT_ERROR;
}
return j.getExitCode();
} }
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);
}
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);
});
}

View File

@ -188,6 +188,13 @@ For a detailed list of changes, please see the file
writing large amounts of data without having to keep everything writing large amounts of data without having to keep everything
in memory. 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 - Other changes
- In JSON v1 mode, the ``"objects"`` key now reflects the repaired - In JSON v1 mode, the ``"objects"`` key now reflects the repaired

View File

@ -1,7 +1,7 @@
argv test passed argv test passed
json 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 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 json warn test passed
qpdfjob json: an output file name is required; use - for standard output qpdfjob json: an output file name is required; use - for standard output
json error test passed json error test passed