mirror of
https://github.com/qpdf/qpdf.git
synced 2024-05-30 08:50:51 +00:00
Add C API to QPDFLogger
This commit is contained in:
parent
daef4e8fb8
commit
8130d50e3b
|
@ -1,5 +1,11 @@
|
||||||
2022-06-18 Jay Berkenbilt <ejb@ql.org>
|
2022-06-18 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* Add examples that show how to capture QPDFJob's output by
|
||||||
|
configuring the default logger (qpdfjob-save-attachment.cc,
|
||||||
|
qpdfjob-c-save-attachment.c). Fixes #691.
|
||||||
|
|
||||||
|
* Add C API for QPDFLogger -- see qpdflogger-c.h
|
||||||
|
|
||||||
* Add additional qpdfjob C API functions take a handle.
|
* 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
|
||||||
|
|
|
@ -130,9 +130,9 @@ class QPDFLogger
|
||||||
void setError(std::shared_ptr<Pipeline>);
|
void setError(std::shared_ptr<Pipeline>);
|
||||||
// See notes above about the save pipeline
|
// See notes above about the save pipeline
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setSave(std::shared_ptr<Pipeline>);
|
void setSave(std::shared_ptr<Pipeline>, bool only_if_not_set);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void saveToStandardOutput();
|
void saveToStandardOutput(bool only_if_not_set);
|
||||||
|
|
||||||
// Shortcut for logic to reset output to new output/error streams.
|
// Shortcut for logic to reset output to new output/error streams.
|
||||||
// out_stream is used for info, err_stream is used for error, and
|
// out_stream is used for info, err_stream is used for error, and
|
||||||
|
|
100
include/qpdf/qpdflogger-c.h
Normal file
100
include/qpdf/qpdflogger-c.h
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/* Copyright (c) 2005-2022 Jay Berkenbilt
|
||||||
|
*
|
||||||
|
* This file is part of qpdf.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Versions of qpdf prior to version 7 were released under the terms
|
||||||
|
* of version 2.0 of the Artistic License. At your option, you may
|
||||||
|
* continue to consider qpdf to be licensed under those terms. Please
|
||||||
|
* see the manual for additional information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QPDFLOGGER_H
|
||||||
|
#define QPDFLOGGER_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file provides a C API for QPDFLogger. See QPDFLogger.hh for
|
||||||
|
* information about the logger.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qpdf/DLL.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* To operate on a logger, you need a handle to it. call
|
||||||
|
* qpdflogger_default_logger to get a handle for the default
|
||||||
|
* logger. The qpdf and qpdfjob functions may offer ways to get
|
||||||
|
* other logger handles. When you're done with the logger handler,
|
||||||
|
* call qpdflogger_cleanup. This does not destroy the underlying
|
||||||
|
* log object. It just cleans up the handle to it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _qpdflogger_handle* qpdflogger_handle;
|
||||||
|
QPDF_DLL
|
||||||
|
qpdflogger_handle qpdflogger_default_logger();
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_cleanup(qpdflogger_handle* l);
|
||||||
|
|
||||||
|
enum qpdf_log_dest_e {
|
||||||
|
qpdf_log_dest_default = 0,
|
||||||
|
qpdf_log_dest_stdout = 1,
|
||||||
|
qpdf_log_dest_stderr = 2,
|
||||||
|
qpdf_log_dest_discard = 3,
|
||||||
|
qpdf_log_dest_custom = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*qpdf_log_fn_t)(char const* data, size_t len, void* udata);
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_set_info(
|
||||||
|
qpdflogger_handle l,
|
||||||
|
enum qpdf_log_dest_e dest,
|
||||||
|
qpdf_log_fn_t fn,
|
||||||
|
void* udata);
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_set_warn(
|
||||||
|
qpdflogger_handle l,
|
||||||
|
enum qpdf_log_dest_e dest,
|
||||||
|
qpdf_log_fn_t fn,
|
||||||
|
void* udata);
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_set_error(
|
||||||
|
qpdflogger_handle l,
|
||||||
|
enum qpdf_log_dest_e dest,
|
||||||
|
qpdf_log_fn_t fn,
|
||||||
|
void* udata);
|
||||||
|
|
||||||
|
/* A non-zero value for only_if_not_set means that the save
|
||||||
|
* pipeline will only be changed if it is not already set.
|
||||||
|
*/
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_set_save(
|
||||||
|
qpdflogger_handle l,
|
||||||
|
enum qpdf_log_dest_e dest,
|
||||||
|
qpdf_log_fn_t fn,
|
||||||
|
void* udata,
|
||||||
|
int only_if_not_set);
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdflogger_save_to_standard_output(
|
||||||
|
qpdflogger_handle l, int only_if_not_set);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // QPDFLOGGER_H
|
|
@ -110,7 +110,8 @@ set(libqpdf_SOURCES
|
||||||
SF_FlateLzwDecode.cc
|
SF_FlateLzwDecode.cc
|
||||||
SparseOHArray.cc
|
SparseOHArray.cc
|
||||||
qpdf-c.cc
|
qpdf-c.cc
|
||||||
qpdfjob-c.cc)
|
qpdfjob-c.cc
|
||||||
|
qpdflogger-c.cc)
|
||||||
|
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
|
|
|
@ -710,7 +710,7 @@ QPDFJob::checkConfiguration()
|
||||||
save_to_stdout = true;
|
save_to_stdout = true;
|
||||||
}
|
}
|
||||||
if (save_to_stdout) {
|
if (save_to_stdout) {
|
||||||
this->m->log->saveToStandardOutput();
|
this->m->log->saveToStandardOutput(true);
|
||||||
}
|
}
|
||||||
if ((!m->split_pages) &&
|
if ((!m->split_pages) &&
|
||||||
QUtil::same_file(m->infilename.get(), m->outfilename.get())) {
|
QUtil::same_file(m->infilename.get(), m->outfilename.get())) {
|
||||||
|
@ -925,7 +925,7 @@ QPDFJob::doShowObj(QPDF& pdf)
|
||||||
} else {
|
} else {
|
||||||
// If anything has been written to standard output,
|
// If anything has been written to standard output,
|
||||||
// this will fail.
|
// this will fail.
|
||||||
this->m->log->saveToStandardOutput();
|
this->m->log->saveToStandardOutput(true);
|
||||||
obj.pipeStreamData(
|
obj.pipeStreamData(
|
||||||
this->m->log->getSave().get(),
|
this->m->log->getSave().get(),
|
||||||
(filter && m->normalize) ? qpdf_ef_normalize : 0,
|
(filter && m->normalize) ? qpdf_ef_normalize : 0,
|
||||||
|
@ -1031,7 +1031,7 @@ QPDFJob::doShowAttachment(QPDF& pdf)
|
||||||
auto efs = fs->getEmbeddedFileStream();
|
auto efs = fs->getEmbeddedFileStream();
|
||||||
// saveToStandardOutput has already been called, but it's harmless
|
// saveToStandardOutput has already been called, but it's harmless
|
||||||
// to call it again, so do as defensive coding.
|
// 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);
|
efs.pipeStreamData(this->m->log->getSave().get(), 0, qpdf_dl_all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3289,7 +3289,7 @@ QPDFJob::writeOutfile(QPDF& pdf)
|
||||||
} else {
|
} else {
|
||||||
// saveToStandardOutput has already been called, but
|
// saveToStandardOutput has already been called, but
|
||||||
// calling it again is defensive and harmless.
|
// calling it again is defensive and harmless.
|
||||||
this->m->log->saveToStandardOutput();
|
this->m->log->saveToStandardOutput(true);
|
||||||
w.setOutputPipeline(this->m->log->getSave().get());
|
w.setOutputPipeline(this->m->log->getSave().get());
|
||||||
}
|
}
|
||||||
setWriterOptions(pdf, w);
|
setWriterOptions(pdf, w);
|
||||||
|
|
|
@ -181,8 +181,11 @@ QPDFLogger::setError(std::shared_ptr<Pipeline> p)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFLogger::setSave(std::shared_ptr<Pipeline> p)
|
QPDFLogger::setSave(std::shared_ptr<Pipeline> p, bool only_if_not_set)
|
||||||
{
|
{
|
||||||
|
if (only_if_not_set && (this->m->p_save != nullptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this->m->p_save == p) {
|
if (this->m->p_save == p) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -202,9 +205,9 @@ QPDFLogger::setSave(std::shared_ptr<Pipeline> p)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFLogger::saveToStandardOutput()
|
QPDFLogger::saveToStandardOutput(bool only_if_not_set)
|
||||||
{
|
{
|
||||||
setSave(standardOutput());
|
setSave(standardOutput(), only_if_not_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
163
libqpdf/qpdflogger-c.cc
Normal file
163
libqpdf/qpdflogger-c.cc
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
#include <qpdf/qpdflogger-c.h>
|
||||||
|
|
||||||
|
#include <qpdf/Pipeline.hh>
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QPDFLogger.hh>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct _qpdflogger_handle
|
||||||
|
{
|
||||||
|
_qpdflogger_handle(std::shared_ptr<QPDFLogger> l);
|
||||||
|
~_qpdflogger_handle() = default;
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFLogger> 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<char const*>(buf), QIntC::to_ulong(len), udata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionPipeline::finish()
|
||||||
|
{
|
||||||
|
// Nothing needed
|
||||||
|
}
|
||||||
|
|
||||||
|
_qpdflogger_handle::_qpdflogger_handle(std::shared_ptr<QPDFLogger> 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<void(std::shared_ptr<Pipeline>)> 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<FunctionPipeline>(identifier, fn, udata));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_log_dest(
|
||||||
|
QPDFLogger* l,
|
||||||
|
void (QPDFLogger::*method)(std::shared_ptr<Pipeline>),
|
||||||
|
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);
|
||||||
|
}
|
|
@ -33,10 +33,18 @@ set(TEST_PROGRAMS
|
||||||
runlength
|
runlength
|
||||||
sha2
|
sha2
|
||||||
sparse_array)
|
sparse_array)
|
||||||
|
set(TEST_C_PROGRAMS
|
||||||
|
logger_c)
|
||||||
|
|
||||||
foreach(PROG ${TEST_PROGRAMS})
|
foreach(PROG ${TEST_PROGRAMS})
|
||||||
add_executable(${PROG} ${PROG}.cc)
|
add_executable(${PROG} ${PROG}.cc)
|
||||||
target_link_libraries(${PROG} libqpdf_object)
|
target_link_libraries(${PROG} libqpdf_object)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
foreach(PROG ${TEST_C_PROGRAMS})
|
||||||
|
add_executable(${PROG} ${PROG}.c)
|
||||||
|
target_link_libraries(${PROG} libqpdf_object)
|
||||||
|
set_property(TARGET ${PROG} PROPERTY LINKER_LANGUAGE CXX)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
# Since libtests link with the object library and don't use the DLL,
|
# Since libtests link with the object library and don't use the DLL,
|
||||||
# we don't need to (and shouldn't) add the libqpdf target directory to
|
# we don't need to (and shouldn't) add the libqpdf target directory to
|
||||||
|
|
|
@ -22,7 +22,7 @@ test1()
|
||||||
*(logger->getInfo()) << "getSave exception: " << e.what() << "\n";
|
*(logger->getInfo()) << "getSave exception: " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
logger->saveToStandardOutput();
|
logger->saveToStandardOutput(true);
|
||||||
assert(false);
|
assert(false);
|
||||||
} catch (std::logic_error& e) {
|
} catch (std::logic_error& e) {
|
||||||
*(logger->getInfo())
|
*(logger->getInfo())
|
||||||
|
@ -40,12 +40,12 @@ test2()
|
||||||
// First call saveToStandardOutput. Then use info, which then to
|
// First call saveToStandardOutput. Then use info, which then to
|
||||||
// go stderr.
|
// go stderr.
|
||||||
QPDFLogger l;
|
QPDFLogger l;
|
||||||
l.saveToStandardOutput();
|
l.saveToStandardOutput(true);
|
||||||
l.info(std::string("info to stderr\n"));
|
l.info(std::string("info to stderr\n"));
|
||||||
*(l.getSave()) << "save to stdout\n";
|
*(l.getSave()) << "save to stdout\n";
|
||||||
l.setInfo(nullptr);
|
l.setInfo(nullptr);
|
||||||
l.info("info still to stderr\n");
|
l.info("info still to stderr\n");
|
||||||
l.setSave(nullptr);
|
l.setSave(nullptr, false);
|
||||||
l.setInfo(nullptr);
|
l.setInfo(nullptr);
|
||||||
l.info("info back to stdout\n");
|
l.info("info back to stdout\n");
|
||||||
}
|
}
|
||||||
|
|
108
libtests/logger_c.c
Normal file
108
libtests/logger_c.c
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#include <qpdf/assert_test.h>
|
||||||
|
|
||||||
|
#include <qpdf/qpdflogger-c.h>
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
|
#include <qpdf/qpdfjob-c.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
fn(char const* data, size_t len, void* udata)
|
||||||
|
{
|
||||||
|
FILE* f = (FILE*)udata;
|
||||||
|
fwrite(data, 1, len, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_run(char const* json, int exp_status)
|
||||||
|
{
|
||||||
|
int status = qpdfjob_run_from_json(json);
|
||||||
|
assert(status == exp_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE*
|
||||||
|
do_fopen(char const* filename)
|
||||||
|
{
|
||||||
|
FILE* f = NULL;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
if (fopen_s(&f, filename, "wb") != 0) {
|
||||||
|
f = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
f = fopen(filename, "wb");
|
||||||
|
#endif
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "unable to open %s\n", filename);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
FILE* info = do_fopen("info");
|
||||||
|
FILE* warn = do_fopen("warn");
|
||||||
|
FILE* error = do_fopen("error");
|
||||||
|
FILE* save = do_fopen("save");
|
||||||
|
FILE* save2 = do_fopen("save2");
|
||||||
|
qpdflogger_handle l = qpdflogger_default_logger();
|
||||||
|
|
||||||
|
qpdflogger_set_info(l, qpdf_log_dest_custom, fn, (void*)info);
|
||||||
|
qpdflogger_set_warn(l, qpdf_log_dest_custom, fn, (void*)warn);
|
||||||
|
qpdflogger_set_error(l, qpdf_log_dest_custom, fn, (void*)error);
|
||||||
|
qpdflogger_set_save(l, qpdf_log_dest_custom, fn, (void*)save, 0);
|
||||||
|
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"normal.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_success);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"warning.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_warning);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"missing.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_error);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"normal.pdf\","
|
||||||
|
" \"staticId\": \"\","
|
||||||
|
" \"outputFile\": \"-\"}",
|
||||||
|
qpdf_exit_success);
|
||||||
|
|
||||||
|
fclose(info);
|
||||||
|
fclose(warn);
|
||||||
|
fclose(error);
|
||||||
|
fclose(save);
|
||||||
|
|
||||||
|
qpdflogger_set_info(l, qpdf_log_dest_stderr, NULL, NULL);
|
||||||
|
qpdflogger_set_warn(l, qpdf_log_dest_stdout, NULL, NULL);
|
||||||
|
qpdflogger_set_error(l, qpdf_log_dest_default, NULL, NULL);
|
||||||
|
qpdflogger_set_save(l, qpdf_log_dest_custom, fn, (void*)save2, 0);
|
||||||
|
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"2pages.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_success);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"warning.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_warning);
|
||||||
|
do_run(
|
||||||
|
|
||||||
|
"{\"inputFile\": \"missing.pdf\", \"showNpages\": \"\"}",
|
||||||
|
qpdf_exit_error);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"attach.pdf\","
|
||||||
|
" \"showAttachment\": \"a\"}",
|
||||||
|
qpdf_exit_success);
|
||||||
|
|
||||||
|
/* This won't change save since it's already set */
|
||||||
|
qpdflogger_save_to_standard_output(l, 1);
|
||||||
|
do_run(
|
||||||
|
"{\"inputFile\": \"attach.pdf\","
|
||||||
|
" \"showAttachment\": \"a\"}",
|
||||||
|
qpdf_exit_success);
|
||||||
|
|
||||||
|
qpdflogger_cleanup(&l);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -24,10 +24,22 @@ $td->runtest("check stderr",
|
||||||
{$td->FILE => "exp-stderr"},
|
{$td->FILE => "exp-stderr"},
|
||||||
$td->NORMALIZE_NEWLINES);
|
$td->NORMALIZE_NEWLINES);
|
||||||
|
|
||||||
|
$td->runtest("logger C API",
|
||||||
|
{$td->COMMAND => "logger_c >stdout 2>stderr"},
|
||||||
|
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||||
|
$td->NORMALIZE_NEWLINES);
|
||||||
|
foreach my $f (qw(stdout stderr info warn error save save2))
|
||||||
|
{
|
||||||
|
$td->runtest("check $f (C)",
|
||||||
|
{$td->FILE => "$f"},
|
||||||
|
{$td->FILE => "c-exp-$f"},
|
||||||
|
$td->NORMALIZE_NEWLINES);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
$td->report(3);
|
$td->report(11);
|
||||||
|
|
||||||
sub cleanup
|
sub cleanup
|
||||||
{
|
{
|
||||||
unlink "stdout", "stderr";
|
unlink "stdout", "stderr", "info", "warn", "error", "save", "save2";
|
||||||
}
|
}
|
||||||
|
|
BIN
libtests/qtest/logger/2pages.pdf
Normal file
BIN
libtests/qtest/logger/2pages.pdf
Normal file
Binary file not shown.
BIN
libtests/qtest/logger/attach.pdf
Normal file
BIN
libtests/qtest/logger/attach.pdf
Normal file
Binary file not shown.
1
libtests/qtest/logger/c-exp-error
Normal file
1
libtests/qtest/logger/c-exp-error
Normal file
|
@ -0,0 +1 @@
|
||||||
|
qpdfjob json: open missing.pdf: No such file or directory
|
2
libtests/qtest/logger/c-exp-info
Normal file
2
libtests/qtest/logger/c-exp-info
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
1
|
||||||
|
1
|
BIN
libtests/qtest/logger/c-exp-save
Normal file
BIN
libtests/qtest/logger/c-exp-save
Normal file
Binary file not shown.
2
libtests/qtest/logger/c-exp-save2
Normal file
2
libtests/qtest/logger/c-exp-save2
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
quack
|
||||||
|
quack
|
3
libtests/qtest/logger/c-exp-stderr
Normal file
3
libtests/qtest/logger/c-exp-stderr
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
2
|
||||||
|
1
|
||||||
|
qpdfjob json: open missing.pdf: No such file or directory
|
4
libtests/qtest/logger/c-exp-stdout
Normal file
4
libtests/qtest/logger/c-exp-stdout
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
WARNING: warning.pdf: file is damaged
|
||||||
|
WARNING: warning.pdf (offset 1556): xref not found
|
||||||
|
WARNING: warning.pdf: Attempting to reconstruct cross-reference table
|
||||||
|
qpdfjob json: operation succeeded with warnings
|
4
libtests/qtest/logger/c-exp-warn
Normal file
4
libtests/qtest/logger/c-exp-warn
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
WARNING: warning.pdf: file is damaged
|
||||||
|
WARNING: warning.pdf (offset 1556): xref not found
|
||||||
|
WARNING: warning.pdf: Attempting to reconstruct cross-reference table
|
||||||
|
qpdfjob json: operation succeeded with warnings
|
79
libtests/qtest/logger/normal.pdf
Normal file
79
libtests/qtest/logger/normal.pdf
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
%PDF-1.3
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Pages 2 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Kids [
|
||||||
|
3 0 R
|
||||||
|
]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/Parent 2 0 R
|
||||||
|
/MediaBox [0 0 612 792]
|
||||||
|
/Contents 4 0 R
|
||||||
|
/Resources <<
|
||||||
|
/ProcSet 5 0 R
|
||||||
|
/Font <<
|
||||||
|
/F1 6 0 R
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Length 44
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
BT
|
||||||
|
/F1 24 Tf
|
||||||
|
72 720 Td
|
||||||
|
(Potato) Tj
|
||||||
|
ET
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
5 0 obj
|
||||||
|
[
|
||||||
|
/PDF
|
||||||
|
/Text
|
||||||
|
]
|
||||||
|
endobj
|
||||||
|
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type1
|
||||||
|
/Name /F1
|
||||||
|
/BaseFont /Helvetica
|
||||||
|
/Encoding /WinAnsiEncoding
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 7
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000009 00000 n
|
||||||
|
0000000063 00000 n
|
||||||
|
0000000135 00000 n
|
||||||
|
0000000307 00000 n
|
||||||
|
0000000403 00000 n
|
||||||
|
0000000438 00000 n
|
||||||
|
trailer <<
|
||||||
|
/Size 7
|
||||||
|
/Root 1 0 R
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
556
|
||||||
|
%%EOF
|
79
libtests/qtest/logger/warning.pdf
Normal file
79
libtests/qtest/logger/warning.pdf
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
%PDF-1.3
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Catalog
|
||||||
|
/Pages 2 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Pages
|
||||||
|
/Kids [
|
||||||
|
3 0 R
|
||||||
|
]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Page
|
||||||
|
/Parent 2 0 R
|
||||||
|
/MediaBox [0 0 612 792]
|
||||||
|
/Contents 4 0 R
|
||||||
|
/Resources <<
|
||||||
|
/ProcSet 5 0 R
|
||||||
|
/Font <<
|
||||||
|
/F1 6 0 R
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Length 44
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
BT
|
||||||
|
/F1 24 Tf
|
||||||
|
72 720 Td
|
||||||
|
(Potato) Tj
|
||||||
|
ET
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
5 0 obj
|
||||||
|
[
|
||||||
|
/PDF
|
||||||
|
/Text
|
||||||
|
]
|
||||||
|
endobj
|
||||||
|
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/Type /Font
|
||||||
|
/Subtype /Type1
|
||||||
|
/Name /F1
|
||||||
|
/BaseFont /Helvetica
|
||||||
|
/Encoding /WinAnsiEncoding
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 7
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000009 00000 n
|
||||||
|
0000000063 00000 n
|
||||||
|
0000000135 00000 n
|
||||||
|
0000000307 00000 n
|
||||||
|
0000000403 00000 n
|
||||||
|
0000000438 00000 n
|
||||||
|
trailer <<
|
||||||
|
/Size 7
|
||||||
|
/Root 1 0 R
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
1556
|
||||||
|
%%EOF
|
|
@ -158,6 +158,8 @@ For a detailed list of changes, please see the file
|
||||||
output and errors that slipped through the cracks with
|
output and errors that slipped through the cracks with
|
||||||
``setOutputStreams``.
|
``setOutputStreams``.
|
||||||
|
|
||||||
|
- A C API is available in :file:`include/qpdf/qpdflogger-c.h`.
|
||||||
|
|
||||||
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
|
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
|
||||||
``eraseItemAndGet``, ``replaceKeyAndGet``, and
|
``eraseItemAndGet``, ``replaceKeyAndGet``, and
|
||||||
``removeKeyAndGet`` return the newly added or removed object.
|
``removeKeyAndGet`` return the newly added or removed object.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user