aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-04-10 15:29:11 +0200
committerJay Berkenbilt <ejb@ql.org>2022-04-10 22:52:57 +0200
commit5525c9312420cf002aef78fa1d52219724d3fc20 (patch)
tree4a3436dc380081500cd58a8f041e20cecec9ff6f
parent90cfe80bacdd0d398631afce76c4182e08cc78b9 (diff)
downloadqpdf-5525c9312420cf002aef78fa1d52219724d3fc20.tar.zst
Use QPDF_DLL_CLASS with Pipeline and InputSource subclasses
This enables RTTI so we can use dynamic_cast on them across the shared object boundary.
-rw-r--r--README-maintainer11
-rw-r--r--include/qpdf/BufferInputSource.hh4
-rw-r--r--include/qpdf/ClosedFileInputSource.hh4
-rw-r--r--include/qpdf/FileInputSource.hh4
-rw-r--r--include/qpdf/InputSource.hh3
-rw-r--r--include/qpdf/Pipeline.hh2
-rw-r--r--include/qpdf/Pl_Buffer.hh4
-rw-r--r--include/qpdf/Pl_Concatenate.hh4
-rw-r--r--include/qpdf/Pl_Count.hh4
-rw-r--r--include/qpdf/Pl_DCT.hh4
-rw-r--r--include/qpdf/Pl_Discard.hh4
-rw-r--r--include/qpdf/Pl_Flate.hh4
-rw-r--r--include/qpdf/Pl_QPDFTokenizer.hh4
-rw-r--r--include/qpdf/Pl_RunLength.hh4
-rw-r--r--include/qpdf/Pl_StdioFile.hh4
-rw-r--r--qpdf/test_driver.cc17
16 files changed, 52 insertions, 29 deletions
diff --git a/README-maintainer b/README-maintainer
index 60e7de57..52c10810 100644
--- a/README-maintainer
+++ b/README-maintainer
@@ -156,9 +156,14 @@ CODING RULES
* Use QPDF_DLL on all methods that are to be exported in the shared
library/DLL. Use QPDF_DLL_CLASS for all classes whose type
- information is needed. This is important for exception classes and
- it seems also for classes that are intended to be subclassed across
- the shared library boundary.
+ information is needed. This is important for classes that are used
+ as exceptions, subclassed, or tested with dynamic_cast across the
+ the shared object boundary (or "shared library boundary" -- we may
+ use either term in comments and documentation). In particular,
+ anything new derived from Pipeline or InputSource should be marked
+ with QPDF_DLL_CLASS, but we don't need to do it for QPDFObjectHelper
+ or QPDFDocumentHelper subclasses since there's no reason to use
+ dynamic_cast with those.
* Put private member variables in std::shared_ptr<Members> for all
public classes. Remember to use QPDF_DLL on ~Members(). Exception:
diff --git a/include/qpdf/BufferInputSource.hh b/include/qpdf/BufferInputSource.hh
index 6fd92e16..53c362a9 100644
--- a/include/qpdf/BufferInputSource.hh
+++ b/include/qpdf/BufferInputSource.hh
@@ -25,7 +25,7 @@
#include <qpdf/Buffer.hh>
#include <qpdf/InputSource.hh>
-class BufferInputSource: public InputSource
+class QPDF_DLL_CLASS BufferInputSource: public InputSource
{
public:
// If own_memory is true, BufferInputSource will delete the buffer
@@ -54,7 +54,7 @@ class BufferInputSource: public InputSource
virtual void unreadCh(char ch);
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class BufferInputSource;
diff --git a/include/qpdf/ClosedFileInputSource.hh b/include/qpdf/ClosedFileInputSource.hh
index cbaa9a52..e5142bc1 100644
--- a/include/qpdf/ClosedFileInputSource.hh
+++ b/include/qpdf/ClosedFileInputSource.hh
@@ -35,7 +35,7 @@
class FileInputSource;
-class ClosedFileInputSource: public InputSource
+class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource
{
public:
QPDF_DLL
@@ -71,7 +71,7 @@ class ClosedFileInputSource: public InputSource
void before();
void after();
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class ClosedFileInputSource;
diff --git a/include/qpdf/FileInputSource.hh b/include/qpdf/FileInputSource.hh
index 000590c3..c3b60265 100644
--- a/include/qpdf/FileInputSource.hh
+++ b/include/qpdf/FileInputSource.hh
@@ -24,7 +24,7 @@
#include <qpdf/InputSource.hh>
-class FileInputSource: public InputSource
+class QPDF_DLL_CLASS FileInputSource: public InputSource
{
public:
QPDF_DLL
@@ -54,7 +54,7 @@ class FileInputSource: public InputSource
FileInputSource(FileInputSource const&) = delete;
FileInputSource& operator=(FileInputSource const&) = delete;
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class FileInputSource;
diff --git a/include/qpdf/InputSource.hh b/include/qpdf/InputSource.hh
index b53ac0b3..8d46895d 100644
--- a/include/qpdf/InputSource.hh
+++ b/include/qpdf/InputSource.hh
@@ -30,6 +30,9 @@
#include <stdio.h>
#include <string>
+// Remember to use QPDF_DLL_CLASS on anything derived from InputSource
+// so it will work with dynamic_cast across the shared object
+// boundary.
class QPDF_DLL_CLASS InputSource
{
public:
diff --git a/include/qpdf/Pipeline.hh b/include/qpdf/Pipeline.hh
index 3b06b406..2a2f9d3c 100644
--- a/include/qpdf/Pipeline.hh
+++ b/include/qpdf/Pipeline.hh
@@ -50,6 +50,8 @@
#include <memory>
#include <string>
+// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so
+// it will work with dynamic_cast across the shared object boundary.
class QPDF_DLL_CLASS Pipeline
{
public:
diff --git a/include/qpdf/Pl_Buffer.hh b/include/qpdf/Pl_Buffer.hh
index 2556e672..f72646f0 100644
--- a/include/qpdf/Pl_Buffer.hh
+++ b/include/qpdf/Pl_Buffer.hh
@@ -39,7 +39,7 @@
#include <memory>
-class Pl_Buffer: public Pipeline
+class QPDF_DLL_CLASS Pl_Buffer: public Pipeline
{
public:
QPDF_DLL
@@ -71,7 +71,7 @@ class Pl_Buffer: public Pipeline
void getMallocBuffer(unsigned char** buf, size_t* len);
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_Buffer;
diff --git a/include/qpdf/Pl_Concatenate.hh b/include/qpdf/Pl_Concatenate.hh
index 806d61ea..702c48e4 100644
--- a/include/qpdf/Pl_Concatenate.hh
+++ b/include/qpdf/Pl_Concatenate.hh
@@ -30,7 +30,7 @@
#include <qpdf/Pipeline.hh>
-class Pl_Concatenate: public Pipeline
+class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline
{
public:
QPDF_DLL
@@ -50,7 +50,7 @@ class Pl_Concatenate: public Pipeline
void manualFinish();
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_Concatenate;
diff --git a/include/qpdf/Pl_Count.hh b/include/qpdf/Pl_Count.hh
index 4b8f441c..8d9bc6b7 100644
--- a/include/qpdf/Pl_Count.hh
+++ b/include/qpdf/Pl_Count.hh
@@ -28,7 +28,7 @@
#include <qpdf/Pipeline.hh>
#include <qpdf/Types.h>
-class Pl_Count: public Pipeline
+class QPDF_DLL_CLASS Pl_Count: public Pipeline
{
public:
QPDF_DLL
@@ -48,7 +48,7 @@ class Pl_Count: public Pipeline
unsigned char getLastChar() const;
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_Count;
diff --git a/include/qpdf/Pl_DCT.hh b/include/qpdf/Pl_DCT.hh
index 9481fee9..0339afb7 100644
--- a/include/qpdf/Pl_DCT.hh
+++ b/include/qpdf/Pl_DCT.hh
@@ -31,7 +31,7 @@
// definition of size_t.
#include <jpeglib.h>
-class Pl_DCT: public Pipeline
+class QPDF_DLL_CLASS Pl_DCT: public Pipeline
{
public:
// Constructor for decompressing image data
@@ -75,7 +75,7 @@ class Pl_DCT: public Pipeline
enum action_e { a_compress, a_decompress };
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_DCT;
diff --git a/include/qpdf/Pl_Discard.hh b/include/qpdf/Pl_Discard.hh
index 277461d9..051f9fe1 100644
--- a/include/qpdf/Pl_Discard.hh
+++ b/include/qpdf/Pl_Discard.hh
@@ -30,7 +30,7 @@
#include <qpdf/Pipeline.hh>
-class Pl_Discard: public Pipeline
+class QPDF_DLL_CLASS Pl_Discard: public Pipeline
{
public:
QPDF_DLL
@@ -43,7 +43,7 @@ class Pl_Discard: public Pipeline
virtual void finish();
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_Discard;
diff --git a/include/qpdf/Pl_Flate.hh b/include/qpdf/Pl_Flate.hh
index 90c0bbde..503c2db8 100644
--- a/include/qpdf/Pl_Flate.hh
+++ b/include/qpdf/Pl_Flate.hh
@@ -26,7 +26,7 @@
#include <functional>
#include <memory>
-class Pl_Flate: public Pipeline
+class QPDF_DLL_CLASS Pl_Flate: public Pipeline
{
public:
static unsigned int const def_bufsize = 65536;
@@ -65,7 +65,7 @@ class Pl_Flate: public Pipeline
void checkError(char const* prefix, int error_code);
void warn(char const*, int error_code);
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_Flate;
diff --git a/include/qpdf/Pl_QPDFTokenizer.hh b/include/qpdf/Pl_QPDFTokenizer.hh
index a5ac3ccc..d5b531e2 100644
--- a/include/qpdf/Pl_QPDFTokenizer.hh
+++ b/include/qpdf/Pl_QPDFTokenizer.hh
@@ -41,7 +41,7 @@
// QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh for
// details.
-class Pl_QPDFTokenizer: public Pipeline
+class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline
{
public:
// Whatever pipeline is provided as "next" will be set as the
@@ -60,7 +60,7 @@ class Pl_QPDFTokenizer: public Pipeline
virtual void finish();
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_QPDFTokenizer;
diff --git a/include/qpdf/Pl_RunLength.hh b/include/qpdf/Pl_RunLength.hh
index e93c5fb6..5becd198 100644
--- a/include/qpdf/Pl_RunLength.hh
+++ b/include/qpdf/Pl_RunLength.hh
@@ -24,7 +24,7 @@
#include <qpdf/Pipeline.hh>
-class Pl_RunLength: public Pipeline
+class QPDF_DLL_CLASS Pl_RunLength: public Pipeline
{
public:
enum action_e { a_encode, a_decode };
@@ -46,7 +46,7 @@ class Pl_RunLength: public Pipeline
enum state_e { st_top, st_copying, st_run };
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_RunLength;
diff --git a/include/qpdf/Pl_StdioFile.hh b/include/qpdf/Pl_StdioFile.hh
index ffc7a790..64f4738d 100644
--- a/include/qpdf/Pl_StdioFile.hh
+++ b/include/qpdf/Pl_StdioFile.hh
@@ -32,7 +32,7 @@
// This pipeline is reusable.
//
-class Pl_StdioFile: public Pipeline
+class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline
{
public:
// f is externally maintained; this class just writes to and
@@ -48,7 +48,7 @@ class Pl_StdioFile: public Pipeline
virtual void finish();
private:
- class Members
+ class QPDF_DLL_PRIVATE Members
{
friend class Pl_StdioFile;
diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc
index 8a93721f..6e48bb35 100644
--- a/qpdf/test_driver.cc
+++ b/qpdf/test_driver.cc
@@ -3,6 +3,7 @@
#include <qpdf/QPDF.hh>
+#include <qpdf/BufferInputSource.hh>
#include <qpdf/Pl_Buffer.hh>
#include <qpdf/Pl_Discard.hh>
#include <qpdf/Pl_Flate.hh>
@@ -2314,8 +2315,9 @@ test_60(QPDF& pdf, char const* arg2)
static void
test_61(QPDF& pdf, char const* arg2)
{
- // Test to make sure exceptions can be caught properly across
- // shared library boundaries.
+ // Test to make sure type information is passed across shared
+ // library boundaries. This includes exception handling, dynamic
+ // cast, and subclassing.
pdf.setAttemptRecovery(false);
pdf.setSuppressWarnings(true);
try {
@@ -2338,6 +2340,17 @@ test_61(QPDF& pdf, char const* arg2)
} catch (std::runtime_error const&) {
std::cout << "Caught runtime_error as expected" << std::endl;
}
+
+ // Spot check RTTI for dynamic cast. We intend to have pipelines
+ // and input sources be testable, but adding comprehensive tests
+ // for everything doesn't add value as it wouldn't catch
+ // forgetting QPDF_DLL_CLASS on a new subclass.
+ BufferInputSource b("x", "y");
+ InputSource* is = &b;
+ assert(dynamic_cast<BufferInputSource*>(is) != nullptr);
+ Pl_Discard pd;
+ Pipeline* p = &pd;
+ assert(dynamic_cast<Pl_Discard*>(p) != nullptr);
}
static void