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

Add qpdfjob-c.h -- simple C API around parts of QPDFJob

This commit is contained in:
Jay Berkenbilt 2022-02-01 08:55:18 -05:00
parent 03e67a28fe
commit bc4e2320e7
12 changed files with 245 additions and 5 deletions

79
include/qpdf/qpdfjob-c.h Normal file
View File

@ -0,0 +1,79 @@
/* Copyright (c) 2005-2021 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 QPDFJOB_C_H
#define QPDFJOB_C_H
/*
* This file defines a basic "C" API for QPDFJob. See also qpdf-c.h,
* which defines an API that exposes more of the library's API. This
* API is primarily intended to make it simpler for programs in
* languages other than C++ to incorporate functionality that could be
* run directly from the command-line.
*/
#include <qpdf/DLL.h>
#include <string.h>
#ifndef QPDF_NO_WCHAR_T
# include <wchar.h>
#endif
/*
* This file provides a minimal wrapper around QPDFJob. See
* examples/qpdf-job.c for an example of its use.
*/
#ifdef __cplusplus
extern "C" {
#endif
/* This function does the equivalent of running the qpdf
* command-line with the given arguments and returns the exit code
* that qpdf would use. Note that arguments must be UTF8-encoded.
* If calling this from wmain on Windows, use
* qpdfjob_run_from_wide_argv instead.
*/
QPDF_DLL
int qpdfjob_run_from_argv(int argc, char* argv[]);
#ifndef QPDF_NO_WCHAR_T
/* This function is the same as qpdfjob_run_from_argv except argv
* is encoded with wide characters. This would suitable for
* calling from a Windows wmain function.
*/
QPDF_DLL
int qpdfjob_run_from_wide_argv(int argc, wchar_t* argv[]);
#endif /* QPDF_NO_WCHAR_T */
/* This function runs QPDFJob from a job JSON file. See the "QPDF
* Job" section of the manual for details. The JSON string must be
* UTF8-encoded. It returns the error code that qpdf would return
* with the equivalent command-line invocation.
*/
QPDF_DLL
int qpdfjob_run_from_json(char const* json);
#ifdef __cplusplus
}
#endif
#endif /* QPDFJOB_C_H */

View File

@ -115,7 +115,8 @@ SRCS_libqpdf = \
libqpdf/SecureRandomDataProvider.cc \ libqpdf/SecureRandomDataProvider.cc \
libqpdf/SF_FlateLzwDecode.cc \ libqpdf/SF_FlateLzwDecode.cc \
libqpdf/SparseOHArray.cc \ libqpdf/SparseOHArray.cc \
libqpdf/qpdf-c.cc libqpdf/qpdf-c.cc \
libqpdf/qpdfjob-c.cc
ifeq ($(USE_CRYPTO_NATIVE), 1) ifeq ($(USE_CRYPTO_NATIVE), 1)
SRCS_libqpdf += $(CRYPTO_NATIVE) SRCS_libqpdf += $(CRYPTO_NATIVE)

50
libqpdf/qpdfjob-c.cc Normal file
View File

@ -0,0 +1,50 @@
#include <qpdf/qpdfjob-c.h>
#include <qpdf/QPDFJob.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QPDFUsage.hh>
#include <cstdio>
#include <cstring>
int qpdfjob_run_from_argv(int argc, char* argv[])
{
auto whoami = QUtil::getWhoami(argv[0]);
QUtil::setLineBuf(stdout);
QPDFJob j;
try
{
j.initializeFromArgv(argc, argv);
j.run();
}
catch (std::exception& e)
{
std::cerr << whoami << ": " << e.what() << std::endl;
return QPDFJob::EXIT_ERROR;
}
return j.getExitCode();
}
#ifndef QPDF_NO_WCHAR_T
int qpdfjob_run_from_wide_argv(int argc, wchar_t* argv[])
{
return QUtil::call_main_from_wmain(argc, argv, qpdfjob_run_from_argv);
}
#endif // QPDF_NO_WCHAR_T
int qpdfjob_run_from_json(char const* json)
{
QPDFJob j;
try
{
j.initializeFromJson(json);
j.run();
}
catch (std::exception& e)
{
std::cerr << "qpdfjob json: " << e.what() << std::endl;
return QPDFJob::EXIT_ERROR;
}
return j.getExitCode();
}

View File

@ -14,7 +14,7 @@ executable is available from inside the C++ library using the
- Use from the C++ API with ``QPDFJob::initializeFromArgv`` - Use from the C++ API with ``QPDFJob::initializeFromArgv``
- Use from the C API with QXXXQ - Use from the C API with ``qpdfjob_run_from_argv`` from :file:`qpdfjob-c.h`
- The job JSON file format - The job JSON file format
@ -22,7 +22,7 @@ executable is available from inside the C++ library using the
- Use from the C++ API with ``QPDFJob::initializeFromJson`` - Use from the C++ API with ``QPDFJob::initializeFromJson``
- Use from the C API with QXXXQ - Use from the C API with ``qpdfjob_run_from_json`` from :file:`qpdfjob-c.h`
- The ``QPDFJob`` C++ API - The ``QPDFJob`` C++ API

