Commit 79f6b4823b95b65290a045a59fdd4a8d9b302708

Authored by Jay Berkenbilt
1 parent 864a546a

Convert remaining public classes to use Members pattern

Have classes contain only a single private member of type
PointerHolder<Members>. 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
... ... @@ -70,6 +70,9 @@ CODING RULES
70 70 it seems also for classes that are intended to be subclassed across
71 71 the shared library boundary.
72 72  
  73 +* Put private member variables in PointerHolder<Members> for all
  74 + public classes. Remember to use QPDF_DLL on ~Members().
  75 +
73 76 RELEASE PREPARATION
74 77  
75 78 * Each year, update copyright notices. Just do a case-insensitive
... ...
1 1 Next ABI
2 2 ========
3 3  
4   - * Check all classes that don't use the Members pattern and see if
5   - they should be converted. Most of the pipeline classes should be
6   - converted.
7   -
8   - Buffer.hh
9   - BufferInputSource.hh
10   - FileInputSource.hh
11   - InputSource.hh
12   - Pl_Buffer.hh
13   - Pl_Concatenate.hh
14   - Pl_Count.hh
15   - Pl_DCT.hh
16   - Pl_Discard.hh
17   - Pl_Flate.hh
18   - Pl_RunLength.hh
19   - Pl_StdioFile.hh
20   - QPDFExc.hh
21   - QPDFObjGen.hh
22   - QPDFSystemError.hh
23   - QPDFXRefEntry.hh
24   -
25   - * Pl_Buffer's internal structure is not right for what it does. It
26   - was modified for greater efficiency, but it was done in a way that
27   - preserved binary compatibility, so the implementation is a bit
28   - convoluted.
29   -
30 4 * Check all overloaded methods to see if any can be eliminated by
31 5 using defaulted arguments. See ../misc/find-overloaded-functions.pl
32 6 (not in source repo)
... ...
include/qpdf/Buffer.hh
... ... @@ -23,7 +23,8 @@
23 23 #define BUFFER_HH
24 24  
25 25 #include <qpdf/DLL.h>
26   -#include <cstring> // for size_t
  26 +#include <qpdf/PointerHolder.hh>
  27 +#include <stddef.h>
27 28  
28 29 class Buffer
29 30 {
... ... @@ -46,8 +47,6 @@ class Buffer
46 47 QPDF_DLL
47 48 Buffer& operator=(Buffer const&);
48 49 QPDF_DLL
49   - ~Buffer();
50   - QPDF_DLL
51 50 size_t getSize() const;
52 51 QPDF_DLL
53 52 unsigned char const* getBuffer() const;
... ... @@ -55,13 +54,26 @@ class Buffer
55 54 unsigned char* getBuffer();
56 55  
57 56 private:
58   - void init(size_t size, unsigned char* buf, bool own_memory);
  57 + class Members
  58 + {
  59 + friend class Buffer;
  60 +
  61 + public:
  62 + QPDF_DLL
  63 + ~Members();
  64 +
  65 + private:
  66 + Members(size_t size, unsigned char* buf, bool own_memory);
  67 + Members(Members const&);
  68 +
  69 + bool own_memory;
  70 + size_t size;
  71 + unsigned char* buf;
  72 + };
  73 +
59 74 void copy(Buffer const&);
60   - void destroy();
61 75  
62   - bool own_memory;
63   - size_t size;
64   - unsigned char* buf;
  76 + PointerHolder<Members> m;
65 77 };
66 78  
67 79 #endif // BUFFER_HH
... ...
include/qpdf/BufferInputSource.hh
... ... @@ -56,10 +56,25 @@ class BufferInputSource: public InputSource
56 56 private:
57 57 qpdf_offset_t const bufSizeAsOffset() const;
58 58  
59   - bool own_memory;
60   - std::string description;
61   - Buffer* buf;
62   - qpdf_offset_t cur_offset;
  59 + class Members
  60 + {
  61 + friend class BufferInputSource;
  62 +
  63 + public:
  64 + QPDF_DLL
  65 + ~Members();
  66 +
  67 + private:
  68 + Members(bool own_memory, std::string const& description, Buffer* buf);
  69 + Members(Members const&);
  70 +
  71 + bool own_memory;
  72 + std::string description;
  73 + Buffer* buf;
  74 + qpdf_offset_t cur_offset;
  75 + };
  76 +
  77 + PointerHolder<Members> m;
63 78 };
64 79  
65 80 #endif // QPDF_BUFFERINPUTSOURCE_HH
... ...
include/qpdf/FileInputSource.hh
... ... @@ -54,11 +54,24 @@ class FileInputSource: public InputSource
54 54 FileInputSource(FileInputSource const&);
55 55 FileInputSource& operator=(FileInputSource const&);
56 56  
57   - void destroy();
  57 + class Members
  58 + {
  59 + friend class FileInputSource;
58 60  
59   - bool close_file;
60   - std::string filename;
61   - FILE* file;
  61 + public:
  62 + QPDF_DLL
  63 + ~Members();
  64 +
  65 + private:
  66 + Members(bool close_file);
  67 + Members(Members const&);
  68 +
  69 + bool close_file;
  70 + std::string filename;
  71 + FILE* file;
  72 + };
  73 +
  74 + PointerHolder<Members> m;
62 75 };
63 76  
64 77 #endif // QPDF_FILEINPUTSOURCE_HH
... ...
include/qpdf/InputSource.hh
... ... @@ -24,6 +24,7 @@
24 24  
25 25 #include <qpdf/DLL.h>
26 26 #include <qpdf/Types.h>
  27 +#include <qpdf/PointerHolder.hh>
27 28 #include <stdio.h>
28 29 #include <string>
29 30  
... ... @@ -86,6 +87,22 @@ class QPDF_DLL_CLASS InputSource
86 87  
87 88 protected:
88 89 qpdf_offset_t last_offset;
  90 +
  91 + private:
  92 + class Members
  93 + {
  94 + friend class InputSource;
  95 +
  96 + public:
  97 + QPDF_DLL
  98 + ~Members();
  99 +
  100 + private:
  101 + Members();
  102 + Members(Members const&);
  103 + };
  104 +
  105 + PointerHolder<Members> m;
89 106 };
90 107  
91 108 #endif // QPDF_INPUTSOURCE_HH
... ...
include/qpdf/Pipeline.hh
... ... @@ -45,6 +45,7 @@
45 45 #define PIPELINE_HH
46 46  
47 47 #include <qpdf/DLL.h>
  48 +#include <qpdf/PointerHolder.hh>
48 49 #include <string>
49 50  
50 51 class QPDF_DLL_CLASS Pipeline
... ... @@ -79,7 +80,22 @@ class QPDF_DLL_CLASS Pipeline
79 80 Pipeline(Pipeline const&);
80 81 Pipeline& operator=(Pipeline const&);
81 82  
82   - Pipeline* next;
  83 + class Members
  84 + {
  85 + friend class Pipeline;
  86 +
  87 + public:
  88 + QPDF_DLL
  89 + ~Members();
  90 +
  91 + private:
  92 + Members(Pipeline* next);
  93 + Members(Members const&);
  94 +
  95 + Pipeline* next;
  96 + };
  97 +
  98 + PointerHolder<Members> m;
