aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-06-19 14:56:36 +0200
committerJay Berkenbilt <ejb@ql.org>2022-06-19 15:12:29 +0200
commiteae75dbe448b0395aee7e49c2a9cca9f82680782 (patch)
treeea5a9edfbd52ca5c381e5f97f79e46693d4b2beb
parentbb0ea2f8e7d8fffa575b291004e4426138c7bb1a (diff)
downloadqpdf-eae75dbe448b0395aee7e49c2a9cca9f82680782.tar.zst
Add Pl_Function -- a generic function pipeline
-rw-r--r--include/qpdf/Pl_Function.hh73
-rw-r--r--include/qpdf/Pl_String.hh10
-rw-r--r--libqpdf/CMakeLists.txt1
-rw-r--r--libqpdf/Pl_Function.cc39
-rw-r--r--libtests/CMakeLists.txt1
-rw-r--r--libtests/pl_function.cc29
-rw-r--r--libtests/qtest/pl_function.test17
-rw-r--r--libtests/qtest/pl_function/exp2
-rw-r--r--qpdf/sizes.cc2
9 files changed, 169 insertions, 5 deletions
diff --git a/include/qpdf/Pl_Function.hh b/include/qpdf/Pl_Function.hh
new file mode 100644
index 00000000..dd700e80
--- /dev/null
+++ b/include/qpdf/Pl_Function.hh
@@ -0,0 +1,73 @@
+// 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 PL_FUNCTION_HH
+#define PL_FUNCTION_HH
+
+// This pipeline calls an arbitrary function with whatever data is
+// passed to it. This pipeline can be reused.
+//
+// For this pipeline, "next" may be null. If a next pointer is
+// provided, this pipeline will also pass the data through to it and
+// will forward finish() to it.
+//
+// It is okay to not call finish() on this pipeline if it has no
+// "next".
+
+#include <qpdf/Pipeline.hh>
+
+#include <functional>
+
+class QPDF_DLL_CLASS Pl_Function: public Pipeline
+{
+ public:
+ typedef std::function<void(unsigned char const*, size_t)> writer_t;
+
+ QPDF_DLL
+ Pl_Function(char const* identifier, Pipeline* next, writer_t fn);
+ QPDF_DLL
+ virtual ~Pl_Function();
+
+ QPDF_DLL
+ virtual void write(unsigned char const* buf, size_t len);
+ QPDF_DLL
+ virtual void finish();
+
+ private:
+ class QPDF_DLL_PRIVATE Members
+ {
+ friend class Pl_Function;
+
+ public:
+ QPDF_DLL
+ ~Members() = default;
+
+ private:
+ Members(writer_t);
+ Members(Members const&) = delete;
+
+ writer_t fn;
+ };
+
+ std::shared_ptr<Members> m;
+};
+
+#endif // PL_FUNCTION_HH
diff --git a/include/qpdf/Pl_String.hh b/include/qpdf/Pl_String.hh
index 327598da..906a2660 100644
--- a/include/qpdf/Pl_String.hh
+++ b/include/qpdf/Pl_String.hh
@@ -30,11 +30,11 @@
// provided, this pipeline will also pass the data through to it and
// will forward finish() to it.
//
-// It is okay to not call finish() on this pipeline. This makes it
-// easy to stick this in front of another pipeline to capture data
-// that is written to the other pipeline without interfering with when
-// finish is called on the other pipeline and without having to put a
-// Pl_Concatenate after it.
+// It is okay to not call finish() on this pipeline if it has no
+// "next". This makes it easy to stick this in front of another
+// pipeline to capture data that is written to the other pipeline
+// without interfering with when finish is called on the other
+// pipeline and without having to put a Pl_Concatenate after it.
#include <qpdf/Pipeline.hh>
diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt
index 3c14115b..a6e30163 100644
--- a/libqpdf/CMakeLists.txt
+++ b/libqpdf/CMakeLists.txt
@@ -42,6 +42,7 @@ set(libqpdf_SOURCES
Pl_DCT.cc
Pl_Discard.cc
Pl_Flate.cc
+ Pl_Function.cc
Pl_LZWDecoder.cc
Pl_MD5.cc
Pl_OStream.cc
diff --git a/libqpdf/Pl_Function.cc b/libqpdf/Pl_Function.cc
new file mode 100644
index 00000000..32fcccf1
--- /dev/null
+++ b/libqpdf/Pl_Function.cc
@@ -0,0 +1,39 @@
+#include <qpdf/Pl_Function.hh>
+
+#include <qpdf/QUtil.hh>
+#include <errno.h>
+#include <stdexcept>
+
+Pl_Function::Members::Members(writer_t fn) :
+ fn(fn)
+{
+}
+
+Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_t fn) :
+ Pipeline(identifier, next),
+ m(new Members(fn))
+{
+}
+
+Pl_Function::~Pl_Function()
+{
+ // Must be explicit and not inline -- see QPDF_DLL_CLASS in
+ // README-maintainer
+}
+
+void
+Pl_Function::write(unsigned char const* buf, size_t len)
+{
+ this->m->fn(buf, len);
+ if (getNext(true)) {
+ getNext()->write(buf, len);
+ }
+}
+
+void
+Pl_Function::finish()
+{
+ if (getNext(true)) {
+ getNext()->finish();
+ }
+}
diff --git a/libtests/CMakeLists.txt b/libtests/CMakeLists.txt
index 62ba390e..ea4dc7cd 100644
--- a/libtests/CMakeLists.txt
+++ b/libtests/CMakeLists.txt
@@ -24,6 +24,7 @@ set(TEST_PROGRAMS
nntree
numrange
pdf_version
+ pl_function
pointer_holder
predictors
qintc
diff --git a/libtests/pl_function.cc b/libtests/pl_function.cc
new file mode 100644
index 00000000..960ad5cb
--- /dev/null
+++ b/libtests/pl_function.cc
@@ -0,0 +1,29 @@
+#include <qpdf/assert_test.h>
+
+#include <qpdf/Pl_Function.hh>
+#include <qpdf/Pl_String.hh>
+#include <qpdf/Pl_Base64.hh>
+#include <iostream>
+
+int
+main(int argc, char* argv[])
+{
+ Pl_Function p1(
+ "p1", nullptr, [](unsigned char const* data, size_t len) {
+ std::cout << "p1: " << len << ": " << data << std::endl;
+ });
+ p1.write(reinterpret_cast<unsigned char const*>("potato"), 6);
+
+ std::string s;
+ Pl_String ps("string", nullptr, s);
+ Pl_Base64 b("base64", &ps, Pl_Base64::a_encode);
+ Pl_Function p2(
+ "p2", &b, [](unsigned char const* data, size_t len) {
+ std::cout << "p2: " << len << ": " << data << std::endl;
+ });
+ p2.write(reinterpret_cast<unsigned char const*>("salad"), 5);
+ p2.finish();
+ assert(s == "c2FsYWQ=");
+
+ return 0;
+}
diff --git a/libtests/qtest/pl_function.test b/libtests/qtest/pl_function.test
new file mode 100644
index 00000000..847aa472
--- /dev/null
+++ b/libtests/qtest/pl_function.test
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+require 5.008;
+use warnings;
+use strict;
+
+chdir("pl_function") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+my $td = new TestDriver('pl_function');
+
+$td->runtest("pl_function",
+ {$td->COMMAND => "pl_function"},
+ {$td->FILE => "exp", $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+
+$td->report(1);
diff --git a/libtests/qtest/pl_function/exp b/libtests/qtest/pl_function/exp
new file mode 100644
index 00000000..fd2ea1bc
--- /dev/null
+++ b/libtests/qtest/pl_function/exp
@@ -0,0 +1,2 @@
+p1: 6: potato
+p2: 5: salad
diff --git a/qpdf/sizes.cc b/qpdf/sizes.cc
index 6d4635fd..12843ab2 100644
--- a/qpdf/sizes.cc
+++ b/qpdf/sizes.cc
@@ -16,6 +16,7 @@
#include <qpdf/Pl_DCT.hh>
#include <qpdf/Pl_Discard.hh>
#include <qpdf/Pl_Flate.hh>
+#include <qpdf/Pl_Function.hh>
#include <qpdf/Pl_OStream.hh>
#include <qpdf/Pl_QPDFTokenizer.hh>
#include <qpdf/Pl_RunLength.hh>
@@ -78,6 +79,7 @@ main()
print_size(Pl_DCT);
print_size(Pl_Discard);
print_size(Pl_Flate);
+ print_size(Pl_Function);
print_size(Pl_OStream);
print_size(Pl_QPDFTokenizer);
print_size(Pl_RunLength);