From 79f6b4823b95b65290a045a59fdd4a8d9b302708 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Fri, 21 Jun 2019 21:32:47 -0400 Subject: [PATCH] Convert remaining public classes to use Members pattern Have classes contain only a single private member of type PointerHolder. This makes it safe to change the structure of the Members class without breaking binary compatibility. Many of the classes already follow this pattern quite successfully. This brings in the rest of the class that are part of the public API. --- README-maintainer | 3 + TODO | 26 ------- include/qpdf/Buffer.hh | 30 ++++++--- include/qpdf/BufferInputSource.hh | 23 +++++-- include/qpdf/FileInputSource.hh | 21 ++++-- include/qpdf/InputSource.hh | 17 +++++ include/qpdf/Pipeline.hh | 18 ++++- include/qpdf/Pl_Buffer.hh | 22 ++++-- include/qpdf/Pl_Concatenate.hh | 16 +++++ include/qpdf/Pl_Count.hh | 23 +++++-- include/qpdf/Pl_DCT.hh | 36 +++++++--- include/qpdf/Pl_Discard.hh | 16 +++++ include/qpdf/Pl_Flate.hh | 25 +++++-- include/qpdf/Pl_RunLength.hh | 23 +++++-- include/qpdf/Pl_StdioFile.hh | 17 ++++- include/qpdf/QPDFExc.hh | 5 +- include/qpdf/QPDFObjGen.hh | 3 + include/qpdf/QPDFSystemError.hh | 5 +- include/qpdf/QPDFXRefEntry.hh | 2 + libqpdf/Buffer.cc | 108 ++++++++++++++---------------- libqpdf/BufferInputSource.cc | 82 +++++++++++++---------- libqpdf/FileInputSource.cc | 65 +++++++++--------- libqpdf/InputSource.cc | 7 ++ libqpdf/Pipeline.cc | 15 ++++- libqpdf/Pl_Buffer.cc | 60 ++++++++--------- libqpdf/Pl_Concatenate.cc | 8 +++ libqpdf/Pl_Count.cc | 21 ++++-- libqpdf/Pl_DCT.cc | 57 ++++++++++------ libqpdf/Pl_Discard.cc | 8 +++ libqpdf/Pl_Flate.cc | 66 ++++++++++-------- libqpdf/Pl_RunLength.cc | 97 +++++++++++++++------------ libqpdf/Pl_StdioFile.cc | 15 ++++- libtests/buffer.cc | 30 +++++++++ libtests/qtest/buffer/buffer.out | 2 + 34 files changed, 637 insertions(+), 335 deletions(-) diff --git a/README-maintainer b/README-maintainer index 3bb2b659..94e6514b 100644 --- a/README-maintainer +++ b/README-maintainer @@ -70,6 +70,9 @@ CODING RULES it seems also for classes that are intended to be subclassed across the shared library boundary. +* Put private member variables in PointerHolder for all + public classes. Remember to use QPDF_DLL on ~Members(). + RELEASE PREPARATION * Each year, update copyright notices. Just do a case-insensitive diff --git a/TODO b/TODO index d32d21d7..dd41430c 100644 --- a/TODO +++ b/TODO @@ -1,32 +1,6 @@ Next ABI ======== - * Check all classes that don't use the Members pattern and see if - they should be converted. Most of the pipeline classes should be - converted. - - Buffer.hh - BufferInputSource.hh - FileInputSource.hh - InputSource.hh - Pl_Buffer.hh - Pl_Concatenate.hh - Pl_Count.hh - Pl_DCT.hh - Pl_Discard.hh - Pl_Flate.hh - Pl_RunLength.hh - Pl_StdioFile.hh - QPDFExc.hh - QPDFObjGen.hh - QPDFSystemError.hh - QPDFXRefEntry.hh - - * Pl_Buffer's internal structure is not right for what it does. It - was modified for greater efficiency, but it was done in a way that - preserved binary compatibility, so the implementation is a bit - convoluted. - * Check all overloaded methods to see if any can be eliminated by using defaulted arguments. See ../misc/find-overloaded-functions.pl (not in source repo) diff --git a/include/qpdf/Buffer.hh b/include/qpdf/Buffer.hh index bb9a3eb9..8145f41a 100644 --- a/include/qpdf/Buffer.hh +++ b/include/qpdf/Buffer.hh @@ -23,7 +23,8 @@ #define BUFFER_HH #include -#include // for size_t +#include +#include class Buffer { @@ -46,8 +47,6 @@ class Buffer QPDF_DLL Buffer& operator=(Buffer const&); QPDF_DLL - ~Buffer(); - QPDF_DLL size_t getSize() const; QPDF_DLL unsigned char const* getBuffer() const; @@ -55,13 +54,26 @@ class Buffer unsigned char* getBuffer(); private: - void init(size_t size, unsigned char* buf, bool own_memory); - void copy(Buffer const&); - void destroy(); + class Members + { + friend class Buffer; - bool own_memory; - size_t size; - unsigned char* buf; + public: + QPDF_DLL + ~Members(); + + private: + Members(size_t size, unsigned char* buf, bool own_memory); + Members(Members const&); + + bool own_memory; + size_t size; + unsigned char* buf; + }; + + void copy(Buffer const&); + + PointerHolder m; }; #endif // BUFFER_HH diff --git a/include/qpdf/BufferInputSource.hh b/include/qpdf/BufferInputSource.hh index 51bb98f9..90263335 100644 --- a/include/qpdf/BufferInputSource.hh +++ b/include/qpdf/BufferInputSource.hh @@ -56,10 +56,25 @@ class BufferInputSource: public InputSource private: qpdf_offset_t const bufSizeAsOffset() const; - bool own_memory; - std::string description; - Buffer* buf; - qpdf_offset_t cur_offset; + class Members + { + friend class BufferInputSource; + + public: + QPDF_DLL + ~Members(); + + private: + Members(bool own_memory, std::string const& description, Buffer* buf); + Members(Members const&); + + bool own_memory; + std::string description; + Buffer* buf; + qpdf_offset_t cur_offset; + }; + + PointerHolder m; }; #endif // QPDF_BUFFERINPUTSOURCE_HH diff --git a/include/qpdf/FileInputSource.hh b/include/qpdf/FileInputSource.hh index 0845f241..1bf2a2de 100644 --- a/include/qpdf/FileInputSource.hh +++ b/include/qpdf/FileInputSource.hh @@ -54,11 +54,24 @@ class FileInputSource: public InputSource FileInputSource(FileInputSource const&); FileInputSource& operator=(FileInputSource const&); - void destroy(); + class Members + { + friend class FileInputSource; - bool close_file; - std::string filename; - FILE* file; + public: + QPDF_DLL + ~Members(); + + private: + Members(bool close_file); + Members(Members const&); + + bool close_file; + std::string filename; + FILE* file; + }; + + PointerHolder m; }; #endif // QPDF_FILEINPUTSOURCE_HH diff --git a/include/qpdf/InputSource.hh b/include/qpdf/InputSource.hh index 3d0d9aaf..db48fcba 100644 --- a/include/qpdf/InputSource.hh +++ b/include/qpdf/InputSource.hh @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -86,6 +87,22 @@ class QPDF_DLL_CLASS InputSource protected: qpdf_offset_t last_offset; + + private: + class Members + { + friend class InputSource; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + }; + + PointerHolder m; }; #endif // QPDF_INPUTSOURCE_HH diff --git a/include/qpdf/Pipeline.hh b/include/qpdf/Pipeline.hh index a5440a27..36a25df0 100644 --- a/include/qpdf/Pipeline.hh +++ b/include/qpdf/Pipeline.hh @@ -45,6 +45,7 @@ #define PIPELINE_HH #include +#include #include class QPDF_DLL_CLASS Pipeline @@ -79,7 +80,22 @@ class QPDF_DLL_CLASS Pipeline Pipeline(Pipeline const&); Pipeline& operator=(Pipeline const&); - Pipeline* next; + class Members + { + friend class Pipeline; + + public: + QPDF_DLL + ~Members(); + + private: + Members(Pipeline* next); + Members(Members const&); + + Pipeline* next; + }; + + PointerHolder m; }; #endif // PIPELINE_HH diff --git a/include/qpdf/Pl_Buffer.hh b/include/qpdf/Pl_Buffer.hh index 5eb143b2..0afa6c69 100644 --- a/include/qpdf/Pl_Buffer.hh +++ b/include/qpdf/Pl_Buffer.hh @@ -36,7 +36,6 @@ #include #include #include -#include class Pl_Buffer: public Pipeline { @@ -57,9 +56,24 @@ class Pl_Buffer: public Pipeline Buffer* getBuffer(); private: - bool ready; - std::list > data; - size_t total_size; + class Members + { + friend class Pl_Buffer; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + + bool ready; + PointerHolder data; + size_t total_size; + }; + + PointerHolder m; }; #endif // PL_BUFFER_HH diff --git a/include/qpdf/Pl_Concatenate.hh b/include/qpdf/Pl_Concatenate.hh index 26e5849e..135a9899 100644 --- a/include/qpdf/Pl_Concatenate.hh +++ b/include/qpdf/Pl_Concatenate.hh @@ -48,6 +48,22 @@ class Pl_Concatenate: public Pipeline // the pipeline. QPDF_DLL void manualFinish(); + + private: + class Members + { + friend class Pl_Concatenate; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + }; + + PointerHolder m; }; #endif // PL_CONCATENATE_HH diff --git a/include/qpdf/Pl_Count.hh b/include/qpdf/Pl_Count.hh index 0b021d9a..aa281c5c 100644 --- a/include/qpdf/Pl_Count.hh +++ b/include/qpdf/Pl_Count.hh @@ -48,10 +48,25 @@ class Pl_Count: public Pipeline unsigned char getLastChar() const; private: - // Must be qpdf_offset_t, not size_t, to handle writing more than - // size_t can handle. - qpdf_offset_t count; - unsigned char last_char; + class Members + { + friend class Pl_Count; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + + // Must be qpdf_offset_t, not size_t, to handle writing more than + // size_t can handle. + qpdf_offset_t count; + unsigned char last_char; + }; + + PointerHolder m; }; #endif // PL_COUNT_HH diff --git a/include/qpdf/Pl_DCT.hh b/include/qpdf/Pl_DCT.hh index 1827fa80..57a52cb4 100644 --- a/include/qpdf/Pl_DCT.hh +++ b/include/qpdf/Pl_DCT.hh @@ -68,17 +68,37 @@ class Pl_DCT: public Pipeline enum action_e { a_compress, a_decompress }; - action_e action; - Pl_Buffer buf; + class Members + { + friend class Pl_DCT; - // Used for compression - JDIMENSION image_width; - JDIMENSION image_height; - int components; - J_COLOR_SPACE color_space; + public: + QPDF_DLL + ~Members(); - CompressConfig* config_callback; + private: + Members(action_e action, + char const* buf_description, + JDIMENSION image_width = 0, + JDIMENSION image_height = 0, + int components = 1, + J_COLOR_SPACE color_space = JCS_GRAYSCALE, + CompressConfig* config_callback = 0); + Members(Members const&); + action_e action; + Pl_Buffer buf; + + // Used for compression + JDIMENSION image_width; + JDIMENSION image_height; + int components; + J_COLOR_SPACE color_space; + + CompressConfig* config_callback; + }; + + PointerHolder m; }; #endif // PL_DCT_HH diff --git a/include/qpdf/Pl_Discard.hh b/include/qpdf/Pl_Discard.hh index 129431b2..3130ef45 100644 --- a/include/qpdf/Pl_Discard.hh +++ b/include/qpdf/Pl_Discard.hh @@ -41,6 +41,22 @@ class Pl_Discard: public Pipeline virtual void write(unsigned char*, size_t); QPDF_DLL virtual void finish(); + + private: + class Members + { + friend class Pl_Discard; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + }; + + PointerHolder m; }; #endif // PL_DISCARD_HH diff --git a/include/qpdf/Pl_Flate.hh b/include/qpdf/Pl_Flate.hh index 923b33a8..2884ecc5 100644 --- a/include/qpdf/Pl_Flate.hh +++ b/include/qpdf/Pl_Flate.hh @@ -46,11 +46,26 @@ class Pl_Flate: public Pipeline void handleData(unsigned char* data, size_t len, int flush); void checkError(char const* prefix, int error_code); - unsigned char* outbuf; - size_t out_bufsize; - action_e action; - bool initialized; - void* zdata; + class Members + { + friend class Pl_Flate; + + public: + QPDF_DLL + ~Members(); + + private: + Members(size_t out_bufsize, action_e action); + Members(Members const&); + + unsigned char* outbuf; + size_t out_bufsize; + action_e action; + bool initialized; + void* zdata; + }; + + PointerHolder m; }; #endif // PL_FLATE_HH diff --git a/include/qpdf/Pl_RunLength.hh b/include/qpdf/Pl_RunLength.hh index b8e696b6..a579ceea 100644 --- a/include/qpdf/Pl_RunLength.hh +++ b/include/qpdf/Pl_RunLength.hh @@ -47,10 +47,25 @@ class Pl_RunLength: public Pipeline enum state_e { st_top, st_copying, st_run }; - action_e action; - state_e state; - unsigned char buf[128]; - unsigned int length; + class Members + { + friend class Pl_RunLength; + + public: + QPDF_DLL + ~Members(); + + private: + Members(action_e); + Members(Members const&); + + action_e action; + state_e state; + unsigned char buf[128]; + unsigned int length; + }; + + PointerHolder m; }; #endif // PL_RUNLENGTH_HH diff --git a/include/qpdf/Pl_StdioFile.hh b/include/qpdf/Pl_StdioFile.hh index fd228333..83d7faf2 100644 --- a/include/qpdf/Pl_StdioFile.hh +++ b/include/qpdf/Pl_StdioFile.hh @@ -48,7 +48,22 @@ class Pl_StdioFile: public Pipeline virtual void finish(); private: - FILE* file; + class Members + { + friend class Pl_StdioFile; + + public: + QPDF_DLL + ~Members(); + + private: + Members(FILE*); + Members(Members const&); + + FILE* file; + }; + + PointerHolder m; }; #endif // PL_STDIOFILE_HH diff --git a/include/qpdf/QPDFExc.hh b/include/qpdf/QPDFExc.hh index 188ede29..4cabd7a9 100644 --- a/include/qpdf/QPDFExc.hh +++ b/include/qpdf/QPDFExc.hh @@ -24,8 +24,8 @@ #include #include - #include + #include #include @@ -70,6 +70,9 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error qpdf_offset_t offset, std::string const& message); + // This class does not use the Members pattern to avoid needless + // memory allocations during exception handling. + qpdf_error_code_e error_code; std::string filename; std::string object; diff --git a/include/qpdf/QPDFObjGen.hh b/include/qpdf/QPDFObjGen.hh index 81c45d9f..9b61c78d 100644 --- a/include/qpdf/QPDFObjGen.hh +++ b/include/qpdf/QPDFObjGen.hh @@ -44,6 +44,9 @@ class QPDFObjGen int getGen() const; private: + // This class does not use the Members pattern to avoid a memory + // allocation for every one of these. A lot of these get created + // and destroyed. int obj; int gen; }; diff --git a/include/qpdf/QPDFSystemError.hh b/include/qpdf/QPDFSystemError.hh index e8ea09eb..4ecd01d6 100644 --- a/include/qpdf/QPDFSystemError.hh +++ b/include/qpdf/QPDFSystemError.hh @@ -24,8 +24,8 @@ #include #include - #include + #include #include @@ -51,6 +51,9 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error static std::string createWhat(std::string const& description, int system_errno); + // This class does not use the Members pattern to avoid needless + // memory allocations during exception handling. + std::string description; int system_errno; }; diff --git a/include/qpdf/QPDFXRefEntry.hh b/include/qpdf/QPDFXRefEntry.hh index ee3cf746..59b6a23f 100644 --- a/include/qpdf/QPDFXRefEntry.hh +++ b/include/qpdf/QPDFXRefEntry.hh @@ -49,6 +49,8 @@ class QPDFXRefEntry int getObjStreamIndex() const; // only for type 2 private: + // This class does not use the Members pattern to avoid a memory + // allocation for every one of these. A lot of these get created. int type; qpdf_offset_t field1; int field2; diff --git a/libqpdf/Buffer.cc b/libqpdf/Buffer.cc index 94e69a56..a15f73e8 100644 --- a/libqpdf/Buffer.cc +++ b/libqpdf/Buffer.cc @@ -1,45 +1,12 @@ #include -#include +#include -Buffer::Buffer() +Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) : + own_memory(own_memory), + size(size), + buf(0) { - init(0, 0, true); -} - -Buffer::Buffer(size_t size) -{ - init(size, 0, true); -} - -Buffer::Buffer(unsigned char* buf, size_t size) -{ - init(size, buf, false); -} - -Buffer::Buffer(Buffer const& rhs) -{ - init(0, 0, true); - copy(rhs); -} - -Buffer& -Buffer::operator=(Buffer const& rhs) -{ - copy(rhs); - return *this; -} - -Buffer::~Buffer() -{ - destroy(); -} - -void -Buffer::init(size_t size, unsigned char* buf, bool own_memory) -{ - this->own_memory = own_memory; - this->size = size; if (own_memory) { this->buf = (size ? new unsigned char[size] : 0); @@ -50,45 +17,68 @@ Buffer::init(size_t size, unsigned char* buf, bool own_memory) } } -void -Buffer::copy(Buffer const& rhs) -{ - if (this != &rhs) - { - this->destroy(); - this->init(rhs.size, 0, true); - if (this->size) - { - memcpy(this->buf, rhs.buf, this->size); - } - } -} - -void -Buffer::destroy() +Buffer::Members::~Members() { if (this->own_memory) { delete [] this->buf; } - this->size = 0; - this->buf = 0; +} + +Buffer::Buffer() : + m(new Members(0, 0, true)) +{ +} + +Buffer::Buffer(size_t size) : + m(new Members(size, 0, true)) +{ +} + +Buffer::Buffer(unsigned char* buf, size_t size) : + m(new Members(size, buf, false)) +{ +} + +Buffer::Buffer(Buffer const& rhs) +{ + copy(rhs); +} + +Buffer& +Buffer::operator=(Buffer const& rhs) +{ + copy(rhs); + return *this; +} + +void +Buffer::copy(Buffer const& rhs) +{ + if (this != &rhs) + { + this->m = new Members(rhs.m->size, 0, true); + if (this->m->size) + { + memcpy(this->m->buf, rhs.m->buf, this->m->size); + } + } } size_t Buffer::getSize() const { - return this->size; + return this->m->size; } unsigned char const* Buffer::getBuffer() const { - return this->buf; + return this->m->buf; } unsigned char* Buffer::getBuffer() { - return this->buf; + return this->m->buf; } diff --git a/libqpdf/BufferInputSource.cc b/libqpdf/BufferInputSource.cc index 1bf61bbd..23bad5f0 100644 --- a/libqpdf/BufferInputSource.cc +++ b/libqpdf/BufferInputSource.cc @@ -4,8 +4,9 @@ #include #include -BufferInputSource::BufferInputSource(std::string const& description, - Buffer* buf, bool own_memory) : +BufferInputSource::Members::Members(bool own_memory, + std::string const& description, + Buffer* buf) : own_memory(own_memory), description(description), buf(buf), @@ -13,70 +14,77 @@ BufferInputSource::BufferInputSource(std::string const& description, { } +BufferInputSource::Members::~Members() +{ +} + +BufferInputSource::BufferInputSource(std::string const& description, + Buffer* buf, bool own_memory) : + m(new Members(own_memory, description, buf)) +{ +} + BufferInputSource::BufferInputSource(std::string const& description, std::string const& contents) : - own_memory(true), - description(description), - buf(0), - cur_offset(0) + m(new Members(true, description, 0)) { - this->buf = new Buffer(contents.length()); - unsigned char* bp = buf->getBuffer(); + this->m->buf = new Buffer(contents.length()); + unsigned char* bp = this->m->buf->getBuffer(); memcpy(bp, contents.c_str(), contents.length()); } BufferInputSource::~BufferInputSource() { - if (own_memory) + if (this->m->own_memory) { - delete this->buf; + delete this->m->buf; } } qpdf_offset_t const BufferInputSource::bufSizeAsOffset() const { - return QIntC::to_offset(this->buf->getSize()); + return QIntC::to_offset(this->m->buf->getSize()); } qpdf_offset_t BufferInputSource::findAndSkipNextEOL() { - if (this->cur_offset < 0) + if (this->m->cur_offset < 0) { throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); } qpdf_offset_t end_pos = bufSizeAsOffset(); - if (this->cur_offset >= end_pos) + if (this->m->cur_offset >= end_pos) { this->last_offset = end_pos; - this->cur_offset = end_pos; + this->m->cur_offset = end_pos; return end_pos; } qpdf_offset_t result = 0; - size_t len = QIntC::to_size(end_pos - this->cur_offset); - unsigned char const* buffer = this->buf->getBuffer(); + size_t len = QIntC::to_size(end_pos - this->m->cur_offset); + unsigned char const* buffer = this->m->buf->getBuffer(); - void* start = const_cast(buffer) + this->cur_offset; + void* start = const_cast(buffer) + this->m->cur_offset; unsigned char* p1 = static_cast(memchr(start, '\r', len)); unsigned char* p2 = static_cast(memchr(start, '\n', len)); unsigned char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; if (p) { result = p - buffer; - this->cur_offset = result + 1; + this->m->cur_offset = result + 1; ++p; - while ((this->cur_offset < end_pos) && + while ((this->m->cur_offset < end_pos) && ((*p == '\r') || (*p == '\n'))) { ++p; - ++this->cur_offset; + ++this->m->cur_offset; } } else { - this->cur_offset = end_pos; + this->m->cur_offset = end_pos; result = end_pos; } return result; @@ -85,13 +93,13 @@ BufferInputSource::findAndSkipNextEOL() std::string const& BufferInputSource::getName() const { - return this->description; + return this->m->description; } qpdf_offset_t BufferInputSource::tell() { - return this->cur_offset; + return this->m->cur_offset; } void @@ -100,15 +108,15 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence) switch (whence) { case SEEK_SET: - this->cur_offset = offset; + this->m->cur_offset = offset; break; case SEEK_END: - this->cur_offset = bufSizeAsOffset() + offset; + this->m->cur_offset = bufSizeAsOffset() + offset; break; case SEEK_CUR: - this->cur_offset += offset; + this->m->cur_offset += offset; break; default: @@ -117,46 +125,46 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence) break; } - if (this->cur_offset < 0) + if (this->m->cur_offset < 0) { throw std::runtime_error( - this->description + ": seek before beginning of buffer"); + this->m->description + ": seek before beginning of buffer"); } } void BufferInputSource::rewind() { - this->cur_offset = 0; + this->m->cur_offset = 0; } size_t BufferInputSource::read(char* buffer, size_t length) { - if (this->cur_offset < 0) + if (this->m->cur_offset < 0) { throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0"); } qpdf_offset_t end_pos = bufSizeAsOffset(); - if (this->cur_offset >= end_pos) + if (this->m->cur_offset >= end_pos) { this->last_offset = end_pos; return 0; } - this->last_offset = this->cur_offset; + this->last_offset = this->m->cur_offset; size_t len = std::min( - QIntC::to_size(end_pos - this->cur_offset), length); - memcpy(buffer, buf->getBuffer() + this->cur_offset, len); - this->cur_offset += QIntC::to_offset(len); + QIntC::to_size(end_pos - this->m->cur_offset), length); + memcpy(buffer, this->m->buf->getBuffer() + this->m->cur_offset, len); + this->m->cur_offset += QIntC::to_offset(len); return len; } void BufferInputSource::unreadCh(char ch) { - if (this->cur_offset > 0) + if (this->m->cur_offset > 0) { - --this->cur_offset; + --this->m->cur_offset; } } diff --git a/libqpdf/FileInputSource.cc b/libqpdf/FileInputSource.cc index d0f3c8ef..cd8feda4 100644 --- a/libqpdf/FileInputSource.cc +++ b/libqpdf/FileInputSource.cc @@ -4,45 +4,45 @@ #include #include -FileInputSource::FileInputSource() : - close_file(false), +FileInputSource::Members::Members(bool close_file) : + close_file(close_file), file(0) { } +FileInputSource::Members::~Members() +{ + if (this->file && this->close_file) + { + fclose(this->file); + } +} + +FileInputSource::FileInputSource() : + m(new Members(false)) +{ +} + void FileInputSource::setFilename(char const* filename) { - destroy(); - this->filename = filename; - this->close_file = true; - this->file = QUtil::safe_fopen(this->filename.c_str(), "rb"); + this->m = new Members(true); + this->m->filename = filename; + this->m->file = QUtil::safe_fopen(filename, "rb"); } void FileInputSource::setFile( char const* description, FILE* filep, bool close_file) { - destroy(); - this->filename = description; - this->close_file = close_file; - this->file = filep; + this->m = new Members(close_file); + this->m->filename = description; + this->m->file = filep; this->seek(0, SEEK_SET); } FileInputSource::~FileInputSource() { - destroy(); -} - -void -FileInputSource::destroy() -{ - if (this->file && this->close_file) - { - fclose(this->file); - this->file = 0; - } } qpdf_offset_t @@ -53,7 +53,7 @@ FileInputSource::findAndSkipNextEOL() char buf[10240]; while (! done) { - qpdf_offset_t cur_offset = QUtil::tell(this->file); + qpdf_offset_t cur_offset = QUtil::tell(this->m->file); size_t len = this->read(buf, sizeof(buf)); if (len == 0) { @@ -93,41 +93,42 @@ FileInputSource::findAndSkipNextEOL() std::string const& FileInputSource::getName() const { - return this->filename; + return this->m->filename; } qpdf_offset_t FileInputSource::tell() { - return QUtil::tell(this->file); + return QUtil::tell(this->m->file); } void FileInputSource::seek(qpdf_offset_t offset, int whence) { - QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " + + QUtil::os_wrapper(std::string("seek to ") + + this->m->filename + ", offset " + QUtil::int_to_string(offset) + " (" + QUtil::int_to_string(whence) + ")", - QUtil::seek(this->file, offset, whence)); + QUtil::seek(this->m->file, offset, whence)); } void FileInputSource::rewind() { - ::rewind(this->file); + ::rewind(this->m->file); } size_t FileInputSource::read(char* buffer, size_t length) { this->last_offset = this->tell(); - size_t len = fread(buffer, 1, length, this->file); + size_t len = fread(buffer, 1, length, this->m->file); if (len == 0) { - if (ferror(this->file)) + if (ferror(this->m->file)) { throw QPDFExc(qpdf_e_system, - this->filename, "", + this->m->filename, "", this->last_offset, std::string("read ") + QUtil::uint_to_string(length) + " bytes"); @@ -144,6 +145,6 @@ FileInputSource::read(char* buffer, size_t length) void FileInputSource::unreadCh(char ch) { - QUtil::os_wrapper(this->filename + ": unread character", - ungetc(static_cast(ch), this->file)); + QUtil::os_wrapper(this->m->filename + ": unread character", + ungetc(static_cast(ch), this->m->file)); } diff --git a/libqpdf/InputSource.cc b/libqpdf/InputSource.cc index ca363566..a0e81a7a 100644 --- a/libqpdf/InputSource.cc +++ b/libqpdf/InputSource.cc @@ -5,6 +5,13 @@ #include #include +InputSource::Members::Members() +{ +} + +InputSource::Members::~Members() +{ +} void InputSource::setLastOffset(qpdf_offset_t offset) diff --git a/libqpdf/Pipeline.cc b/libqpdf/Pipeline.cc index b80b2d67..bcd48e46 100644 --- a/libqpdf/Pipeline.cc +++ b/libqpdf/Pipeline.cc @@ -1,9 +1,18 @@ #include #include +Pipeline::Members::Members(Pipeline* next) : + next(next) +{ +} + +Pipeline::Members::~Members() +{ +} + Pipeline::Pipeline(char const* identifier, Pipeline* next) : identifier(identifier), - next(next) + m(new Members(next)) { } @@ -14,11 +23,11 @@ Pipeline::~Pipeline() Pipeline* Pipeline::getNext(bool allow_null) { - if ((next == 0) && (! allow_null)) + if ((this->m->next == 0) && (! allow_null)) { throw std::logic_error( this->identifier + ": Pipeline::getNext() called on pipeline with no next"); } - return this->next; + return this->m->next; } diff --git a/libqpdf/Pl_Buffer.cc b/libqpdf/Pl_Buffer.cc index d11959f4..70d906ea 100644 --- a/libqpdf/Pl_Buffer.cc +++ b/libqpdf/Pl_Buffer.cc @@ -4,13 +4,22 @@ #include #include -Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), +Pl_Buffer::Members::Members() : ready(true), total_size(0) { } +Pl_Buffer::Members::~Members() +{ +} + +Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) : + Pipeline(identifier, next), + m(new Members()) +{ +} + Pl_Buffer::~Pl_Buffer() { } @@ -18,32 +27,25 @@ Pl_Buffer::~Pl_Buffer() void Pl_Buffer::write(unsigned char* buf, size_t len) { - PointerHolder cur_buf; - size_t cur_size = 0; - if (! this->data.empty()) + if (this->m->data.getPointer() == 0) { - cur_buf = this->data.back(); - cur_size = cur_buf->getSize(); + this->m->data = new Buffer(len); } - size_t left = cur_size - this->total_size; + size_t cur_size = this->m->data->getSize(); + size_t left = cur_size - this->m->total_size; if (left < len) { - size_t new_size = std::max(this->total_size + len, 2 * cur_size); - Buffer* b = new Buffer(new_size); - if (cur_buf.getPointer()) - { - memcpy(b->getBuffer(), cur_buf->getBuffer(), this->total_size); - } - this->data.clear(); - cur_buf = b; - this->data.push_back(cur_buf); + size_t new_size = std::max(this->m->total_size + len, 2 * cur_size); + PointerHolder b = new Buffer(new_size); + memcpy(b->getBuffer(), this->m->data->getBuffer(), this->m->total_size); + this->m->data = b; } if (len) { - memcpy(cur_buf->getBuffer() + this->total_size, buf, len); - this->total_size += len; + memcpy(this->m->data->getBuffer() + this->m->total_size, buf, len); + this->m->total_size += len; } - this->ready = false; + this->m->ready = false; if (getNext(true)) { @@ -54,7 +56,7 @@ Pl_Buffer::write(unsigned char* buf, size_t len) void Pl_Buffer::finish() { - this->ready = true; + this->m->ready = true; if (getNext(true)) { getNext()->finish(); @@ -64,21 +66,17 @@ Pl_Buffer::finish() Buffer* Pl_Buffer::getBuffer() { - if (! this->ready) + if (! this->m->ready) { throw std::logic_error("Pl_Buffer::getBuffer() called when not ready"); } - Buffer* b = new Buffer(this->total_size); - unsigned char* p = b->getBuffer(); - if (! this->data.empty()) + Buffer* b = new Buffer(this->m->total_size); + if (this->m->total_size > 0) { - PointerHolder bp = this->data.back(); - this->data.clear(); - memcpy(p, bp->getBuffer(), this->total_size); + unsigned char* p = b->getBuffer(); + memcpy(p, this->m->data->getBuffer(), this->m->total_size); } - this->total_size = 0; - this->ready = false; - + this->m = new Members(); return b; } diff --git a/libqpdf/Pl_Concatenate.cc b/libqpdf/Pl_Concatenate.cc index 8d48de60..7ad8e546 100644 --- a/libqpdf/Pl_Concatenate.cc +++ b/libqpdf/Pl_Concatenate.cc @@ -1,5 +1,13 @@ #include +Pl_Concatenate::Members::Members() +{ +} + +Pl_Concatenate::Members::~Members() +{ +} + Pl_Concatenate::Pl_Concatenate(char const* identifier, Pipeline* next) : Pipeline(identifier, next) { diff --git a/libqpdf/Pl_Count.cc b/libqpdf/Pl_Count.cc index b4b13640..8077092a 100644 --- a/libqpdf/Pl_Count.cc +++ b/libqpdf/Pl_Count.cc @@ -1,13 +1,22 @@ #include #include -Pl_Count::Pl_Count(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), +Pl_Count::Members::Members() : count(0), last_char('\0') { } +Pl_Count::Members::~Members() +{ +} + +Pl_Count::Pl_Count(char const* identifier, Pipeline* next) : + Pipeline(identifier, next), + m(new Members()) +{ +} + Pl_Count::~Pl_Count() { } @@ -17,9 +26,9 @@ Pl_Count::write(unsigned char* buf, size_t len) { if (len) { - this->count += QIntC::to_offset(len); + this->m->count += QIntC::to_offset(len); getNext()->write(buf, len); - this->last_char = buf[len - 1]; + this->m->last_char = buf[len - 1]; } } @@ -32,11 +41,11 @@ Pl_Count::finish() qpdf_offset_t Pl_Count::getCount() const { - return this->count; + return this->m->count; } unsigned char Pl_Count::getLastChar() const { - return this->last_char; + return this->m->last_char; } diff --git a/libqpdf/Pl_DCT.cc b/libqpdf/Pl_DCT.cc index 4da068cb..de7e1a5e 100644 --- a/libqpdf/Pl_DCT.cc +++ b/libqpdf/Pl_DCT.cc @@ -31,10 +31,30 @@ error_handler(j_common_ptr cinfo) longjmp(jerr->jmpbuf, 1); } +Pl_DCT::Members::Members(action_e action, + char const* buf_description, + JDIMENSION image_width, + JDIMENSION image_height, + int components, + J_COLOR_SPACE color_space, + CompressConfig* config_callback) : + action(action), + buf(buf_description), + image_width(image_width), + image_height(image_height), + components(components), + color_space(color_space), + config_callback(config_callback) +{ +} + +Pl_DCT::Members::~Members() +{ +} + Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) : Pipeline(identifier, next), - action(a_decompress), - buf("DCT compressed image") + m(new Members(a_decompress, "DCT compressed image")) { } @@ -45,13 +65,8 @@ Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next, J_COLOR_SPACE color_space, CompressConfig* config_callback) : Pipeline(identifier, next), - action(a_compress), - buf("DCT uncompressed image"), - image_width(image_width), - image_height(image_height), - components(components), - color_space(color_space), - config_callback(config_callback) + m(new Members(a_compress, "DCT uncompressed image", + image_width, image_height, components, color_space, config_callback)) { } @@ -62,18 +77,18 @@ Pl_DCT::~Pl_DCT() void Pl_DCT::write(unsigned char* data, size_t len) { - this->buf.write(data, len); + this->m->buf.write(data, len); } void Pl_DCT::finish() { - this->buf.finish(); + this->m->buf.finish(); // Using a PointerHolder here and passing it into compress // and decompress causes a memory leak with setjmp/longjmp. Just // use a pointer and delete it. - Buffer* b = this->buf.getBuffer(); + Buffer* b = this->m->buf.getBuffer(); if (b->getSize() == 0) { // Special case: empty data will never succeed and probably @@ -99,7 +114,7 @@ Pl_DCT::finish() { try { - if (this->action == a_compress) + if (this->m->action == a_compress) { compress(reinterpret_cast(&cinfo_compress), b); } @@ -123,11 +138,11 @@ Pl_DCT::finish() } delete b; - if (this->action == a_compress) + if (this->m->action == a_compress) { jpeg_destroy_compress(&cinfo_compress); } - if (this->action == a_decompress) + if (this->m->action == a_decompress) { jpeg_destroy_decompress(&cinfo_decompress); } @@ -272,14 +287,14 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b) unsigned char* outbuffer = outbuffer_ph.getPointer(); jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, this->getNext()); - cinfo->image_width = this->image_width; - cinfo->image_height = this->image_height; - cinfo->input_components = this->components; - cinfo->in_color_space = this->color_space; + cinfo->image_width = this->m->image_width; + cinfo->image_height = this->m->image_height; + cinfo->input_components = this->m->components; + cinfo->in_color_space = this->m->color_space; jpeg_set_defaults(cinfo); - if (this->config_callback) + if (this->m->config_callback) { - this->config_callback->apply(cinfo); + this->m->config_callback->apply(cinfo); } jpeg_start_compress(cinfo, TRUE); diff --git a/libqpdf/Pl_Discard.cc b/libqpdf/Pl_Discard.cc index 34d49f3a..f2ba561f 100644 --- a/libqpdf/Pl_Discard.cc +++ b/libqpdf/Pl_Discard.cc @@ -2,6 +2,14 @@ // Exercised in md5 test suite +Pl_Discard::Members::Members() +{ +} + +Pl_Discard::Members::~Members() +{ +} + Pl_Discard::Pl_Discard() : Pipeline("discard", 0) { diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc index 67e02d2d..c42d3c28 100644 --- a/libqpdf/Pl_Flate.cc +++ b/libqpdf/Pl_Flate.cc @@ -6,12 +6,12 @@ #include #include -Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, - action_e action, unsigned int out_bufsize_int) : - Pipeline(identifier, next), - out_bufsize(QIntC::to_size(out_bufsize_int)), +Pl_Flate::Members::Members(size_t out_bufsize, + action_e action) : + out_bufsize(out_bufsize), action(action), - initialized(false) + initialized(false), + zdata(0) { this->outbuf = new unsigned char[out_bufsize]; // Indirect through zdata to reach the z_stream so we don't have @@ -38,7 +38,7 @@ Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, zstream.avail_out = QIntC::to_uint(out_bufsize); } -Pl_Flate::~Pl_Flate() +Pl_Flate::Members::~Members() { delete [] this->outbuf; this->outbuf = 0; @@ -60,10 +60,21 @@ Pl_Flate::~Pl_Flate() this->zdata = 0; } +Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next, + action_e action, unsigned int out_bufsize_int) : + Pipeline(identifier, next), + m(new Members(QIntC::to_size(out_bufsize_int), action)) +{ +} + +Pl_Flate::~Pl_Flate() +{ +} + void Pl_Flate::write(unsigned char* data, size_t len) { - if (this->outbuf == 0) + if (this->m->outbuf == 0) { throw std::logic_error( this->identifier + @@ -79,7 +90,7 @@ Pl_Flate::write(unsigned char* data, size_t len) { size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left); handleData(buf, bytes, - (action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH)); + (this->m->action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH)); bytes_left -= bytes; buf += bytes; } @@ -94,11 +105,11 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) "Pl_Flate: zlib doesn't support data" " blocks larger than int"); } - z_stream& zstream = *(static_cast(this->zdata)); + z_stream& zstream = *(static_cast(this->m->zdata)); zstream.next_in = data; zstream.avail_in = QIntC::to_uint(len); - if (! this->initialized) + if (! this->m->initialized) { int err = Z_OK; @@ -109,7 +120,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wold-style-cast" #endif - if (this->action == a_deflate) + if (this->m->action == a_deflate) { err = deflateInit(&zstream, Z_DEFAULT_COMPRESSION); } @@ -123,7 +134,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) #endif checkError("Init", err); - this->initialized = true; + this->m->initialized = true; } int err = Z_OK; @@ -131,7 +142,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) bool done = false; while (! done) { - if (action == a_deflate) + if (this->m->action == a_deflate) { err = deflate(&zstream, flush); } @@ -139,7 +150,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) { err = inflate(&zstream, flush); } - if ((action == a_inflate) && (err != Z_OK) && zstream.msg && + if ((this->m->action == a_inflate) && (err != Z_OK) && zstream.msg && (strcmp(zstream.msg, "incorrect data check") == 0)) { // Other PDF readers ignore this specific error. Combining @@ -172,12 +183,12 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush) done = true; } uLong ready = - QIntC::to_ulong(this->out_bufsize - zstream.avail_out); + QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out); if (ready > 0) { - this->getNext()->write(this->outbuf, ready); - zstream.next_out = this->outbuf; - zstream.avail_out = QIntC::to_uint(this->out_bufsize); + this->getNext()->write(this->m->outbuf, ready); + zstream.next_out = this->m->outbuf; + zstream.avail_out = QIntC::to_uint(this->m->out_bufsize); } } break; @@ -194,16 +205,16 @@ Pl_Flate::finish() { try { - if (this->outbuf) + if (this->m->outbuf) { - if (this->initialized) + if (this->m->initialized) { - z_stream& zstream = *(static_cast(this->zdata)); + z_stream& zstream = *(static_cast(this->m->zdata)); unsigned char buf[1]; buf[0] = '\0'; handleData(buf, 0, Z_FINISH); int err = Z_OK; - if (action == a_deflate) + if (this->m->action == a_deflate) { err = deflateEnd(&zstream); } @@ -211,12 +222,12 @@ Pl_Flate::finish() { err = inflateEnd(&zstream); } - this->initialized = false; + this->m->initialized = false; checkError("End", err); } - delete [] this->outbuf; - this->outbuf = 0; + delete [] this->m->outbuf; + this->m->outbuf = 0; } } catch (std::exception& e) @@ -230,10 +241,11 @@ Pl_Flate::finish() void Pl_Flate::checkError(char const* prefix, int error_code) { - z_stream& zstream = *(static_cast(this->zdata)); + z_stream& zstream = *(static_cast(this->m->zdata)); if (error_code != Z_OK) { - char const* action_str = (action == a_deflate ? "deflate" : "inflate"); + char const* action_str = + (this->m->action == a_deflate ? "deflate" : "inflate"); std::string msg = this->identifier + ": " + action_str + ": " + prefix + ": "; diff --git a/libqpdf/Pl_RunLength.cc b/libqpdf/Pl_RunLength.cc index 3e3abd98..ed3b7576 100644 --- a/libqpdf/Pl_RunLength.cc +++ b/libqpdf/Pl_RunLength.cc @@ -3,15 +3,24 @@ #include #include -Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, - action_e action) : - Pipeline(identifier, next), +Pl_RunLength::Members::Members(action_e action) : action(action), state(st_top), length(0) { } +Pl_RunLength::Members::~Members() +{ +} + +Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, + action_e action) : + Pipeline(identifier, next), + m(new Members(action)) +{ +} + Pl_RunLength::~Pl_RunLength() { } @@ -19,7 +28,7 @@ Pl_RunLength::~Pl_RunLength() void Pl_RunLength::write(unsigned char* data, size_t len) { - if (this->action == a_encode) + if (this->m->action == a_encode) { encode(data, len); } @@ -34,41 +43,41 @@ Pl_RunLength::encode(unsigned char* data, size_t len) { for (size_t i = 0; i < len; ++i) { - if ((this->state == st_top) != (this->length <= 1)) + if ((this->m->state == st_top) != (this->m->length <= 1)) { throw std::logic_error( "Pl_RunLength::encode: state/length inconsistency"); } unsigned char ch = data[i]; - if ((this->length > 0) && - ((this->state == st_copying) || (this->length < 128)) && - (ch == this->buf[this->length-1])) + if ((this->m->length > 0) && + ((this->m->state == st_copying) || (this->m->length < 128)) && + (ch == this->m->buf[this->m->length-1])) { QTC::TC("libtests", "Pl_RunLength: switch to run", - (this->length == 128) ? 0 : 1); - if (this->state == st_copying) + (this->m->length == 128) ? 0 : 1); + if (this->m->state == st_copying) { - --this->length; + --this->m->length; flush_encode(); - this->buf[0] = ch; - this->length = 1; + this->m->buf[0] = ch; + this->m->length = 1; } - this->state = st_run; - this->buf[this->length] = ch; - ++this->length; + this->m->state = st_run; + this->m->buf[this->m->length] = ch; + ++this->m->length; } else { - if ((this->length == 128) || (this->state == st_run)) + if ((this->m->length == 128) || (this->m->state == st_run)) { flush_encode(); } - else if (this->length > 0) + else if (this->m->length > 0) { - this->state = st_copying; + this->m->state = st_copying; } - this->buf[this->length] = ch; - ++this->length; + this->m->buf[this->m->length] = ch; + ++this->m->length; } } } @@ -79,20 +88,20 @@ Pl_RunLength::decode(unsigned char* data, size_t len) for (size_t i = 0; i < len; ++i) { unsigned char ch = data[i]; - switch (this->state) + switch (this->m->state) { case st_top: if (ch < 128) { // length represents remaining number of bytes to copy - this->length = 1U + ch; - this->state = st_copying; + this->m->length = 1U + ch; + this->m->state = st_copying; } else if (ch > 128) { // length represents number of copies of next byte - this->length = 257U - ch; - this->state = st_run; + this->m->length = 257U - ch; + this->m->state = st_run; } else // ch == 128 { @@ -102,18 +111,18 @@ Pl_RunLength::decode(unsigned char* data, size_t len) case st_copying: this->getNext()->write(&ch, 1); - if (--this->length == 0) + if (--this->m->length == 0) { - this->state = st_top; + this->m->state = st_top; } break; case st_run: - for (unsigned int j = 0; j < this->length; ++j) + for (unsigned int j = 0; j < this->m->length; ++j) { this->getNext()->write(&ch, 1); } - this->state = st_top; + this->m->state = st_top; break; } } @@ -122,36 +131,36 @@ Pl_RunLength::decode(unsigned char* data, size_t len) void Pl_RunLength::flush_encode() { - if (this->length == 128) + if (this->m->length == 128) { QTC::TC("libtests", "Pl_RunLength flush full buffer", - (this->state == st_copying ? 0 : - this->state == st_run ? 1 : + (this->m->state == st_copying ? 0 : + this->m->state == st_run ? 1 : -1)); } - if (this->length == 0) + if (this->m->length == 0) { QTC::TC("libtests", "Pl_RunLength flush empty buffer"); } - if (this->state == st_run) + if (this->m->state == st_run) { - if ((this->length < 2) || (this->length > 128)) + if ((this->m->length < 2) || (this->m->length > 128)) { throw std::logic_error( "Pl_RunLength: invalid length in flush_encode for run"); } - unsigned char ch = static_cast(257 - this->length); + unsigned char ch = static_cast(257 - this->m->length); this->getNext()->write(&ch, 1); - this->getNext()->write(&this->buf[0], 1); + this->getNext()->write(&this->m->buf[0], 1); } - else if (this->length > 0) + else if (this->m->length > 0) { - unsigned char ch = static_cast(this->length - 1); + unsigned char ch = static_cast(this->m->length - 1); this->getNext()->write(&ch, 1); - this->getNext()->write(this->buf, this->length); + this->getNext()->write(this->m->buf, this->m->length); } - this->state = st_top; - this->length = 0; + this->m->state = st_top; + this->m->length = 0; } void @@ -161,7 +170,7 @@ Pl_RunLength::finish() // data, which means the stream was terminated early, but we will // just ignore this case since this is the only sensible thing to // do. - if (this->action == a_encode) + if (this->m->action == a_encode) { flush_encode(); unsigned char ch = 128; diff --git a/libqpdf/Pl_StdioFile.cc b/libqpdf/Pl_StdioFile.cc index 4d3cba60..253e36a1 100644 --- a/libqpdf/Pl_StdioFile.cc +++ b/libqpdf/Pl_StdioFile.cc @@ -4,9 +4,18 @@ #include #include +Pl_StdioFile::Members::Members(FILE* f) : + file(f) +{ +} + +Pl_StdioFile::Members::~Members() +{ +} + Pl_StdioFile::Pl_StdioFile(char const* identifier, FILE* f) : Pipeline(identifier, 0), - file(f) + m(new Members(f)) { } @@ -20,7 +29,7 @@ Pl_StdioFile::write(unsigned char* buf, size_t len) size_t so_far = 0; while (len > 0) { - so_far = fwrite(buf, 1, len, this->file); + so_far = fwrite(buf, 1, len, this->m->file); if (so_far == 0) { QUtil::throw_system_error( @@ -37,7 +46,7 @@ Pl_StdioFile::write(unsigned char* buf, size_t len) void Pl_StdioFile::finish() { - if ((fflush(this->file) == -1) && + if ((fflush(this->m->file) == -1) && (errno == EBADF)) { throw std::logic_error( diff --git a/libtests/buffer.cc b/libtests/buffer.cc index 4713f554..bd28746f 100644 --- a/libtests/buffer.cc +++ b/libtests/buffer.cc @@ -5,6 +5,7 @@ #include #include #include +#include static unsigned char* uc(char const* s) { @@ -13,6 +14,25 @@ static unsigned char* uc(char const* s) int main() { + { + // Test that buffers can be copied by value. + Buffer bc1(2); + unsigned char* bc1p = bc1.getBuffer(); + bc1p[0] = 'Q'; + bc1p[1] = 'W'; + Buffer bc2(bc1); + bc1p[0] = 'R'; + unsigned char* bc2p = bc2.getBuffer(); + assert(bc2p != bc1p); + assert(bc2p[0] == 'Q'); + assert(bc2p[1] == 'W'); + bc2 = bc1; + bc2p = bc2.getBuffer(); + assert(bc2p != bc1p); + assert(bc2p[0] == 'R'); + assert(bc2p[1] == 'W'); + } + try { Pl_Discard discard; @@ -68,6 +88,16 @@ int main() b = bp3.getBuffer(); std::cout << "size: " << b->getSize() << std::endl; delete b; + // Should be able to call getBuffer again and get an empty buffer + b = bp3.getBuffer(); + std::cout << "size: " << b->getSize() << std::endl; + delete b; + // Also can write 0 and do it. + bp3.write(uc(""), 0); + bp3.finish(); + b = bp3.getBuffer(); + std::cout << "size: " << b->getSize() << std::endl; + delete b; } catch (std::exception& e) { diff --git a/libtests/qtest/buffer/buffer.out b/libtests/qtest/buffer/buffer.out index c1bf24cf..e1e404b1 100644 --- a/libtests/qtest/buffer/buffer.out +++ b/libtests/qtest/buffer/buffer.out @@ -9,4 +9,6 @@ Pl_Buffer::getBuffer() called when not ready size: 9 data: mooquack size: 0 +size: 0 +size: 0 done