83 99 };
84 100  
85 101 #endif // PIPELINE_HH
... ...
include/qpdf/Pl_Buffer.hh
... ... @@ -36,7 +36,6 @@
36 36 #include <qpdf/Pipeline.hh>
37 37 #include <qpdf/PointerHolder.hh>
38 38 #include <qpdf/Buffer.hh>
39   -#include <list>
40 39  
41 40 class Pl_Buffer: public Pipeline
42 41 {
... ... @@ -57,9 +56,24 @@ class Pl_Buffer: public Pipeline
57 56 Buffer* getBuffer();
58 57  
59 58 private:
60   - bool ready;
61   - std::list<PointerHolder<Buffer> > data;
62   - size_t total_size;
  59 + class Members
  60 + {
  61 + friend class Pl_Buffer;
  62 +
  63 + public:
  64 + QPDF_DLL
  65 + ~Members();
  66 +
  67 + private:
  68 + Members();
  69 + Members(Members const&);
  70 +
  71 + bool ready;
  72 + PointerHolder<Buffer> data;
  73 + size_t total_size;
  74 + };
  75 +
  76 + PointerHolder<Members> m;
63 77 };
64 78  
65 79 #endif // PL_BUFFER_HH
... ...
include/qpdf/Pl_Concatenate.hh
... ... @@ -48,6 +48,22 @@ class Pl_Concatenate: public Pipeline
48 48 // the pipeline.
49 49 QPDF_DLL
50 50 void manualFinish();
  51 +
  52 + private:
  53 + class Members
  54 + {
  55 + friend class Pl_Concatenate;
  56 +
  57 + public:
  58 + QPDF_DLL
  59 + ~Members();
  60 +
  61 + private:
  62 + Members();
  63 + Members(Members const&);
  64 + };
  65 +
  66 + PointerHolder<Members> m;
51 67 };
52 68  
53 69 #endif // PL_CONCATENATE_HH
... ...
include/qpdf/Pl_Count.hh
... ... @@ -48,10 +48,25 @@ class Pl_Count: public Pipeline
48 48 unsigned char getLastChar() const;
49 49  
50 50 private:
51   - // Must be qpdf_offset_t, not size_t, to handle writing more than
52   - // size_t can handle.
53   - qpdf_offset_t count;
54   - unsigned char last_char;
  51 + class Members
  52 + {
  53 + friend class Pl_Count;
  54 +
  55 + public:
  56 + QPDF_DLL
  57 + ~Members();
  58 +
  59 + private:
  60 + Members();
  61 + Members(Members const&);
  62 +
  63 + // Must be qpdf_offset_t, not size_t, to handle writing more than
  64 + // size_t can handle.
  65 + qpdf_offset_t count;
  66 + unsigned char last_char;
  67 + };
  68 +
  69 + PointerHolder<Members> m;
55 70 };
56 71  
57 72 #endif // PL_COUNT_HH
... ...
include/qpdf/Pl_DCT.hh
... ... @@ -68,17 +68,37 @@ class Pl_DCT: public Pipeline
68 68  
69 69 enum action_e { a_compress, a_decompress };
70 70  
71   - action_e action;
72   - Pl_Buffer buf;
  71 + class Members
  72 + {
  73 + friend class Pl_DCT;
  74 +
  75 + public:
  76 + QPDF_DLL
  77 + ~Members();
73 78  
74   - // Used for compression
75   - JDIMENSION image_width;
76   - JDIMENSION image_height;
77   - int components;
78   - J_COLOR_SPACE color_space;
  79 + private:
  80 + Members(action_e action,
  81 + char const* buf_description,
  82 + JDIMENSION image_width = 0,
  83 + JDIMENSION image_height = 0,
  84 + int components = 1,
  85 + J_COLOR_SPACE color_space = JCS_GRAYSCALE,
  86 + CompressConfig* config_callback = 0);
  87 + Members(Members const&);
79 88  
80   - CompressConfig* config_callback;
  89 + action_e action;
  90 + Pl_Buffer buf;
  91 +
  92 + // Used for compression
  93 + JDIMENSION image_width;
  94 + JDIMENSION image_height;
  95 + int components;
  96 + J_COLOR_SPACE color_space;
  97 +
  98 + CompressConfig* config_callback;
  99 + };
81 100  
  101 + PointerHolder<Members> m;
82 102 };
83 103  
84 104 #endif // PL_DCT_HH
... ...
include/qpdf/Pl_Discard.hh
... ... @@ -41,6 +41,22 @@ class Pl_Discard: public Pipeline
41 41 virtual void write(unsigned char*, size_t);
42 42 QPDF_DLL
43 43 virtual void finish();
  44 +
  45 + private:
  46 + class Members
  47 + {
  48 + friend class Pl_Discard;
  49 +
  50 + public:
  51 + QPDF_DLL
  52 + ~Members();
  53 +
  54 + private:
  55 + Members();
  56 + Members(Members const&);
  57 + };
  58 +
  59 + PointerHolder<Members> m;
44 60 };
45 61  
46 62 #endif // PL_DISCARD_HH
... ...
include/qpdf/Pl_Flate.hh
... ... @@ -46,11 +46,26 @@ class Pl_Flate: public Pipeline
46 46 void handleData(unsigned char* data, size_t len, int flush);
47 47 void checkError(char const* prefix, int error_code);
48 48  
49   - unsigned char* outbuf;
50   - size_t out_bufsize;
51   - action_e action;
52   - bool initialized;
53   - void* zdata;
  49 + class Members
  50 + {
  51 + friend class Pl_Flate;
  52 +
  53 + public:
  54 + QPDF_DLL
  55 + ~Members();
  56 +
  57 + private:
  58 + Members(size_t out_bufsize, action_e action);
  59 + Members(Members const&);
  60 +
  61 + unsigned char* outbuf;
  62 + size_t out_bufsize;
  63 + action_e action;
  64 + bool initialized;
  65 + void* zdata;
  66 + };
  67 +
  68 + PointerHolder<Members> m;
54 69 };
55 70  
56 71 #endif // PL_FLATE_HH
... ...
include/qpdf/Pl_RunLength.hh
... ... @@ -47,10 +47,25 @@ class Pl_RunLength: public Pipeline
47 47  
48 48 enum state_e { st_top, st_copying, st_run };
49 49  
50   - action_e action;
51   - state_e state;
52   - unsigned char buf[128];
53   - unsigned int length;
  50 + class Members
  51 + {
  52 + friend class Pl_RunLength;
  53 +
  54 + public:
  55 + QPDF_DLL
  56 + ~Members();
  57 +
  58 + private:
  59 + Members(action_e);
  60 + Members(Members const&);
  61 +
  62 + action_e action;
  63 + state_e state;
  64 + unsigned char buf[128];
  65 + unsigned int length;
  66 + };
  67 +
  68 + PointerHolder<Members> m;
54 69 };
55 70  
56 71 #endif // PL_RUNLENGTH_HH
... ...
include/qpdf/Pl_StdioFile.hh
... ... @@ -48,7 +48,22 @@ class Pl_StdioFile: public Pipeline
48 48 virtual void finish();
49 49  
50 50 private:
51   - FILE* file;
  51 + class Members
  52 + {
  53 + friend class Pl_StdioFile;
  54 +
  55 + public:
  56 + QPDF_DLL
  57 + ~Members();
  58 +
  59 + private:
  60 + Members(FILE*);
  61 + Members(Members const&);
  62 +
  63 + FILE* file;
  64 + };
  65 +
  66 + PointerHolder<Members> m;
52 67 };
53 68  
54 69 #endif // PL_STDIOFILE_HH
... ...
include/qpdf/QPDFExc.hh
... ... @@ -24,8 +24,8 @@
24 24  
25 25 #include <qpdf/DLL.h>
26 26 #include <qpdf/Types.h>
27   -
28 27 #include <qpdf/Constants.h>
  28 +
29 29 #include <string>
30 30 #include <stdexcept>
31 31  
... ... @@ -70,6 +70,9 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
70 70 qpdf_offset_t offset,
71 71 std::string const& message);
72 72  
  73 + // This class does not use the Members pattern to avoid needless
  74 + // memory allocations during exception handling.
  75 +
73 76 qpdf_error_code_e error_code;
74 77 std::string filename;
75 78 std::string object;
... ...
include/qpdf/QPDFObjGen.hh
... ... @@ -44,6 +44,9 @@ class QPDFObjGen
44 44 int getGen() const;
45 45  
46 46 private:
  47 + // This class does not use the Members pattern to avoid a memory
  48 + // allocation for every one of these. A lot of these get created
  49 + // and destroyed.
