Commit eae75dbe448b0395aee7e49c2a9cca9f82680782

Authored by Jay Berkenbilt
1 parent bb0ea2f8

Add Pl_Function -- a generic function pipeline

include/qpdf/Pl_Function.hh 0 → 100644
  1 +// Copyright (c) 2005-2022 Jay Berkenbilt
  2 +//
  3 +// This file is part of qpdf.
  4 +//
  5 +// Licensed under the Apache License, Version 2.0 (the "License");
  6 +// you may not use this file except in compliance with the License.
  7 +// You may obtain a copy of the License at
  8 +//
  9 +// http://www.apache.org/licenses/LICENSE-2.0
  10 +//
  11 +// Unless required by applicable law or agreed to in writing, software
  12 +// distributed under the License is distributed on an "AS IS" BASIS,
  13 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 +// See the License for the specific language governing permissions and
  15 +// limitations under the License.
  16 +//
  17 +// Versions of qpdf prior to version 7 were released under the terms
  18 +// of version 2.0 of the Artistic License. At your option, you may
  19 +// continue to consider qpdf to be licensed under those terms. Please
  20 +// see the manual for additional information.
  21 +
  22 +#ifndef PL_FUNCTION_HH
  23 +#define PL_FUNCTION_HH
  24 +
  25 +// This pipeline calls an arbitrary function with whatever data is
  26 +// passed to it. This pipeline can be reused.
  27 +//
  28 +// For this pipeline, "next" may be null. If a next pointer is
  29 +// provided, this pipeline will also pass the data through to it and
  30 +// will forward finish() to it.
  31 +//
  32 +// It is okay to not call finish() on this pipeline if it has no
  33 +// "next".
  34 +
  35 +#include <qpdf/Pipeline.hh>
  36 +
  37 +#include <functional>
  38 +
  39 +class QPDF_DLL_CLASS Pl_Function: public Pipeline
  40 +{
  41 + public:
  42 + typedef std::function<void(unsigned char const*, size_t)> writer_t;
  43 +
  44 + QPDF_DLL
  45 + Pl_Function(char const* identifier, Pipeline* next, writer_t fn);
  46 + QPDF_DLL
  47 + virtual ~Pl_Function();
  48 +
  49 + QPDF_DLL
  50 + virtual void write(unsigned char const* buf, size_t len);
  51 + QPDF_DLL
  52 + virtual void finish();
  53 +
  54 + private:
  55 + class QPDF_DLL_PRIVATE Members
  56 + {
  57 + friend class Pl_Function;
  58 +
  59 + public:
  60 + QPDF_DLL
  61 + ~Members() = default;
  62 +
  63 + private:
  64 + Members(writer_t);
  65 + Members(Members const&) = delete;
  66 +
  67 + writer_t fn;
  68 + };
  69 +
  70 + std::shared_ptr<Members> m;
  71 +};
  72 +
  73 +#endif // PL_FUNCTION_HH
... ...
include/qpdf/Pl_String.hh
... ... @@ -30,11 +30,11 @@
30 30 // provided, this pipeline will also pass the data through to it and
31 31 // will forward finish() to it.
32 32 //
33   -// It is okay to not call finish() on this pipeline. This makes it
34   -// easy to stick this in front of another pipeline to capture data
35   -// that is written to the other pipeline without interfering with when
36   -// finish is called on the other pipeline and without having to put a
37   -// Pl_Concatenate after it.
  33 +// It is okay to not call finish() on this pipeline if it has no
  34 +// "next". This makes it easy to stick this in front of another
  35 +// pipeline to capture data that is written to the other pipeline
  36 +// without interfering with when finish is called on the other
  37 +// pipeline and without having to put a Pl_Concatenate after it.
