Commit 553ac7f353c7043806ec0de70d8630f5cd0a7bb8
1 parent
efdd46da
Add QUtil::pipe_file and QUtil::file_provider
Showing
5 changed files
with
63 additions
and
1 deletions
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 "\n"; |
| 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> | ... | ... |