47 50 int obj;
48 51 int gen;
49 52 };
... ...
include/qpdf/QPDFSystemError.hh
... ... @@ -24,8 +24,8 @@
24 24  
25 25 #include <qpdf/DLL.h>
26 26 #include <qpdf/Types.h>
27   -
28 27 #include <qpdf/Constants.h>
  28 +
29 29 #include <string>
30 30 #include <stdexcept>
31 31  
... ... @@ -51,6 +51,9 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
51 51 static std::string createWhat(std::string const& description,
52 52 int system_errno);
53 53  
  54 + // This class does not use the Members pattern to avoid needless
  55 + // memory allocations during exception handling.
  56 +
54 57 std::string description;
55 58 int system_errno;
56 59 };
... ...
include/qpdf/QPDFXRefEntry.hh
... ... @@ -49,6 +49,8 @@ class QPDFXRefEntry
49 49 int getObjStreamIndex() const; // only for type 2
50 50  
51 51 private:
  52 + // This class does not use the Members pattern to avoid a memory
  53 + // allocation for every one of these. A lot of these get created.
52 54 int type;
53 55 qpdf_offset_t field1;
54 56 int field2;
... ...
libqpdf/Buffer.cc
1 1 #include <qpdf/Buffer.hh>
2 2  
3   -#include <string.h>
  3 +#include <cstring>
4 4  
5   -Buffer::Buffer()
  5 +Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) :
  6 + own_memory(own_memory),
  7 + size(size),
  8 + buf(0)
6 9 {
7   - init(0, 0, true);
  10 + if (own_memory)
  11 + {
  12 + this->buf = (size ? new unsigned char[size] : 0);
  13 + }
  14 + else
  15 + {
  16 + this->buf = buf;
  17 + }
8 18 }
9 19  
10   -Buffer::Buffer(size_t size)
  20 +Buffer::Members::~Members()
11 21 {
12   - init(size, 0, true);
  22 + if (this->own_memory)
  23 + {
  24 + delete [] this->buf;
  25 + }
13 26 }
14 27  
15   -Buffer::Buffer(unsigned char* buf, size_t size)
  28 +Buffer::Buffer() :
  29 + m(new Members(0, 0, true))
16 30 {
17   - init(size, buf, false);
18 31 }
19 32  
20   -Buffer::Buffer(Buffer const& rhs)
  33 +Buffer::Buffer(size_t size) :
  34 + m(new Members(size, 0, true))
21 35 {
22   - init(0, 0, true);
23   - copy(rhs);
24 36 }
25 37  
26   -Buffer&
27   -Buffer::operator=(Buffer const& rhs)
  38 +Buffer::Buffer(unsigned char* buf, size_t size) :
  39 + m(new Members(size, buf, false))
28 40 {
29   - copy(rhs);
30   - return *this;
31 41 }
32 42  
33   -Buffer::~Buffer()
  43 +Buffer::Buffer(Buffer const& rhs)
34 44 {
35   - destroy();
  45 + copy(rhs);
36 46 }
37 47  
38   -void
39   -Buffer::init(size_t size, unsigned char* buf, bool own_memory)
  48 +Buffer&
  49 +Buffer::operator=(Buffer const& rhs)
40 50 {
41   - this->own_memory = own_memory;
42   - this->size = size;
43   - if (own_memory)
44   - {
45   - this->buf = (size ? new unsigned char[size] : 0);
46   - }
47   - else
48   - {
49   - this->buf = buf;
50   - }
  51 + copy(rhs);
  52 + return *this;
51 53 }
52 54  
53 55 void
... ... @@ -55,40 +57,28 @@ Buffer::copy(Buffer const&amp; rhs)
55 57 {
56 58 if (this != &rhs)
57 59 {
58   - this->destroy();
59   - this->init(rhs.size, 0, true);
60   - if (this->size)
  60 + this->m = new Members(rhs.m->size, 0, true);
  61 + if (this->m->size)
61 62 {
62   - memcpy(this->buf, rhs.buf, this->size);
  63 + memcpy(this->m->buf, rhs.m->buf, this->m->size);
63 64 }
64 65 }
65 66 }
66 67  
67   -void
68   -Buffer::destroy()
69   -{
70   - if (this->own_memory)
71   - {
72   - delete [] this->buf;
73   - }
74   - this->size = 0;
75   - this->buf = 0;
76   -}
77   -
78 68 size_t
79 69 Buffer::getSize() const
80 70 {
81   - return this->size;
  71 + return this->m->size;
82 72 }
83 73  
84 74 unsigned char const*
85 75 Buffer::getBuffer() const
86 76 {
87   - return this->buf;
  77 + return this->m->buf;
88 78 }
89 79  
90 80 unsigned char*
91 81 Buffer::getBuffer()
92 82 {
93   - return this->buf;
  83 + return this->m->buf;
94 84 }
... ...
libqpdf/BufferInputSource.cc
... ... @@ -4,8 +4,9 @@
4 4 #include <stdexcept>
5 5 #include <algorithm>
6 6  
7   -BufferInputSource::BufferInputSource(std::string const& description,
8   - Buffer* buf, bool own_memory) :
  7 +BufferInputSource::Members::Members(bool own_memory,
  8 + std::string const& description,
  9 + Buffer* buf) :