38 38  
39 39 #include <qpdf/Pipeline.hh>
40 40  
... ...
libqpdf/CMakeLists.txt
... ... @@ -42,6 +42,7 @@ set(libqpdf_SOURCES
42 42 Pl_DCT.cc
43 43 Pl_Discard.cc
44 44 Pl_Flate.cc
  45 + Pl_Function.cc
45 46 Pl_LZWDecoder.cc
46 47 Pl_MD5.cc
47 48 Pl_OStream.cc
... ...
libqpdf/Pl_Function.cc 0 → 100644
  1 +#include <qpdf/Pl_Function.hh>
  2 +
  3 +#include <qpdf/QUtil.hh>
  4 +#include <errno.h>
  5 +#include <stdexcept>
  6 +
  7 +Pl_Function::Members::Members(writer_t fn) :
  8 + fn(fn)
  9 +{
  10 +}
  11 +
  12 +Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_t fn) :
  13 + Pipeline(identifier, next),
  14 + m(new Members(fn))
  15 +{
  16 +}
  17 +
  18 +Pl_Function::~Pl_Function()
  19 +{
  20 + // Must be explicit and not inline -- see QPDF_DLL_CLASS in
  21 + // README-maintainer
  22 +}
  23 +
  24 +void
  25 +Pl_Function::write(unsigned char const* buf, size_t len)
  26 +{
  27 + this->m->fn(buf, len);
  28 + if (getNext(true)) {
  29 + getNext()->write(buf, len);
  30 + }
  31 +}
  32 +
  33 +void
  34 +Pl_Function::finish()
  35 +{
  36 + if (getNext(true)) {
  37 + getNext()->finish();
  38 + }
  39 +}
... ...
libtests/CMakeLists.txt
... ... @@ -24,6 +24,7 @@ set(TEST_PROGRAMS
24 24 nntree
25 25 numrange
26 26 pdf_version
  27 + pl_function
27 28 pointer_holder
28 29 predictors
29 30 qintc
... ...
libtests/pl_function.cc 0 → 100644
  1 +#include <qpdf/assert_test.h>
  2 +
  3 +#include <qpdf/Pl_Function.hh>
  4 +#include <qpdf/Pl_String.hh>
  5 +#include <qpdf/Pl_Base64.hh>
  6 +#include <iostream>
  7 +
  8 +int
  9 +main(int argc, char* argv[])
  10 +{
  11 + Pl_Function p1(
  12 + "p1", nullptr, [](unsigned char const* data, size_t len) {
  13 + std::cout << "p1: " << len << ": " << data << std::endl;
  14 + });
  15 + p1.write(reinterpret_cast<unsigned char const*>("potato"), 6);
  16 +
  17 + std::string s;
  18 + Pl_String ps("string", nullptr, s);
  19 + Pl_Base64 b("base64", &ps, Pl_Base64::a_encode);
  20 + Pl_Function p2(
  21 + "p2", &b, [](unsigned char const* data, size_t len) {
  22 + std::cout << "p2: " << len << ": " << data << std::endl;
  23 + });
  24 + p2.write(reinterpret_cast<unsigned char const*>("salad"), 5);
  25 + p2.finish();
  26 + assert(s == "c2FsYWQ=");
  27 +
  28 + return 0;
  29 +}
... ...
libtests/qtest/pl_function.test 0 → 100644
  1 +#!/usr/bin/env perl
  2 +require 5.008;
  3 +use warnings;
  4 +use strict;
  5 +
  6 +chdir("pl_function") or die "chdir testdir failed: $!\n";
  7 +
  8 +require TestDriver;
  9 +
  10 +my $td = new TestDriver('pl_function');
  11 +
  12 +$td->runtest("pl_function",
  13 + {$td->COMMAND => "pl_function"},
  14 + {$td->FILE => "exp", $td->EXIT_STATUS => 0},
  15 + $td->NORMALIZE_NEWLINES);
  16 +
  17 +$td->report(1);
... ...
libtests/qtest/pl_function/exp 0 → 100644
  1 +p1: 6: potato
  2 +p2: 5: salad
... ...
qpdf/sizes.cc
... ... @@ -16,6 +16,7 @@
16 16 #include <qpdf/Pl_DCT.hh>
17 17 #include <qpdf/Pl_Discard.hh>
18 18 #include <qpdf/Pl_Flate.hh>
  19 +#include <qpdf/Pl_Function.hh>
19 20 #include <qpdf/Pl_OStream.hh>
20 21 #include <qpdf/Pl_QPDFTokenizer.hh>
21 22 #include <qpdf/Pl_RunLength.hh>
... ... @@ -78,6 +79,7 @@ main()
78 79 print_size(Pl_DCT);
79 80 print_size(Pl_Discard);
80 81 print_size(Pl_Flate);
  82 + print_size(Pl_Function);
81 83 print_size(Pl_OStream);
82 84 print_size(Pl_QPDFTokenizer);
83 85 print_size(Pl_RunLength);
... ...