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