9 10 own_memory(own_memory),
10 11 description(description),
11 12 buf(buf),
... ... @@ -13,70 +14,77 @@ BufferInputSource::BufferInputSource(std::string const&amp; description,
13 14 {
14 15 }
15 16  
  17 +BufferInputSource::Members::~Members()
  18 +{
  19 +}
  20 +
  21 +BufferInputSource::BufferInputSource(std::string const& description,
  22 + Buffer* buf, bool own_memory) :
  23 + m(new Members(own_memory, description, buf))
  24 +{
  25 +}
  26 +
16 27 BufferInputSource::BufferInputSource(std::string const& description,
17 28 std::string const& contents) :
18   - own_memory(true),
19   - description(description),
20   - buf(0),
21   - cur_offset(0)
  29 + m(new Members(true, description, 0))
22 30 {
23   - this->buf = new Buffer(contents.length());
24   - unsigned char* bp = buf->getBuffer();
  31 + this->m->buf = new Buffer(contents.length());
  32 + unsigned char* bp = this->m->buf->getBuffer();
25 33 memcpy(bp, contents.c_str(), contents.length());
26 34 }
27 35  
28 36 BufferInputSource::~BufferInputSource()
29 37 {
30   - if (own_memory)
  38 + if (this->m->own_memory)
31 39 {
32   - delete this->buf;
  40 + delete this->m->buf;
33 41 }
34 42 }
35 43  
36 44 qpdf_offset_t const
37 45 BufferInputSource::bufSizeAsOffset() const
38 46 {
39   - return QIntC::to_offset(this->buf->getSize());
  47 + return QIntC::to_offset(this->m->buf->getSize());
40 48 }
41 49  
42 50 qpdf_offset_t
43 51 BufferInputSource::findAndSkipNextEOL()
44 52 {
45   - if (this->cur_offset < 0)
  53 + if (this->m->cur_offset < 0)
46 54 {
47 55 throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
48 56 }
49 57 qpdf_offset_t end_pos = bufSizeAsOffset();
50   - if (this->cur_offset >= end_pos)
  58 + if (this->m->cur_offset >= end_pos)
51 59 {
52 60 this->last_offset = end_pos;
53   - this->cur_offset = end_pos;
  61 + this->m->cur_offset = end_pos;
54 62 return end_pos;
55 63 }
56 64  
57 65 qpdf_offset_t result = 0;
58   - size_t len = QIntC::to_size(end_pos - this->cur_offset);
59   - unsigned char const* buffer = this->buf->getBuffer();
  66 + size_t len = QIntC::to_size(end_pos - this->m->cur_offset);
  67 + unsigned char const* buffer = this->m->buf->getBuffer();
60 68  
61   - void* start = const_cast<unsigned char*>(buffer) + this->cur_offset;
  69 + void* start = const_cast<unsigned char*>(buffer) + this->m->cur_offset;
62 70 unsigned char* p1 = static_cast<unsigned char*>(memchr(start, '\r', len));
63 71 unsigned char* p2 = static_cast<unsigned char*>(memchr(start, '\n', len));
64 72 unsigned char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2;
65 73 if (p)
66 74 {
67 75 result = p - buffer;
68   - this->cur_offset = result + 1;
  76 + this->m->cur_offset = result + 1;
69 77 ++p;
70   - while ((this->cur_offset < end_pos) &&
  78 + while ((this->m->cur_offset < end_pos) &&
71 79 ((*p == '\r') || (*p == '\n')))
72 80 {
73 81 ++p;
74   - ++this->cur_offset;
  82 + ++this->m->cur_offset;
75 83 }
76 84 }
77 85 else
78 86 {
79   - this->cur_offset = end_pos;
  87 + this->m->cur_offset = end_pos;
80 88 result = end_pos;
81 89 }
82 90 return result;
... ... @@ -85,13 +93,13 @@ BufferInputSource::findAndSkipNextEOL()
85 93 std::string const&
86 94 BufferInputSource::getName() const
87 95 {
88   - return this->description;
  96 + return this->m->description;
89 97 }
90 98  
91 99 qpdf_offset_t
92 100 BufferInputSource::tell()
93 101 {
94   - return this->cur_offset;
  102 + return this->m->cur_offset;
95 103 }
96 104  
97 105 void
... ... @@ -100,15 +108,15 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence)
100 108 switch (whence)
101 109 {
102 110 case SEEK_SET:
103   - this->cur_offset = offset;
  111 + this->m->cur_offset = offset;
104 112 break;
105 113  
106 114 case SEEK_END:
107   - this->cur_offset = bufSizeAsOffset() + offset;
  115 + this->m->cur_offset = bufSizeAsOffset() + offset;
108 116 break;
109 117  
110 118 case SEEK_CUR:
111   - this->cur_offset += offset;
  119 + this->m->cur_offset += offset;
112 120 break;
113 121  
114 122 default:
... ... @@ -117,46 +125,46 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence)
117 125 break;
118 126 }
119 127  
120   - if (this->cur_offset < 0)
  128 + if (this->m->cur_offset < 0)
121 129 {
122 130 throw std::runtime_error(
123   - this->description + ": seek before beginning of buffer");
  131 + this->m->description + ": seek before beginning of buffer");
124 132 }
125 133 }
126 134  
127 135 void
128 136 BufferInputSource::rewind()
129 137 {
130   - this->cur_offset = 0;
  138 + this->m->cur_offset = 0;
131 139 }
132 140  
133 141 size_t
134 142 BufferInputSource::read(char* buffer, size_t length)
135 143 {
136   - if (this->cur_offset < 0)
  144 + if (this->m->cur_offset < 0)
137 145 {
138 146 throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
139 147 }
140 148 qpdf_offset_t end_pos = bufSizeAsOffset();
141   - if (this->cur_offset >= end_pos)
  149 + if (this->m->cur_offset >= end_pos)
142 150 {
143 151 this->last_offset = end_pos;
144 152 return 0;
145 153 }
146 154  
147   - this->last_offset = this->cur_offset;
  155 + this->last_offset = this->m->cur_offset;
148 156 size_t len = std::min(
149   - QIntC::to_size(end_pos - this->cur_offset), length);
150   - memcpy(buffer, buf->getBuffer() + this->cur_offset, len);
151   - this->cur_offset += QIntC::to_offset(len);
  157 + QIntC::to_size(end_pos - this->m->cur_offset), length);
  158 + memcpy(buffer, this->m->buf->getBuffer() + this->m->cur_offset, len);
  159 + this->m->cur_offset += QIntC::to_offset(len);
152 160 return len;
153 161 }
154 162  
155 163 void
156 164 BufferInputSource::unreadCh(char ch)
157 165 {
158   - if (this->cur_offset > 0)
  166 + if (this->m->cur_offset > 0)
159 167 {
160   - --this->cur_offset;
  168 + --this->m->cur_offset;
161 169 }
162 170 }
... ...
libqpdf/FileInputSource.cc
... ... @@ -4,45 +4,45 @@
4 4 #include <qpdf/QPDFExc.hh>
5 5 #include <algorithm>
6 6  
7   -FileInputSource::FileInputSource() :
8   - close_file(false),
  7 +FileInputSource::Members::Members(bool close_file) :
  8 + close_file(close_file),
9 9 file(0)
10 10 {
11 11 }
12 12  
  13 +FileInputSource::Members::~Members()
  14 +{
  15 + if (this->file && this->close_file)
  16 + {
  17 + fclose(this->file);
  18 + }
  19 +}
  20 +
  21 +FileInputSource::FileInputSource() :
  22 + m(new Members(false))
  23 +{
  24 +}
  25 +