View File

@ -12,7 +12,9 @@ BINS_qpdf = \
test_tokenizer \ test_tokenizer \
test_unicode_filenames \ test_unicode_filenames \
test_xref test_xref
CBINS_qpdf = qpdf-ctest CBINS_qpdf = \
qpdf-ctest \
qpdfjob-ctest
TARGETS_qpdf = $(foreach B,$(BINS_qpdf) $(CBINS_qpdf),qpdf/$(OUTPUT_DIR)/$(call binname,$(B))) TARGETS_qpdf = $(foreach B,$(BINS_qpdf) $(CBINS_qpdf),qpdf/$(OUTPUT_DIR)/$(call binname,$(B)))

73
qpdf/qpdfjob-ctest.c Normal file
View File

@ -0,0 +1,73 @@
#include <qpdf/qpdfjob-c.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifndef QPDF_NO_WCHAR_T
static void wide_test()
{
wchar_t* argv[5];
argv[0] = (wchar_t*)(L"qpdfjob");
argv[1] = (wchar_t*)(L"minimal.pdf");
argv[2] = (wchar_t*)(L"a.pdf");
argv[3] = (wchar_t*)(L"--static-id");
argv[4] = NULL;
assert(qpdfjob_run_from_wide_argv(4, argv) == 0);
printf("wide test passed\n");
}
#endif // QPDF_NO_WCHAR_T
static void run_tests()
{
/* Be sure to use a different output file for each test. */
char* argv[5];
argv[0] = (char*)("qpdfjob");
argv[1] = (char*)("minimal.pdf");
argv[2] = (char*)("a.pdf");
argv[3] = (char*)("--deterministic-id");
argv[4] = NULL;
assert(qpdfjob_run_from_argv(4, argv) == 0);
printf("argv test passed\n");
assert(qpdfjob_run_from_json("{\n\
\"inputFile\": \"20-pages.pdf\",\n\
\"password\": \"user\",\n\
\"outputFile\": \"b.pdf\",\n\
\"staticId\": \"\",\n\
\"decrypt\": \"\",\n\
\"objectStreams\": \"generate\"\n\
}") == 0);
printf("json test passed\n");
assert(qpdfjob_run_from_json("{\n\
\"inputFile\": \"xref-with-short-size.pdf\",\n\
\"outputFile\": \"c.pdf\",\n\
\"staticId\": \"\",\n\
\"decrypt\": \"\",\n\
\"objectStreams\": \"generate\"\n\
}") == 3);
printf("json warn test passed\n");
assert(qpdfjob_run_from_json("{\n\
\"inputFile\": \"nothing-there.pdf\"\n\
}") == 2);
printf("json error test passed\n");
}
int main(int argc, char* argv[])
{
if ((argc == 2) && (strcmp(argv[1], "wide") == 0))
{
#ifndef QPDF_NO_WCHAR_T
wide_test();
#else
printf("skipped wide\n");
#endif // QPDF_NO_WCHAR_T
return 0;
}
run_tests();
return 0;
}

View File

@ -402,7 +402,7 @@ my @good_json = (
"underlay-overlay-password", "underlay-overlay-password",
"misc-options", "misc-options",
); );
$n_tests += 4 + scalar(@bad_json) + (2 * scalar(@good_json)); $n_tests += 10 + scalar(@bad_json) + (2 * scalar(@good_json));
foreach my $i (@bad_json) foreach my $i (@bad_json)
@ -457,6 +457,34 @@ $td->runtest("json output from job",
{$td->FILE => "job-json-output.out.json", $td->EXIT_STATUS => 0}, {$td->FILE => "job-json-output.out.json", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES); $td->NORMALIZE_NEWLINES);
$td->runtest("C job API",
{$td->COMMAND => "qpdfjob-ctest"},
{$td->FILE => "qpdfjob-ctest.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
foreach my $i (['a.pdf', 1], ['b.pdf', 2], ['c.pdf', 3])
{
$td->runtest("check output",
{$td->FILE => $i->[0]},
{$td->FILE => "qpdfjob-ctest$i->[1].pdf"});
}
my $wide_out = `qpdfjob-ctest wide`;
$td->runtest("qpdfjob-ctest wide",
{$td->STRING => "$?: $wide_out"},
{$td->REGEXP => "0: (wide test passed|skipped wide)\n"},
$td->NORMALIZE_NEWLINES);
if ($wide_out =~ m/skipped/)
{
$td->runtest("skipped wide",
{$td->STRING => "yes"},
{$td->STRING => "yes"});
}
else
{
$td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "qpdfjob-ctest-wide.pdf"});
}
show_ntests(); show_ntests();
# ---------- # ----------
$td->notify("--- Form Tests ---"); $td->notify("--- Form Tests ---");

Binary file not shown.

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.