From 8130d50e3b5aa0235a133c3c5a3018ac01afb5e1 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 18 Jun 2022 13:38:36 -0400 Subject: Add C API to QPDFLogger --- libqpdf/CMakeLists.txt | 3 +- libqpdf/QPDFJob.cc | 8 +-- libqpdf/QPDFLogger.cc | 9 ++- libqpdf/qpdflogger-c.cc | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 libqpdf/qpdflogger-c.cc (limited to 'libqpdf') diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt index a6b036a7..3c14115b 100644 --- a/libqpdf/CMakeLists.txt +++ b/libqpdf/CMakeLists.txt @@ -110,7 +110,8 @@ set(libqpdf_SOURCES SF_FlateLzwDecode.cc SparseOHArray.cc qpdf-c.cc - qpdfjob-c.cc) + qpdfjob-c.cc + qpdflogger-c.cc) include(FindPkgConfig) include(CheckTypeSize) diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index b25257a1..606a612a 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -710,7 +710,7 @@ QPDFJob::checkConfiguration() save_to_stdout = true; } if (save_to_stdout) { - this->m->log->saveToStandardOutput(); + this->m->log->saveToStandardOutput(true); } if ((!m->split_pages) && QUtil::same_file(m->infilename.get(), m->outfilename.get())) { @@ -925,7 +925,7 @@ QPDFJob::doShowObj(QPDF& pdf) } else { // If anything has been written to standard output, // this will fail. - this->m->log->saveToStandardOutput(); + this->m->log->saveToStandardOutput(true); obj.pipeStreamData( this->m->log->getSave().get(), (filter && m->normalize) ? qpdf_ef_normalize : 0, @@ -1031,7 +1031,7 @@ QPDFJob::doShowAttachment(QPDF& pdf) auto efs = fs->getEmbeddedFileStream(); // saveToStandardOutput has already been called, but it's harmless // to call it again, so do as defensive coding. - this->m->log->saveToStandardOutput(); + this->m->log->saveToStandardOutput(true); efs.pipeStreamData(this->m->log->getSave().get(), 0, qpdf_dl_all); } @@ -3289,7 +3289,7 @@ QPDFJob::writeOutfile(QPDF& pdf) } else { // saveToStandardOutput has already been called, but // calling it again is defensive and harmless. - this->m->log->saveToStandardOutput(); + this->m->log->saveToStandardOutput(true); w.setOutputPipeline(this->m->log->getSave().get()); } setWriterOptions(pdf, w); diff --git a/libqpdf/QPDFLogger.cc b/libqpdf/QPDFLogger.cc index 3b25c050..78cb2a32 100644 --- a/libqpdf/QPDFLogger.cc +++ b/libqpdf/QPDFLogger.cc @@ -181,8 +181,11 @@ QPDFLogger::setError(std::shared_ptr p) } void -QPDFLogger::setSave(std::shared_ptr p) +QPDFLogger::setSave(std::shared_ptr p, bool only_if_not_set) { + if (only_if_not_set && (this->m->p_save != nullptr)) { + return; + } if (this->m->p_save == p) { return; } @@ -202,9 +205,9 @@ QPDFLogger::setSave(std::shared_ptr p) } void -QPDFLogger::saveToStandardOutput() +QPDFLogger::saveToStandardOutput(bool only_if_not_set) { - setSave(standardOutput()); + setSave(standardOutput(), only_if_not_set); } void diff --git a/libqpdf/qpdflogger-c.cc b/libqpdf/qpdflogger-c.cc new file mode 100644 index 00000000..46fd9fba --- /dev/null +++ b/libqpdf/qpdflogger-c.cc @@ -0,0 +1,163 @@ +#include + +#include +#include +#include +#include +#include + +struct _qpdflogger_handle +{ + _qpdflogger_handle(std::shared_ptr l); + ~_qpdflogger_handle() = default; + + std::shared_ptr l; +}; + +namespace +{ + class FunctionPipeline: public Pipeline + { + public: + FunctionPipeline(char const* identifier, qpdf_log_fn_t fn, void* udata); + virtual ~FunctionPipeline() = default; + + virtual void write(unsigned char const* buf, size_t len) override; + virtual void finish() override; + + private: + qpdf_log_fn_t fn; + void* udata; + }; +}; // namespace + +FunctionPipeline::FunctionPipeline( + char const* identifier, qpdf_log_fn_t fn, void* udata) : + Pipeline(identifier, nullptr), + fn(fn), + udata(udata) +{ +} + +void +FunctionPipeline::write(unsigned char const* buf, size_t len) +{ + fn(reinterpret_cast(buf), QIntC::to_ulong(len), udata); +} + +void +FunctionPipeline::finish() +{ + // Nothing needed +} + +_qpdflogger_handle::_qpdflogger_handle(std::shared_ptr l) : + l(l) +{ +} + +qpdflogger_handle +qpdflogger_default_logger() +{ + return new _qpdflogger_handle(QPDFLogger::defaultLogger()); +} + +void +qpdflogger_cleanup(qpdflogger_handle* l) +{ + delete *l; + *l = nullptr; +} + +static void +set_log_dest( + QPDFLogger* l, + std::function)> method, + qpdf_log_dest_e dest, + char const* identifier, + qpdf_log_fn_t fn, + void* udata) +{ + switch (dest) { + case qpdf_log_dest_default: + method(nullptr); + break; + case qpdf_log_dest_stdout: + method(l->standardOutput()); + break; + case qpdf_log_dest_stderr: + method(l->standardError()); + break; + case qpdf_log_dest_discard: + method(l->discard()); + break; + case qpdf_log_dest_custom: + method(std::make_shared(identifier, fn, udata)); + break; + } +} + +static void +set_log_dest( + QPDFLogger* l, + void (QPDFLogger::*method)(std::shared_ptr), + qpdf_log_dest_e dest, + char const* identifier, + qpdf_log_fn_t fn, + void* udata) +{ + set_log_dest( + l, + std::bind(std::mem_fn(method), l, std::placeholders::_1), + dest, + identifier, + fn, + udata); +} + +void +qpdflogger_set_info( + qpdflogger_handle l, qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata) +{ + set_log_dest( + l->l.get(), &QPDFLogger::setInfo, dest, "info logger", fn, udata); +} + +void +qpdflogger_set_warn( + qpdflogger_handle l, qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata) +{ + set_log_dest( + l->l.get(), &QPDFLogger::setWarn, dest, "warn logger", fn, udata); +} + +void +qpdflogger_set_error( + qpdflogger_handle l, qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata) +{ + set_log_dest( + l->l.get(), &QPDFLogger::setError, dest, "error logger", fn, udata); +} + +void +qpdflogger_set_save( + qpdflogger_handle l, + qpdf_log_dest_e dest, + qpdf_log_fn_t fn, + void* udata, + int only_if_not_set) +{ + auto method = std::bind( + std::mem_fn(&QPDFLogger::setSave), + l->l.get(), + std::placeholders::_1, + only_if_not_set); + set_log_dest(l->l.get(), method, dest, "save logger", fn, udata); +} + +void +qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set) +{ + qpdflogger_set_save( + l, qpdf_log_dest_stdout, nullptr, nullptr, only_if_not_set); +} -- cgit v1.2.3-54-g00ecf