13 26 void
14 27 FileInputSource::setFilename(char const* filename)
15 28 {
16   - destroy();
17   - this->filename = filename;
18   - this->close_file = true;
19   - this->file = QUtil::safe_fopen(this->filename.c_str(), "rb");
  29 + this->m = new Members(true);
  30 + this->m->filename = filename;
  31 + this->m->file = QUtil::safe_fopen(filename, "rb");
20 32 }
21 33  
22 34 void
23 35 FileInputSource::setFile(
24 36 char const* description, FILE* filep, bool close_file)
25 37 {
26   - destroy();
27   - this->filename = description;
28   - this->close_file = close_file;
29   - this->file = filep;
  38 + this->m = new Members(close_file);
  39 + this->m->filename = description;
  40 + this->m->file = filep;
30 41 this->seek(0, SEEK_SET);
31 42 }
32 43  
33 44 FileInputSource::~FileInputSource()
34 45 {
35   - destroy();
36   -}
37   -
38   -void
39   -FileInputSource::destroy()
40   -{
41   - if (this->file && this->close_file)
42   - {
43   - fclose(this->file);
44   - this->file = 0;
45   - }
46 46 }
47 47  
48 48 qpdf_offset_t
... ... @@ -53,7 +53,7 @@ FileInputSource::findAndSkipNextEOL()
53 53 char buf[10240];
54 54 while (! done)
55 55 {
56   - qpdf_offset_t cur_offset = QUtil::tell(this->file);
  56 + qpdf_offset_t cur_offset = QUtil::tell(this->m->file);
57 57 size_t len = this->read(buf, sizeof(buf));
58 58 if (len == 0)
59 59 {
... ... @@ -93,41 +93,42 @@ FileInputSource::findAndSkipNextEOL()
93 93 std::string const&
94 94 FileInputSource::getName() const
95 95 {
96   - return this->filename;
  96 + return this->m->filename;
97 97 }
98 98  
99 99 qpdf_offset_t
100 100 FileInputSource::tell()
101 101 {
102   - return QUtil::tell(this->file);
  102 + return QUtil::tell(this->m->file);
103 103 }
104 104  
105 105 void
106 106 FileInputSource::seek(qpdf_offset_t offset, int whence)
107 107 {
108   - QUtil::os_wrapper(std::string("seek to ") + this->filename + ", offset " +
  108 + QUtil::os_wrapper(std::string("seek to ") +
  109 + this->m->filename + ", offset " +
109 110 QUtil::int_to_string(offset) + " (" +
110 111 QUtil::int_to_string(whence) + ")",
111   - QUtil::seek(this->file, offset, whence));
  112 + QUtil::seek(this->m->file, offset, whence));
112 113 }
113 114  
114 115 void
115 116 FileInputSource::rewind()
116 117 {
117   - ::rewind(this->file);
  118 + ::rewind(this->m->file);
118 119 }
119 120  
120 121 size_t
121 122 FileInputSource::read(char* buffer, size_t length)
122 123 {
123 124 this->last_offset = this->tell();
124   - size_t len = fread(buffer, 1, length, this->file);
  125 + size_t len = fread(buffer, 1, length, this->m->file);
125 126 if (len == 0)
126 127 {
127   - if (ferror(this->file))
  128 + if (ferror(this->m->file))
128 129 {
129 130 throw QPDFExc(qpdf_e_system,
130   - this->filename, "",
  131 + this->m->filename, "",
131 132 this->last_offset,
132 133 std::string("read ") +
133 134 QUtil::uint_to_string(length) + " bytes");
... ... @@ -144,6 +145,6 @@ FileInputSource::read(char* buffer, size_t length)
144 145 void
145 146 FileInputSource::unreadCh(char ch)
146 147 {
147   - QUtil::os_wrapper(this->filename + ": unread character",
148   - ungetc(static_cast<unsigned char>(ch), this->file));
  148 + QUtil::os_wrapper(this->m->filename + ": unread character",
  149 + ungetc(static_cast<unsigned char>(ch), this->m->file));
149 150 }
... ...
libqpdf/InputSource.cc
... ... @@ -5,6 +5,13 @@
5 5 #include <qpdf/PointerHolder.hh>
6 6 #include <qpdf/QIntC.hh>
7 7  
  8 +InputSource::Members::Members()
  9 +{
  10 +}
  11 +
  12 +InputSource::Members::~Members()
  13 +{
  14 +}
8 15  
9 16 void
10 17 InputSource::setLastOffset(qpdf_offset_t offset)
... ...
libqpdf/Pipeline.cc
1 1 #include <qpdf/Pipeline.hh>
2 2 #include <stdexcept>
3 3  
  4 +Pipeline::Members::Members(Pipeline* next) :
  5 + next(next)
  6 +{
  7 +}
  8 +
  9 +Pipeline::Members::~Members()
  10 +{
  11 +}
  12 +
4 13 Pipeline::Pipeline(char const* identifier, Pipeline* next) :
5 14 identifier(identifier),
6   - next(next)
  15 + m(new Members(next))
7 16 {
8 17 }
9 18  
... ... @@ -14,11 +23,11 @@ Pipeline::~Pipeline()
14 23 Pipeline*
15 24 Pipeline::getNext(bool allow_null)
16 25 {
17   - if ((next == 0) && (! allow_null))
  26 + if ((this->m->next == 0) && (! allow_null))
18 27 {
19 28 throw std::logic_error(
20 29 this->identifier +
21 30 ": Pipeline::getNext() called on pipeline with no next");
22 31 }
23   - return this->next;
  32 + return this->m->next;
24 33 }
... ...
libqpdf/Pl_Buffer.cc
... ... @@ -4,13 +4,22 @@
4 4 #include <assert.h>
5 5 #include <string.h>
6 6  
7   -Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) :
8   - Pipeline(identifier, next),
  7 +Pl_Buffer::Members::Members() :
9 8 ready(true),
10 9 total_size(0)
11 10 {
12 11 }
13 12  
  13 +Pl_Buffer::Members::~Members()
  14 +{
  15 +}
  16 +
  17 +Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) :
  18 + Pipeline(identifier, next),
  19 + m(new Members())
  20 +{
  21 +}
  22 +
14 23 Pl_Buffer::~Pl_Buffer()
15 24 {
16 25 }
... ... @@ -18,32 +27,25 @@ Pl_Buffer::~Pl_Buffer()
18 27 void
19 28 Pl_Buffer::write(unsigned char* buf, size_t len)
20 29 {
21   - PointerHolder<Buffer> cur_buf;
22   - size_t cur_size = 0;
23   - if (! this->data.empty())
  30 + if (this->m->data.getPointer() == 0)
24 31 {
25   - cur_buf = this->data.back();
26   - cur_size = cur_buf->getSize();
  32 + this->m->data = new Buffer(len);
27 33 }
28   - size_t left = cur_size - this->total_size;
  34 + size_t cur_size = this->m->data->getSize();
  35 + size_t left = cur_size - this->m->total_size;
29 36 if (left < len)
30 37 {
31   - size_t new_size = std::max(this->total_size + len, 2 * cur_size);
32   - Buffer* b = new Buffer(new_size);
33   - if (cur_buf.getPointer())
34   - {
35   - memcpy(b->getBuffer(), cur_buf->getBuffer(), this->total_size);
36   - }
37   - this->data.clear();
38   - cur_buf = b;
39   - this->data.push_back(cur_buf);
  38 + size_t new_size = std::max(this->m->total_size + len, 2 * cur_size);
  39 + PointerHolder<Buffer> b = new Buffer(new_size);
  40 + memcpy(b->getBuffer(), this->m->data->getBuffer(), this->m->total_size);
  41 + this->m->data = b;
40 42 }
41 43 if (len)
42 44 {
43   - memcpy(cur_buf->getBuffer() + this->total_size, buf, len);
44   - this->total_size += len;
  45 + memcpy(this->m->data->getBuffer() + this->m->total_size, buf, len);
  46 + this->m->total_size += len;
45 47 }
46   - this->ready = false;
  48 + this->m->ready = false;
47 49  
48 50 if (getNext(true))
49 51 {
... ... @@ -54,7 +56,7 @@ Pl_Buffer::write(unsigned char* buf, size_t len)
54 56 void
55 57 Pl_Buffer::finish()
56 58 {
57   - this->ready = true;
  59 + this->m->ready = true;
58 60 if (getNext(true))
59 61 {
60 62 getNext()->finish();
... ... @@ -64,21 +66,17 @@ Pl_Buffer::finish()
64 66 Buffer*
65 67 Pl_Buffer::getBuffer()
66 68 {
67   - if (! this->ready)
  69 + if (! this->m->ready)
68 70 {
69 71 throw std::logic_error("Pl_Buffer::getBuffer() called when not ready");
70 72 }
71 73  
72   - Buffer* b = new Buffer(this->total_size);
73   - unsigned char* p = b->getBuffer();
74   - if (! this->data.empty())
  74 + Buffer* b = new Buffer(this->m->total_size);
  75 + if (this->m->total_size > 0)
75 76 {
76   - PointerHolder<Buffer> bp = this->data.back();
77   - this->data.clear();
78   - memcpy(p, bp->getBuffer(), this->total_size);
  77 + unsigned char* p = b->getBuffer();
  78 + memcpy(p, this->m->data->getBuffer(), this->m->total_size);
79 79 }
80   - this->total_size = 0;
81   - this->ready = false;
82   -
  80 + this->m = new Members();
83 81 return b;
84 82 }
... ...
libqpdf/Pl_Concatenate.cc
1 1 #include <qpdf/Pl_Concatenate.hh>
2 2  
  3 +Pl_Concatenate::Members::Members()
  4 +{
  5 +}
  6 +
  7 +Pl_Concatenate::Members::~Members()
  8 +{
  9 +}
  10 +
3 11 Pl_Concatenate::Pl_Concatenate(char const* identifier, Pipeline* next) :
4 12 Pipeline(identifier, next)
5 13 {
... ...
libqpdf/Pl_Count.cc
1 1 #include <qpdf/Pl_Count.hh>
2 2 #include <qpdf/QIntC.hh>
3 3  
4   -Pl_Count::Pl_Count(char const* identifier, Pipeline* next) :
5   - Pipeline(identifier, next),
  4 +Pl_Count::Members::Members() :
6 5 count(0),
7 6 last_char('\0')
8 7 {
9 8 }
10 9  
  10 +Pl_Count::Members::~Members()
  11 +{
  12 +}
  13 +
  14 +Pl_Count::Pl_Count(char const* identifier, Pipeline* next) :
  15 + Pipeline(identifier, next),
  16 + m(new Members())
  17 +{
  18 +}
  19 +
11 20 Pl_Count::~Pl_Count()
12 21 {
13 22 }
... ... @@ -17,9 +26,9 @@ Pl_Count::write(unsigned char* buf, size_t len)
17 26 {
18 27 if (len)
19 28 {
20   - this->count += QIntC::to_offset(len);
  29 + this->m->count += QIntC::to_offset(len);
21 30 getNext()->write(buf, len);
22   - this->last_char = buf[len - 1];
  31 + this->m->last_char = buf[len - 1];
23 32 }
24 33 }
25 34  
... ... @@ -32,11 +41,11 @@ Pl_Count::finish()
32 41 qpdf_offset_t
33 42 Pl_Count::getCount() const
34 43 {
35   - return this->count;
  44 + return this->m->count;
36 45 }
37 46  
38 47 unsigned char
39 48 Pl_Count::getLastChar() const
40 49 {
41   - return this->last_char;
  50 + return this->m->last_char;
42 51 }
... ...
libqpdf/Pl_DCT.cc
... ... @@ -31,10 +31,30 @@ error_handler(j_common_ptr cinfo)
31 31 longjmp(jerr->jmpbuf, 1);
32 32 }
33 33  
  34 +Pl_DCT::Members::Members(action_e action,
  35 + char const* buf_description,
  36 + JDIMENSION image_width,
  37 + JDIMENSION image_height,
  38 + int components,
  39 + J_COLOR_SPACE color_space,
  40 + CompressConfig* config_callback) :
  41 + action(action),
  42 + buf(buf_description),
  43 + image_width(image_width),
  44 + image_height(image_height),
  45 + components(components),
  46 + color_space(color_space),
  47 + config_callback(config_callback)
  48 +{
  49 +}
  50 +
  51 +Pl_DCT::Members::~Members()
  52 +{
  53 +}
  54 +
34 55 Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) :
35 56 Pipeline(identifier, next),
36   - action(a_decompress),
37   - buf("DCT compressed image")
  57 + m(new Members(a_decompress, "DCT compressed image"))
38 58 {
39 59 }
40 60  
... ... @@ -45,13 +65,8 @@ Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next,
45 65 J_COLOR_SPACE color_space,
46 66 CompressConfig* config_callback) :
47 67 Pipeline(identifier, next),
48   - action(a_compress),
49   - buf("DCT uncompressed image"),
50   - image_width(image_width),
51   - image_height(image_height),
52   - components(components),
53   - color_space(color_space),
54   - config_callback(config_callback)
  68 + m(new Members(a_compress, "DCT uncompressed image",
  69 + image_width, image_height, components, color_space, config_callback))
55 70 {
56 71 }
57 72  
... ... @@ -62,18 +77,18 @@ Pl_DCT::~Pl_DCT()
62 77 void
63 78 Pl_DCT::write(unsigned char* data, size_t len)
64 79 {
65   - this->buf.write(data, len);
  80 + this->m->buf.write(data, len);
66 81 }
67 82  
68 83 void
69 84 Pl_DCT::finish()
70 85 {
71   - this->buf.finish();
  86 + this->m->buf.finish();
72 87  
73 88 // Using a PointerHolder<Buffer> here and passing it into compress
74 89 // and decompress causes a memory leak with setjmp/longjmp. Just
75 90 // use a pointer and delete it.
76   - Buffer* b = this->buf.getBuffer();
  91 + Buffer* b = this->m->buf.getBuffer();
77 92 if (b->getSize() == 0)
78 93 {
79 94 // Special case: empty data will never succeed and probably
... ... @@ -99,7 +114,7 @@ Pl_DCT::finish()
99 114 {
100 115 try
101 116 {
102   - if (this->action == a_compress)
  117 + if (this->m->action == a_compress)
103 118 {
104 119 compress(reinterpret_cast<void*>(&cinfo_compress), b);
105 120 }
... ... @@ -123,11 +138,11 @@ Pl_DCT::finish()
123 138 }
124 139 delete b;
125 140  
126   - if (this->action == a_compress)
  141 + if (this->m->action == a_compress)
127 142 {
128 143 jpeg_destroy_compress(&cinfo_compress);
129 144 }
130   - if (this->action == a_decompress)
  145 + if (this->m->action == a_decompress)
131 146 {
132 147 jpeg_destroy_decompress(&cinfo_decompress);
133 148 }
... ... @@ -272,14 +287,14 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
272 287 unsigned char* outbuffer = outbuffer_ph.getPointer();
273 288 jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, this->getNext());
274 289  
275   - cinfo->image_width = this->image_width;
276   - cinfo->image_height = this->image_height;
277   - cinfo->input_components = this->components;
278   - cinfo->in_color_space = this->color_space;
  290 + cinfo->image_width = this->m->image_width;
  291 + cinfo->image_height = this->m->image_height;
  292 + cinfo->input_components = this->m->components;
  293 + cinfo->in_color_space = this->m->color_space;
279 294 jpeg_set_defaults(cinfo);
280   - if (this->config_callback)
  295 + if (this->m->config_callback)
281 296 {
282   - this->config_callback->apply(cinfo);
  297 + this->m->config_callback->apply(cinfo);
283 298 }
284 299  
285 300 jpeg_start_compress(cinfo, TRUE);
... ...
libqpdf/Pl_Discard.cc
... ... @@ -2,6 +2,14 @@
2 2  
3 3 // Exercised in md5 test suite
4 4  
  5 +Pl_Discard::Members::Members()
  6 +{
  7 +}
  8 +
  9 +Pl_Discard::Members::~Members()
  10 +{
  11 +}
  12 +
5 13 Pl_Discard::Pl_Discard() :
6 14 Pipeline("discard", 0)
7 15 {
... ...
libqpdf/Pl_Flate.cc
... ... @@ -6,12 +6,12 @@
6 6 #include <qpdf/QUtil.hh>
7 7 #include <qpdf/QIntC.hh>
8 8  
9   -Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next,
10   - action_e action, unsigned int out_bufsize_int) :
11   - Pipeline(identifier, next),
12   - out_bufsize(QIntC::to_size(out_bufsize_int)),
  9 +Pl_Flate::Members::Members(size_t out_bufsize,
  10 + action_e action) :
  11 + out_bufsize(out_bufsize),
13 12 action(action),
14   - initialized(false)
  13 + initialized(false),
  14 + zdata(0)
15 15 {
16 16 this->outbuf = new unsigned char[out_bufsize];
17 17 // 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,
38 38 zstream.avail_out = QIntC::to_uint(out_bufsize);
39 39 }
40 40  
41   -Pl_Flate::~Pl_Flate()
  41 +Pl_Flate::Members::~Members()
42 42 {
43 43 delete [] this->outbuf;
44 44 this->outbuf = 0;
... ... @@ -60,10 +60,21 @@ Pl_Flate::~Pl_Flate()
60 60 this->zdata = 0;
61 61 }
62 62  
  63 +Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next,
  64 + action_e action, unsigned int out_bufsize_int) :
  65 + Pipeline(identifier, next),
  66 + m(new Members(QIntC::to_size(out_bufsize_int), action))
  67 +{
  68 +}
  69 +
  70 +Pl_Flate::~Pl_Flate()
  71 +{
  72 +}
  73 +
63 74 void
64 75 Pl_Flate::write(unsigned char* data, size_t len)
65 76 {
66   - if (this->outbuf == 0)
  77 + if (this->m->outbuf == 0)
67 78 {
68 79 throw std::logic_error(
69 80 this->identifier +
... ... @@ -79,7 +90,7 @@ Pl_Flate::write(unsigned char* data, size_t len)
79 90 {
80 91 size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
81 92 handleData(buf, bytes,
82   - (action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH));
  93 + (this->m->action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH));
83 94 bytes_left -= bytes;
84 95 buf += bytes;
85 96 }
... ... @@ -94,11 +105,11 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
94 105 "Pl_Flate: zlib doesn't support data"
95 106 " blocks larger than int");
96 107 }
97   - z_stream& zstream = *(static_cast<z_stream*>(this->zdata));
  108 + z_stream& zstream = *(static_cast<z_stream*>(this->m->zdata));
98 109 zstream.next_in = data;
99 110 zstream.avail_in = QIntC::to_uint(len);
100 111  
101   - if (! this->initialized)
  112 + if (! this->m->initialized)
102 113 {
103 114 int err = Z_OK;
104 115  
... ... @@ -109,7 +120,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
109 120 # pragma GCC diagnostic push
110 121 # pragma GCC diagnostic ignored "-Wold-style-cast"
111 122 #endif
112   - if (this->action == a_deflate)
  123 + if (this->m->action == a_deflate)
113 124 {
114 125 err = deflateInit(&zstream, Z_DEFAULT_COMPRESSION);
115 126 }
... ... @@ -123,7 +134,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
123 134 #endif
124 135  
125 136 checkError("Init", err);
126   - this->initialized = true;
  137 + this->m->initialized = true;
127 138 }
128 139  
129 140 int err = Z_OK;
... ... @@ -131,7 +142,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
131 142 bool done = false;
132 143 while (! done)
133 144 {
134   - if (action == a_deflate)
  145 + if (this->m->action == a_deflate)
135 146 {
136 147 err = deflate(&zstream, flush);
137 148 }
... ... @@ -139,7 +150,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
139 150 {
140 151 err = inflate(&zstream, flush);
141 152 }
142   - if ((action == a_inflate) && (err != Z_OK) && zstream.msg &&
  153 + if ((this->m->action == a_inflate) && (err != Z_OK) && zstream.msg &&
143 154 (strcmp(zstream.msg, "incorrect data check") == 0))
144 155 {
145 156 // Other PDF readers ignore this specific error. Combining
... ... @@ -172,12 +183,12 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
172 183 done = true;
173 184 }
174 185 uLong ready =
175   - QIntC::to_ulong(this->out_bufsize - zstream.avail_out);
  186 + QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out);
176 187 if (ready > 0)
177 188 {
178   - this->getNext()->write(this->outbuf, ready);
179   - zstream.next_out = this->outbuf;
180   - zstream.avail_out = QIntC::to_uint(this->out_bufsize);
  189 + this->getNext()->write(this->m->outbuf, ready);
  190 + zstream.next_out = this->m->outbuf;
  191 + zstream.avail_out = QIntC::to_uint(this->m->out_bufsize);
181 192 }
182 193 }
183 194 break;
... ... @@ -194,16 +205,16 @@ Pl_Flate::finish()
194 205 {
195 206 try
196 207 {
197   - if (this->outbuf)
  208 + if (this->m->outbuf)
198 209 {
199   - if (this->initialized)
  210 + if (this->m->initialized)
200 211 {
201   - z_stream& zstream = *(static_cast<z_stream*>(this->zdata));
  212 + z_stream& zstream = *(static_cast<z_stream*>(this->m->zdata));
202 213 unsigned char buf[1];
203 214 buf[0] = '\0';
204 215 handleData(buf, 0, Z_FINISH);
205 216 int err = Z_OK;
206   - if (action == a_deflate)
  217 + if (this->m->action == a_deflate)
207 218 {
208 219 err = deflateEnd(&zstream);
209 220 }
... ... @@ -211,12 +222,12 @@ Pl_Flate::finish()
211 222 {
212 223 err = inflateEnd(&zstream);
213 224 }
214   - this->initialized = false;
  225 + this->m->initialized = false;
215 226 checkError("End", err);
216 227 }
217 228  
218   - delete [] this->outbuf;
219   - this->outbuf = 0;
  229 + delete [] this->m->outbuf;
  230 + this->m->outbuf = 0;
220 231 }
221 232 }
222 233 catch (std::exception& e)
... ... @@ -230,10 +241,11 @@ Pl_Flate::finish()
230 241 void
231 242 Pl_Flate::checkError(char const* prefix, int error_code)
232 243 {
233   - z_stream& zstream = *(static_cast<z_stream*>(this->zdata));
  244 + z_stream& zstream = *(static_cast<z_stream*>(this->m->zdata));
234 245 if (error_code != Z_OK)
235 246 {
236   - char const* action_str = (action == a_deflate ? "deflate" : "inflate");
  247 + char const* action_str =
  248 + (this->m->action == a_deflate ? "deflate" : "inflate");
237 249 std::string msg =
238 250 this->identifier + ": " + action_str + ": " + prefix + ": ";
239 251  
... ...
libqpdf/Pl_RunLength.cc
... ... @@ -3,15 +3,24 @@
3 3 #include <qpdf/QUtil.hh>
4 4 #include <qpdf/QTC.hh>
5 5  
6   -Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next,
7   - action_e action) :
8   - Pipeline(identifier, next),
  6 +Pl_RunLength::Members::Members(action_e action) :
9 7 action(action),
10 8 state(st_top),
11 9 length(0)
12 10 {
13 11 }
14 12  
  13 +Pl_RunLength::Members::~Members()
  14 +{
  15 +}
  16 +
  17 +Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next,
  18 + action_e action) :
  19 + Pipeline(identifier, next),
  20 + m(new Members(action))
  21 +{
  22 +}
  23 +
15 24 Pl_RunLength::~Pl_RunLength()
16 25 {
17 26 }
... ... @@ -19,7 +28,7 @@ Pl_RunLength::~Pl_RunLength()
19 28 void
20 29 Pl_RunLength::write(unsigned char* data, size_t len)
21 30 {
22   - if (this->action == a_encode)
  31 + if (this->m->action == a_encode)
23 32 {
24 33 encode(data, len);
25 34 }
... ... @@ -34,41 +43,41 @@ Pl_RunLength::encode(unsigned char* data, size_t len)
34 43 {
35 44 for (size_t i = 0; i < len; ++i)
36 45 {
37   - if ((this->state == st_top) != (this->length <= 1))
  46 + if ((this->m->state == st_top) != (this->m->length <= 1))
38 47 {
39 48 throw std::logic_error(
40 49 "Pl_RunLength::encode: state/length inconsistency");
41 50 }
42 51 unsigned char ch = data[i];
43   - if ((this->length > 0) &&
44   - ((this->state == st_copying) || (this->length < 128)) &&
45   - (ch == this->buf[this->length-1]))
  52 + if ((this->m->length > 0) &&
  53 + ((this->m->state == st_copying) || (this->m->length < 128)) &&
  54 + (ch == this->m->buf[this->m->length-1]))
46 55 {
47 56 QTC::TC("libtests", "Pl_RunLength: switch to run",
48   - (this->length == 128) ? 0 : 1);
49   - if (this->state == st_copying)
  57 + (this->m->length == 128) ? 0 : 1);
  58 + if (this->m->state == st_copying)
50 59 {
51   - --this->length;
  60 + --this->m->length;
52 61 flush_encode();
53   - this->buf[0] = ch;
54   - this->length = 1;
  62 + this->m->buf[0] = ch;
  63 + this->m->length = 1;
55 64 }
56   - this->state = st_run;
57   - this->buf[this->length] = ch;
58   - ++this->length;
  65 + this->m->state = st_run;
  66 + this->m->buf[this->m->length] = ch;
  67 + ++this->m->length;
59 68 }
60 69 else
61 70 {
62   - if ((this->length == 128) || (this->state == st_run))
  71 + if ((this->m->length == 128) || (this->m->state == st_run))
63 72 {
64 73 flush_encode();
65 74 }
66   - else if (this->length > 0)
  75 + else if (this->m->length > 0)
67 76 {
68   - this->state = st_copying;
  77 + this->m->state = st_copying;
69 78 }
70   - this->buf[this->length] = ch;
71   - ++this->length;
  79 + this->m->buf[this->m->length] = ch;
  80 + ++this->m->length;
72 81 }
73 82 }
74 83 }
... ... @@ -79,20 +88,20 @@ Pl_RunLength::decode(unsigned char* data, size_t len)
79 88 for (size_t i = 0; i < len; ++i)
80 89 {
81 90 unsigned char ch = data[i];
82   - switch (this->state)
  91 + switch (this->m->state)
83 92 {
84 93 case st_top:
85 94 if (ch < 128)
86 95 {
87 96 // length represents remaining number of bytes to copy
88   - this->length = 1U + ch;
89   - this->state = st_copying;
  97 + this->m->length = 1U + ch;
  98 + this->m->state = st_copying;
90 99 }
91 100 else if (ch > 128)
92 101 {
93 102 // length represents number of copies of next byte
94   - this->length = 257U - ch;
95   - this->state = st_run;
  103 + this->m->length = 257U - ch;
  104 + this->m->state = st_run;
96 105 }
97 106 else // ch == 128
98 107 {
... ... @@ -102,18 +111,18 @@ Pl_RunLength::decode(unsigned char* data, size_t len)
102 111  
103 112 case st_copying:
104 113 this->getNext()->write(&ch, 1);
105   - if (--this->length == 0)
  114 + if (--this->m->length == 0)
106 115 {
107   - this->state = st_top;
  116 + this->m->state = st_top;
108 117 }
109 118 break;
110 119  
111 120 case st_run:
112   - for (unsigned int j = 0; j < this->length; ++j)
  121 + for (unsigned int j = 0; j < this->m->length; ++j)
113 122 {
114 123 this->getNext()->write(&ch, 1);
115 124 }
116   - this->state = st_top;
  125 + this->m->state = st_top;
117 126 break;
118 127 }
119 128 }
... ... @@ -122,36 +131,36 @@ Pl_RunLength::decode(unsigned char* data, size_t len)
122 131 void
123 132 Pl_RunLength::flush_encode()
124 133 {
125   - if (this->length == 128)
  134 + if (this->m->length == 128)
126 135 {
127 136 QTC::TC("libtests", "Pl_RunLength flush full buffer",
128   - (this->state == st_copying ? 0 :
129   - this->state == st_run ? 1 :
  137 + (this->m->state == st_copying ? 0 :
  138 + this->m->state == st_run ? 1 :
130 139 -1));
131 140 }
132   - if (this->length == 0)
  141 + if (this->m->length == 0)
133 142 {
134 143 QTC::TC("libtests", "Pl_RunLength flush empty buffer");
135 144 }
136   - if (this->state == st_run)
  145 + if (this->m->state == st_run)
137 146 {
138   - if ((this->length < 2) || (this->length > 128))
  147 + if ((this->m->length < 2) || (this->m->length > 128))
139 148 {
140 149 throw std::logic_error(
141 150 "Pl_RunLength: invalid length in flush_encode for run");
142 151 }
143   - unsigned char ch = static_cast<unsigned char>(257 - this->length);
  152 + unsigned char ch = static_cast<unsigned char>(257 - this->m->length);
144 153 this->getNext()->write(&ch, 1);
145   - this->getNext()->write(&this->buf[0], 1);
  154 + this->getNext()->write(&this->m->buf[0], 1);
146 155 }
147   - else if (this->length > 0)
  156 + else if (this->m->length > 0)
148 157 {
149   - unsigned char ch = static_cast<unsigned char>(this->length - 1);
  158 + unsigned char ch = static_cast<unsigned char>(this->m->length - 1);
150 159 this->getNext()->write(&ch, 1);
151   - this->getNext()->write(this->buf, this->length);
  160 + this->getNext()->write(this->m->buf, this->m->length);
152 161 }
153   - this->state = st_top;
154   - this->length = 0;
  162 + this->m->state = st_top;
  163 + this->m->length = 0;
155 164 }
156 165  
157 166 void
... ... @@ -161,7 +170,7 @@ Pl_RunLength::finish()
161 170 // data, which means the stream was terminated early, but we will
162 171 // just ignore this case since this is the only sensible thing to
163 172 // do.
164   - if (this->action == a_encode)
  173 + if (this->m->action == a_encode)
165 174 {
166 175 flush_encode();
167 176 unsigned char ch = 128;
... ...
libqpdf/Pl_StdioFile.cc
... ... @@ -4,9 +4,18 @@
4 4 #include <stdexcept>
5 5 #include <errno.h>
6 6  
  7 +Pl_StdioFile::Members::Members(FILE* f) :
  8 + file(f)
  9 +{
  10 +}
  11 +
  12 +Pl_StdioFile::Members::~Members()
  13 +{
  14 +}
  15 +
7 16 Pl_StdioFile::Pl_StdioFile(char const* identifier, FILE* f) :
8 17 Pipeline(identifier, 0),
9   - file(f)
  18 + m(new Members(f))
10 19 {
11 20 }
12 21  
... ... @@ -20,7 +29,7 @@ Pl_StdioFile::write(unsigned char* buf, size_t len)
20 29 size_t so_far = 0;
21 30 while (len > 0)
22 31 {
23   - so_far = fwrite(buf, 1, len, this->file);
  32 + so_far = fwrite(buf, 1, len, this->m->file);
24 33 if (so_far == 0)
25 34 {
26 35 QUtil::throw_system_error(
... ... @@ -37,7 +46,7 @@ Pl_StdioFile::write(unsigned char* buf, size_t len)
37 46 void
38 47 Pl_StdioFile::finish()
39 48 {
40   - if ((fflush(this->file) == -1) &&
  49 + if ((fflush(this->m->file) == -1) &&
41 50 (errno == EBADF))
42 51 {
43 52 throw std::logic_error(
... ...
libtests/buffer.cc
... ... @@ -5,6 +5,7 @@
5 5 #include <stdlib.h>
6 6 #include <stdexcept>
7 7 #include <iostream>
  8 +#include <cassert>
8 9  
9 10 static unsigned char* uc(char const* s)
10 11 {
... ... @@ -13,6 +14,25 @@ static unsigned char* uc(char const* s)
13 14  
14 15 int main()
15 16 {
  17 + {
  18 + // Test that buffers can be copied by value.
  19 + Buffer bc1(2);
  20 + unsigned char* bc1p = bc1.getBuffer();
  21 + bc1p[0] = 'Q';
  22 + bc1p[1] = 'W';
  23 + Buffer bc2(bc1);
  24 + bc1p[0] = 'R';
  25 + unsigned char* bc2p = bc2.getBuffer();
  26 + assert(bc2p != bc1p);
  27 + assert(bc2p[0] == 'Q');
  28 + assert(bc2p[1] == 'W');
  29 + bc2 = bc1;
  30 + bc2p = bc2.getBuffer();
  31 + assert(bc2p != bc1p);
  32 + assert(bc2p[0] == 'R');
  33 + assert(bc2p[1] == 'W');
  34 + }
  35 +
16 36 try
17 37 {
18 38 Pl_Discard discard;
... ... @@ -68,6 +88,16 @@ int main()
68 88 b = bp3.getBuffer();
69 89 std::cout << "size: " << b->getSize() << std::endl;
70 90 delete b;
  91 + // Should be able to call getBuffer again and get an empty buffer
  92 + b = bp3.getBuffer();
  93 + std::cout << "size: " << b->getSize() << std::endl;
  94 + delete b;
  95 + // Also can write 0 and do it.
  96 + bp3.write(uc(""), 0);
  97 + bp3.finish();
  98 + b = bp3.getBuffer();
  99 + std::cout << "size: " << b->getSize() << std::endl;
  100 + delete b;
71 101 }
72 102 catch (std::exception& e)
73 103 {
... ...
libtests/qtest/buffer/buffer.out
... ... @@ -9,4 +9,6 @@ Pl_Buffer::getBuffer() called when not ready
9 9 size: 9
10 10 data: mooquack
11 11 size: 0
  12 +size: 0
  13 +size: 0
12 14 done
... ...