mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add examples for output capture (fixes #691)
This commit is contained in:
parent
8130d50e3b
commit
8e361d98f0
17
TODO
17
TODO
@ -9,12 +9,12 @@ Before Release:
|
||||
* Release qtest with updates to qtest-driver and copy back into qpdf
|
||||
|
||||
Next:
|
||||
* output capture
|
||||
* QPDFPagesTree -- avoid ever flattening the pages tree.
|
||||
* JSON v2 fixes
|
||||
|
||||
Pending changes:
|
||||
|
||||
* Allow users to supply a custom progress reporter for QPDFJob
|
||||
* Check about runpath in the linux-bin distribution. I think the
|
||||
appimage build specifically is setting the runpath, which is
|
||||
actually desirable in this case. Make sure to understand and
|
||||
@ -42,21 +42,6 @@ Pending changes:
|
||||
|
||||
Soon: Break ground on "Document-level work"
|
||||
|
||||
Output Capture + QPDFJob
|
||||
========================
|
||||
|
||||
QPDFJob:
|
||||
|
||||
* Allow users to supply a custom progress reporter for QPDFJob
|
||||
|
||||
Output Capture
|
||||
|
||||
See https://github.com/qpdf/qpdf/issues/691
|
||||
|
||||
There needs to be a C API to QPDFLogger. Use functions like this:
|
||||
|
||||
void set_info((*f)(char* data, unsigned int len, void* udata), void* udata);
|
||||
|
||||
|
||||
QPDFPagesTree
|
||||
=============
|
||||
|
@ -14,11 +14,13 @@ set(EXAMPLE_CXX_PROGRAMS
|
||||
pdf-parse-content
|
||||
pdf-set-form-values
|
||||
pdf-split-pages
|
||||
qpdf-job)
|
||||
qpdf-job
|
||||
qpdfjob-save-attachment)
|
||||
set(EXAMPLE_C_PROGRAMS
|
||||
pdf-c-objects
|
||||
pdf-linearize
|
||||
qpdfjob-c)
|
||||
qpdfjob-c
|
||||
qpdfjob-c-save-attachment)
|
||||
|
||||
foreach(PROG ${EXAMPLE_CXX_PROGRAMS})
|
||||
add_executable(${PROG} ${PROG}.cc)
|
||||
|
100
examples/qpdfjob-c-save-attachment.c
Normal file
100
examples/qpdfjob-c-save-attachment.c
Normal file
@ -0,0 +1,100 @@
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/qpdfjob-c.h>
|
||||
#include <qpdf/qpdflogger-c.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// This example demonstrates how we can redirect where saved output
|
||||
// goes by calling the default logger's setSave method before running
|
||||
// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
|
||||
// implementation that uses the C API.
|
||||
|
||||
static void
|
||||
save_to_file(char const* data, size_t len, void* udata)
|
||||
{
|
||||
FILE* f = (FILE*)udata;
|
||||
fwrite(data, 1, len, f);
|
||||
}
|
||||
|
||||
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(int argc, char* argv[])
|
||||
{
|
||||
char const* whoami = "qpdfjob-c-save-attachment";
|
||||
char const* filename = NULL;
|
||||
char const* key = NULL;
|
||||
char const* outfilename = NULL;
|
||||
char* attachment_arg = NULL;
|
||||
char const* attachment_flag = "--show-attachment=";
|
||||
size_t flag_len = 0;
|
||||
FILE* outfile = NULL;
|
||||
int status = 0;
|
||||
qpdfjob_handle j = NULL;
|
||||
qpdflogger_handle l = qpdflogger_default_logger();
|
||||
|
||||
if (argc != 4) {
|
||||
fprintf(stderr, "Usage: %s file attachment-key outfile\n", whoami);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
key = argv[2];
|
||||
outfilename = argv[3];
|
||||
|
||||
flag_len = strlen(attachment_flag) + strlen(key) + 1;
|
||||
attachment_arg = malloc(flag_len);
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(attachment_arg, flag_len, attachment_flag, flag_len);
|
||||
strncat_s(attachment_arg, flag_len, key, flag_len - strlen(attachment_arg));
|
||||
#else
|
||||
strncpy(attachment_arg, attachment_flag, flag_len);
|
||||
strncat(attachment_arg, key, flag_len - strlen(attachment_arg));
|
||||
#endif
|
||||
|
||||
char const* j_argv[5] = {
|
||||
whoami,
|
||||
filename,
|
||||
attachment_arg,
|
||||
"--",
|
||||
NULL,
|
||||
};
|
||||
outfile = do_fopen(outfilename);
|
||||
|
||||
/* Use qpdflogger_set_save with a callback function to redirect
|
||||
* saved data. You can use other qpdf logger functions to capture
|
||||
* informational output, warnings, and errors.
|
||||
*/
|
||||
qpdflogger_set_save(
|
||||
l, qpdf_log_dest_custom, save_to_file, (void*)outfile, 0);
|
||||
qpdflogger_cleanup(&l);
|
||||
j = qpdfjob_init();
|
||||
status = (qpdfjob_initialize_from_argv(j, j_argv) ||
|
||||
qpdfjob_run(j));
|
||||
qpdfjob_cleanup(&j);
|
||||
free(attachment_arg);
|
||||
fclose(outfile);
|
||||
if (status == qpdf_exit_success) {
|
||||
printf("%s: wrote attachment to %s\n", whoami, outfilename);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -52,6 +52,10 @@ main(int argc, char* argv[])
|
||||
* To use that from C just like the argv one, call
|
||||
* qpdfjob_run_from_json instead and pass the json string as a
|
||||
* single char const* argument.
|
||||
*
|
||||
* See qpdfjob-c-save-attachment.c for an example of using the
|
||||
* full form of the qpdfjob interface with init and cleanup
|
||||
* functions.
|
||||
*/
|
||||
r = qpdfjob_run_from_argv(new_argv);
|
||||
return r;
|
||||
|
51
examples/qpdfjob-save-attachment.cc
Normal file
51
examples/qpdfjob-save-attachment.cc
Normal file
@ -0,0 +1,51 @@
|
||||
#include <qpdf/Pl_StdioFile.hh>
|
||||
#include <qpdf/QPDFJob.hh>
|
||||
#include <qpdf/QPDFLogger.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
// This example demonstrates how we can redirect where saved output
|
||||
// goes by calling the default logger's setSave method before running
|
||||
// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
|
||||
// implementation that uses the C API.
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
auto whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << whoami << " file attachment-key outfile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
char const* filename = argv[1];
|
||||
char const* key = argv[2];
|
||||
char const* outfilename = argv[3];
|
||||
std::string attachment_arg = "--show-attachment=";
|
||||
attachment_arg += key;
|
||||
|
||||
char const* j_argv[] = {
|
||||
whoami,
|
||||
filename,
|
||||
attachment_arg.c_str(),
|
||||
"--",
|
||||
nullptr,
|
||||
};
|
||||
|
||||
QUtil::FileCloser fc(QUtil::safe_fopen(outfilename, "wb"));
|
||||
auto save = std::make_shared<Pl_StdioFile>("capture", fc.f);
|
||||
QPDFLogger::defaultLogger()->setSave(save, false);
|
||||
|
||||
try {
|
||||
QPDFJob j;
|
||||
j.initializeFromArgv(j_argv);
|
||||
j.run();
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
std::cout << whoami << ": wrote attachment to " << outfilename << std::endl;
|
||||
return 0;
|
||||
}
|
BIN
examples/qtest/qpdfjob-attachment/attach.pdf
Normal file
BIN
examples/qtest/qpdfjob-attachment/attach.pdf
Normal file
Binary file not shown.
42
examples/qtest/save-attachment.test
Normal file
42
examples/qtest/save-attachment.test
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
chdir("qpdfjob-attachment") or die "chdir testdir failed: $!\n";
|
||||
|
||||
require TestDriver;
|
||||
|
||||
cleanup();
|
||||
|
||||
my $td = new TestDriver('qpdfjob-attachment');
|
||||
|
||||
$td->runtest("save attachment (C)",
|
||||
{$td->COMMAND => "qpdfjob-c-save-attachment attach.pdf a a"},
|
||||
{$td->STRING =>
|
||||
"qpdfjob-c-save-attachment: wrote attachment to a\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a"},
|
||||
{$td->STRING => "quack\n"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("save attachment (C++)",
|
||||
{$td->COMMAND => "qpdfjob-save-attachment attach.pdf a b"},
|
||||
{$td->STRING =>
|
||||
"qpdfjob-save-attachment: wrote attachment to b\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "b"},
|
||||
{$td->STRING => "quack\n"},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
cleanup();
|
||||
|
||||
$td->report(4);
|
||||
|
||||
sub cleanup
|
||||
{
|
||||
unlink "a", "b";
|
||||
}
|
@ -56,6 +56,10 @@ class QPDFLogger
|
||||
// error -- standard error
|
||||
// save -- undefined unless set
|
||||
//
|
||||
// "info" is used for diagnostic messages, verbose messages, and
|
||||
// progress messages. "warn" is used for warnings. "error" is used
|
||||
// for errors. "save" is used for saving output -- see below.
|
||||
//
|
||||
// On deletion, finish() is called for the standard output and
|
||||
// standard error pipelines, which flushes output. If you supply
|
||||
// any custom pipelines, you must call finish() on them yourself.
|
||||
@ -64,6 +68,13 @@ class QPDFLogger
|
||||
//
|
||||
// NOTES ABOUT THE SAVE PIPELINE
|
||||
//
|
||||
// The save pipeline is used by QPDFJob when some kind of binary
|
||||
// output is being saved. This includes saving attachments and
|
||||
// stream data and also includes when the output file is standard
|
||||
// output. If you want to grab that output, you can call setSave.
|
||||
// See examples/qpdfjob-save-attachment.cc and
|
||||
// examples/qpdfjob-c-save-attachment.c.
|
||||
//
|
||||
// You should never set the save pipeline to the same destination
|
||||
// as something else. Doing so will corrupt your save output. If
|
||||
// you want to save to standard output, use the method
|
||||
|
@ -25,7 +25,8 @@
|
||||
|
||||
/*
|
||||
* This file provides a C API for QPDFLogger. See QPDFLogger.hh for
|
||||
* information about the logger.
|
||||
* information about the logger and
|
||||
* examples/qpdfjob-c-save-attachment.c for an example.
|
||||
*/
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
@ -160,6 +160,9 @@ For a detailed list of changes, please see the file
|
||||
|
||||
- A C API is available in :file:`include/qpdf/qpdflogger-c.h`.
|
||||
|
||||
- See examples :file:`examples/qpdfjob-save-attachment.cc` and
|
||||
:file:`examples/qpdfjob-c-save-attachment.cc`.
|
||||
|
||||
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
|
||||
``eraseItemAndGet``, ``replaceKeyAndGet``, and
|
||||
``removeKeyAndGet`` return the newly added or removed object.
|
||||
|
Loading…
Reference in New Issue
Block a user