Commit 553ac7f353c7043806ec0de70d8630f5cd0a7bb8

Authored by Jay Berkenbilt
1 parent efdd46da

Add QUtil::pipe_file and QUtil::file_provider

ChangeLog
  1 +2021-02-07 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add new functions QUtil::pipe_file and QUtil::file_provider for
  4 + sending the contents of a file through a pipeline as binary data.
  5 +
1 6 2021-02-04 Jay Berkenbilt <ejb@ql.org>
2 7  
3 8 * Add new option --pasword-file=file for reading the decryption
... ...
include/qpdf/QUtil.hh
... ... @@ -34,6 +34,7 @@
34 34 #include <time.h>
35 35  
36 36 class RandomDataProvider;
  37 +class Pipeline;
37 38  
38 39 namespace QUtil
39 40 {
... ... @@ -119,6 +120,18 @@ namespace QUtil
119 120 QPDF_DLL
120 121 void rename_file(char const* oldname, char const* newname);
121 122  
  123 + // Write the contents of filename as a binary file to the
  124 + // pipeline.
  125 + QPDF_DLL
  126 + void
  127 + pipe_file(char const* filename, Pipeline* p);
  128 +
  129 + // Return a function that will send the contents of the given file
  130 + // through the given pipeline as binary data.
  131 + QPDF_DLL
  132 + std::function<void(Pipeline*)>
  133 + file_provider(std::string const& filename);
  134 +
122 135 QPDF_DLL
123 136 char* copy_string(std::string const&);
124 137  
... ...
libqpdf/QUtil.cc
... ... @@ -7,6 +7,7 @@
7 7 #include <qpdf/QPDFSystemError.hh>
8 8 #include <qpdf/QTC.hh>
9 9 #include <qpdf/QIntC.hh>
  10 +#include <qpdf/Pipeline.hh>
10 11  
11 12 #include <cmath>
12 13 #include <iomanip>
... ... @@ -612,6 +613,35 @@ QUtil::rename_file(char const* oldname, char const* newname)
612 613 #endif
613 614 }
614 615  
  616 +void
  617 +QUtil::pipe_file(char const* filename, Pipeline* p)
  618 +{
  619 + // Exercised in test suite by testing file_provider.
  620 + FILE* f = safe_fopen(filename, "rb");
  621 + FileCloser fc(f);
  622 + size_t len = 0;
  623 + int constexpr size = 8192;
  624 + unsigned char buf[size];
  625 + while ((len = fread(buf, 1, size, f)) > 0)
  626 + {
  627 + p->write(buf, len);
  628 + }
  629 + p->finish();
  630 + if (ferror(f))
  631 + {
  632 + throw std::runtime_error(
  633 + std::string("failure reading file ") + filename);
  634 + }
  635 +}
  636 +
  637 +std::function<void(Pipeline*)>
  638 +QUtil::file_provider(std::string const& filename)
  639 +{
  640 + return [filename](Pipeline* p) {
  641 + pipe_file(filename.c_str(), p);
  642 + };
  643 +}
  644 +
615 645 char*
616 646 QUtil::copy_string(std::string const& str)
617 647 {
... ... @@ -1018,6 +1048,7 @@ QUtil::read_file_into_memory(
1018 1048 PointerHolder<char>& file_buf, size_t& size)
1019 1049 {
1020 1050 FILE* f = safe_fopen(filename, "rb");
  1051 + FileCloser fc(f);
1021 1052 fseek(f, 0, SEEK_END);
1022 1053 size = QIntC::to_size(QUtil::tell(f));
1023 1054 fseek(f, 0, SEEK_SET);
... ... @@ -1048,7 +1079,6 @@ QUtil::read_file_into_memory(
1048 1079 uint_to_string(size));
1049 1080 }
1050 1081 }
1051   - fclose(f);
1052 1082 }
1053 1083  
1054 1084 static bool read_char_from_FILE(char& ch, FILE* f)
... ...
libtests/qutil.cc
... ... @@ -6,6 +6,7 @@
6 6 #include <qpdf/QUtil.hh>
7 7 #include <qpdf/PointerHolder.hh>
8 8 #include <qpdf/QPDFSystemError.hh>
  9 +#include <qpdf/Pl_Buffer.hh>
9 10 #include <string.h>
10 11 #include <limits.h>
11 12 #include <assert.h>
... ... @@ -483,6 +484,12 @@ void read_from_file_test()
483 484 assert(memcmp(p, "This file is used for qutil testing.", 36) == 0);
484 485 assert(p[59] == static_cast<char>(13));
485 486 assert(memcmp(p + 24641, "very long.", 10) == 0);
  487 + Pl_Buffer b2("buffer");
  488 + // QUtil::file_provider also exercises QUtil::pipe_file
  489 + QUtil::file_provider("other-file")(&b2);
  490 + auto buf2 = b2.getBuffer();
  491 + assert(buf2->getSize() == size);
  492 + assert(memcmp(buf2->getBuffer(), p, size) == 0);
486 493 }
487 494  
488 495 void assert_hex_encode(std::string const& input, std::string const& expected)
... ...
manual/qpdf-manual.xml
... ... @@ -4964,6 +4964,13 @@ print &quot;\n&quot;;
4964 4964 read/write implementation of name and number trees.
4965 4965 </para>
4966 4966 </listitem>
  4967 + <listitem>
  4968 + <para>
  4969 + Add new functions <function>QUtil::pipe_file</function> and
  4970 + <function>QUtil::file_provider</function> for sending the
  4971 + contents of a file through a pipeline as binary data.
  4972 + </para>
  4973 + </listitem>
4967 4974 </itemizedlist>
4968 4975 </listitem>
4969 4976 <listitem>
... ...