2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-11-16 09:37:08 +00:00

Add new protected inline method Pipeline::next

Also, tidy pipeline constructors and make subclasses final where possible.
This commit is contained in:
m-holger 2024-08-07 17:20:19 +01:00
parent 2cb2412fbf
commit c916dcf973
37 changed files with 256 additions and 250 deletions

View File

@ -98,13 +98,19 @@ class QPDF_DLL_CLASS Pipeline
protected:
QPDF_DLL
Pipeline* getNext(bool allow_null = false);
QPDF_DLL
Pipeline*
next() const noexcept
{
return next_;
}
std::string identifier;
private:
Pipeline(Pipeline const&) = delete;
Pipeline& operator=(Pipeline const&) = delete;
Pipeline* next;
Pipeline* next_;
};
#endif // PIPELINE_HH

View File

@ -57,8 +57,8 @@ class QPDF_DLL_CLASS Pl_Count: public Pipeline
Members(Members const&) = delete;
// 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;
qpdf_offset_t count{0};
unsigned char last_char{'\0'};
};
std::shared_ptr<Members> m;

View File

@ -19,6 +19,10 @@
#ifndef PL_FUNCTION_HH
#define PL_FUNCTION_HH
#include <qpdf/Pipeline.hh>
#include <functional>
// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can
// be reused.
//
@ -29,11 +33,6 @@
//
// It is okay to keep calling write() after a previous write throws an exception as long as the
// delegated function allows it.
#include <qpdf/Pipeline.hh>
#include <functional>
class QPDF_DLL_CLASS Pl_Function: public Pipeline
{
public:

View File

@ -64,7 +64,7 @@ class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline
Members();
Members(Members const&) = delete;
QPDFObjectHandle::TokenFilter* filter;
QPDFObjectHandle::TokenFilter* filter{nullptr};
QPDFTokenizer tokenizer;
Pl_Buffer buf;
};

View File

@ -59,9 +59,9 @@ class QPDF_DLL_CLASS Pl_RunLength: public Pipeline
Members(Members const&) = delete;
action_e action;
state_e state;
state_e state{st_top};
unsigned char buf[128];
unsigned int length;
unsigned int length{0};
std::string out;
};

View File

@ -5,18 +5,18 @@
Pipeline::Pipeline(char const* identifier, Pipeline* next) :
identifier(identifier),
next(next)
next_(next)
{
}
Pipeline*
Pipeline::getNext(bool allow_null)
{
if ((this->next == nullptr) && (!allow_null)) {
if (!next_ && !allow_null) {
throw std::logic_error(
this->identifier + ": Pipeline::getNext() called on pipeline with no next");
}
return this->next;
return next_;
}
std::string

View File

@ -18,14 +18,11 @@ Pl_AES_PDF::Pl_AES_PDF(
Pipeline(identifier, next),
crypto(QPDFCryptoProvider::getImpl()),
encrypt(encrypt),
cbc_mode(true),
first(true),
offset(0),
key_bytes(key_bytes),
use_zero_iv(false),
use_specified_iv(false),
disable_padding(false)
key_bytes(key_bytes)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_AES_PDF with nullptr as next");
}
this->key = std::make_unique<unsigned char[]>(key_bytes);
std::memcpy(this->key.get(), key, key_bytes);
std::memset(this->inbuf, 0, this->buf_size);
@ -120,7 +117,7 @@ Pl_AES_PDF::finish()
flush(!this->disable_padding);
}
this->crypto->rijndael_finalize();
getNext()->finish();
next()->finish();
}
void
@ -157,7 +154,7 @@ Pl_AES_PDF::flush(bool strip_padding)
// output stream.
initializeVector();
if (!(this->use_zero_iv || this->use_specified_iv)) {
getNext()->write(this->cbc_block, this->buf_size);
next()->write(this->cbc_block, this->buf_size);
}
} else if (this->use_zero_iv || this->use_specified_iv) {
// Initialize vector with zeroes; zero vector was not written to the beginning of
@ -196,5 +193,5 @@ Pl_AES_PDF::flush(bool strip_padding)
}
}
this->offset = 0;
getNext()->write(this->outbuf, bytes);
next()->write(this->outbuf, bytes);
}

View File

@ -5,11 +5,11 @@
#include <stdexcept>
Pl_ASCII85Decoder::Pl_ASCII85Decoder(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
pos(0),
eod(0)
Pipeline(identifier, next)
{
memset(this->inbuf, 117, 5);
if (!next) {
throw std::logic_error("Attempt to create Pl_ASCII85Decoder with nullptr as next");
}
}
void
@ -52,7 +52,7 @@ Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len)
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
unsigned char zeroes[4];
memset(zeroes, '\0', 4);
getNext()->write(zeroes, 4);
next()->write(zeroes, 4);
}
break;
@ -97,12 +97,12 @@ Pl_ASCII85Decoder::flush()
this->pos = 0;
memset(this->inbuf, 117, 5);
getNext()->write(outbuf, t);
next()->write(outbuf, t);
}
void
Pl_ASCII85Decoder::finish()
{
flush();
getNext()->finish();
next()->finish();
}

View File

@ -5,13 +5,11 @@
#include <stdexcept>
Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
pos(0),
eod(false)
Pipeline(identifier, next)
{
this->inbuf[0] = '0';
this->inbuf[1] = '0';
this->inbuf[2] = '\0';
if (!next) {
throw std::logic_error("Attempt to create Pl_ASCIIHexDecoder with nullptr as next");
}
}
void
@ -85,12 +83,12 @@ Pl_ASCIIHexDecoder::flush()
this->inbuf[1] = '0';
this->inbuf[2] = '\0';
getNext()->write(&ch, 1);
next()->write(&ch, 1);
}
void
Pl_ASCIIHexDecoder::finish()
{
flush();
getNext()->finish();
next()->finish();
}

View File

@ -25,12 +25,11 @@ to_i(int i)
Pl_Base64::Pl_Base64(char const* identifier, Pipeline* next, action_e action) :
Pipeline(identifier, next),
action(action),
pos(0),
end_of_data(false),
finished(false)
action(action)
{
reset();
if (!next) {
throw std::logic_error("Attempt to create Pl_Base64 with nullptr as next");
}
}
void
@ -125,7 +124,7 @@ Pl_Base64::flush_decode()
to_uc(0xff & outval),
};
getNext()->write(out, QIntC::to_size(3 - pad));
next()->write(out, QIntC::to_size(3 - pad));
}
void
@ -158,7 +157,7 @@ Pl_Base64::flush_encode()
for (size_t i = 0; i < 3 - this->pos; ++i) {
out[3 - i] = '=';
}
getNext()->write(out, 4);
next()->write(out, 4);
}
void
@ -176,7 +175,7 @@ Pl_Base64::finish()
flush();
}
this->finished = true;
getNext()->finish();
next()->finish();
}
void

View File

@ -25,8 +25,8 @@ Pl_Buffer::write(unsigned char const* buf, size_t len)
m->data.append(reinterpret_cast<char const*>(buf), len);
m->ready = false;
if (getNext(true)) {
getNext()->write(buf, len);
if (next()) {
next()->write(buf, len);
}
}
@ -34,8 +34,8 @@ void
Pl_Buffer::finish()
{
m->ready = true;
if (getNext(true)) {
getNext()->finish();
if (next()) {
next()->finish();
}
}

View File

@ -1,8 +1,13 @@
#include <qpdf/Pl_Concatenate.hh>
#include <stdexcept>
Pl_Concatenate::Pl_Concatenate(char const* identifier, Pipeline* next) :
Pipeline(identifier, next)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_Concatenate with nullptr as next");
}
}
Pl_Concatenate::~Pl_Concatenate() // NOLINT (modernize-use-equals-default)
@ -13,7 +18,7 @@ Pl_Concatenate::~Pl_Concatenate() // NOLINT (modernize-use-equals-default)
void
Pl_Concatenate::write(unsigned char const* data, size_t len)
{
getNext()->write(data, len);
next()->write(data, len);
}
void
@ -24,5 +29,5 @@ Pl_Concatenate::finish()
void
Pl_Concatenate::manualFinish()
{
getNext()->finish();
next()->finish();
}

View File

@ -2,9 +2,7 @@
#include <qpdf/QIntC.hh>
Pl_Count::Members::Members() :
count(0),
last_char('\0')
Pl_Count::Members::Members()
{
}
@ -12,6 +10,9 @@ Pl_Count::Pl_Count(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
m(new Members())
{
if (!next) {
throw std::logic_error("Attempt to create Pl_Count with nullptr as next");
}
}
Pl_Count::~Pl_Count() // NOLINT (modernize-use-equals-default)
@ -25,14 +26,14 @@ Pl_Count::write(unsigned char const* buf, size_t len)
if (len) {
m->count += QIntC::to_offset(len);
m->last_char = buf[len - 1];
getNext()->write(buf, len);
next()->write(buf, len);
}
}
void
Pl_Count::finish()
{
getNext()->finish();
next()->finish();
}
qpdf_offset_t

View File

@ -78,6 +78,9 @@ Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
m(new Members())
{
if (!next) {
throw std::logic_error("Attempt to create Pl_DCT with nullptr as next");
}
}
void
@ -133,7 +136,7 @@ Pl_DCT::finish()
// Special case: empty data will never succeed and probably means we're calling finish a
// second time from an exception handler.
delete b;
this->getNext()->finish();
next()->finish();
return;
}
@ -300,7 +303,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
static int const BUF_SIZE = 65536;
auto outbuffer_ph = std::make_unique<unsigned char[]>(BUF_SIZE);
unsigned char* outbuffer = outbuffer_ph.get();
jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, this->getNext());
jpeg_pipeline_dest(cinfo, outbuffer, BUF_SIZE, next());
cinfo->image_width = m->image_width;
cinfo->image_height = m->image_height;
@ -326,7 +329,7 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
(void)jpeg_write_scanlines(cinfo, row_pointer, 1);
}
jpeg_finish_compress(cinfo);
this->getNext()->finish();
next()->finish();
}
void
@ -370,8 +373,8 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
(void)jpeg_start_decompress(cinfo);
while (cinfo->output_scanline < cinfo->output_height) {
(void)jpeg_read_scanlines(cinfo, buffer, 1);
getNext()->write(buffer[0], width * sizeof(buffer[0][0]));
next()->write(buffer[0], width * sizeof(buffer[0][0]));
}
(void)jpeg_finish_decompress(cinfo);
getNext()->finish();
next()->finish();
}

View File

@ -61,6 +61,9 @@ Pl_Flate::Pl_Flate(
Pipeline(identifier, next),
m(new Members(QIntC::to_size(out_bufsize_int), action))
{
if (!next) {
throw std::logic_error("Attempt to create Pl_Flate with nullptr as next");
}
}
Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default)
@ -187,7 +190,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
throw std::runtime_error("PL_Flate memory limit exceeded");
}
}
this->getNext()->write(m->outbuf.get(), ready);
next()->write(m->outbuf.get(), ready);
zstream.next_out = m->outbuf.get();
zstream.avail_out = QIntC::to_uint(m->out_bufsize);
}
@ -228,13 +231,13 @@ Pl_Flate::finish()
}
} catch (std::exception& e) {
try {
this->getNext()->finish();
next()->finish();
} catch (...) {
// ignore secondary exception
}
throw std::runtime_error(e.what());
}
this->getNext()->finish();
next()->finish();
}
void

View File

@ -48,15 +48,15 @@ void
Pl_Function::write(unsigned char const* buf, size_t len)
{
m->fn(buf, len);
if (getNext(true)) {
getNext()->write(buf, len);
if (next()) {
next()->write(buf, len);
}
}
void
Pl_Function::finish()
{
if (getNext(true)) {
getNext()->finish();
if (next()) {
next()->finish();
}
}

View File

@ -8,25 +8,20 @@
Pl_LZWDecoder::Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change) :
Pipeline(identifier, next),
code_size(9),
next(0),
byte_pos(0),
bit_pos(0),
bits_available(0),
code_change_delta(early_code_change),
eod(false),
last_code(256)
code_change_delta(early_code_change)
{
memset(buf, 0, 3);
if (!next) {
throw std::logic_error("Attempt to create Pl_LZWDecoder with nullptr as next");
}
}
void
Pl_LZWDecoder::write(unsigned char const* bytes, size_t len)
{
for (size_t i = 0; i < len; ++i) {
this->buf[next++] = bytes[i];
if (this->next == 3) {
this->next = 0;
buf[next_char_++] = bytes[i];
if (next_char_ == 3) {
next_char_ = 0;
}
this->bits_available += 8;
if (this->bits_available >= this->code_size) {
@ -38,7 +33,7 @@ Pl_LZWDecoder::write(unsigned char const* bytes, size_t len)
void
Pl_LZWDecoder::finish()
{
getNext()->finish();
next()->finish();
}
void
@ -101,7 +96,7 @@ Pl_LZWDecoder::getFirstChar(unsigned int code)
}
void
Pl_LZWDecoder::addToTable(unsigned char next)
Pl_LZWDecoder::addToTable(unsigned char c)
{
unsigned int last_size = 0;
unsigned char const* last_data = nullptr;
@ -128,7 +123,7 @@ Pl_LZWDecoder::addToTable(unsigned char next)
Buffer entry(1 + last_size);
unsigned char* new_data = entry.getBuffer();
memcpy(new_data, last_data, last_size);
new_data[last_size] = next;
new_data[last_size] = c;
this->table.push_back(std::move(entry));
}
@ -151,11 +146,11 @@ Pl_LZWDecoder::handleCode(unsigned int code)
if (this->last_code != 256) {
// Add to the table from last time. New table entry would be what we read last plus the
// first character of what we're reading now.
unsigned char next = '\0';
unsigned char next_c = '\0';
unsigned int table_size = QIntC::to_uint(table.size());
if (code < 256) {
// just read < 256; last time's next was code
next = static_cast<unsigned char>(code);
// just read < 256; last time's next_c was code
next_c = static_cast<unsigned char>(code);
} else if (code > 257) {
size_t idx = code - 258;
if (idx > table_size) {
@ -164,16 +159,16 @@ Pl_LZWDecoder::handleCode(unsigned int code)
// The encoder would have just created this entry, so the first character of
// this entry would have been the same as the first character of the last entry.
QTC::TC("libtests", "Pl_LZWDecoder last was table size");
next = getFirstChar(this->last_code);
next_c = getFirstChar(this->last_code);
} else {
next = getFirstChar(code);
next_c = getFirstChar(code);
}
}
unsigned int new_idx = 258 + table_size;
if (new_idx == 4096) {
throw std::runtime_error("LZWDecoder: table full");
}
addToTable(next);
addToTable(next_c);
unsigned int change_idx = new_idx + code_change_delta;
if ((change_idx == 511) || (change_idx == 1023) || (change_idx == 2047)) {
++this->code_size;
@ -182,14 +177,14 @@ Pl_LZWDecoder::handleCode(unsigned int code)
if (code < 256) {
auto ch = static_cast<unsigned char>(code);
getNext()->write(&ch, 1);
next()->write(&ch, 1);
} else {
unsigned int idx = code - 258;
if (idx >= table.size()) {
throw std::runtime_error("Pl_LZWDecoder::handleCode: table overflow");
}
Buffer& b = table.at(idx);
getNext()->write(b.getBuffer(), b.getSize());
next()->write(b.getBuffer(), b.getSize());
}
}

View File

@ -3,11 +3,11 @@
#include <stdexcept>
Pl_MD5::Pl_MD5(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
in_progress(false),
enabled(true),
persist_across_finish(false)
Pipeline(identifier, next)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_MD5 with nullptr as next");
}
}
void
@ -31,13 +31,13 @@ Pl_MD5::write(unsigned char const* buf, size_t len)
}
}
this->getNext()->write(buf, len);
next()->write(buf, len);
}
void
Pl_MD5::finish()
{
this->getNext()->finish();
next()->finish();
if (!this->persist_across_finish) {
this->in_progress = false;
}

View File

@ -26,13 +26,11 @@ Pl_PNGFilter::Pl_PNGFilter(
unsigned int samples_per_pixel,
unsigned int bits_per_sample) :
Pipeline(identifier, next),
action(action),
cur_row(nullptr),
prev_row(nullptr),
buf1(nullptr),
buf2(nullptr),
pos(0)
action(action)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_PNGFilter with nullptr as next");
}
if (samples_per_pixel < 1) {
throw std::runtime_error("PNGFilter created with invalid samples_per_pixel");
}
@ -130,7 +128,7 @@ Pl_PNGFilter::decodeRow()
}
}
getNext()->write(this->cur_row + 1, this->bytes_per_row);
next()->write(this->cur_row + 1, this->bytes_per_row);
}
void
@ -230,14 +228,14 @@ Pl_PNGFilter::encodeRow()
{
// For now, hard-code to using UP filter.
unsigned char ch = 2;
getNext()->write(&ch, 1);
next()->write(&ch, 1);
if (this->prev_row) {
for (unsigned int i = 0; i < this->bytes_per_row; ++i) {
ch = static_cast<unsigned char>(this->cur_row[i] - this->prev_row[i]);
getNext()->write(&ch, 1);
next()->write(&ch, 1);
}
} else {
getNext()->write(this->cur_row, this->bytes_per_row);
next()->write(this->cur_row, this->bytes_per_row);
}
}
@ -253,5 +251,5 @@ Pl_PNGFilter::finish()
this->pos = 0;
memset(this->cur_row, 0, this->bytes_per_row + 1);
getNext()->finish();
next()->finish();
}

View File

@ -5,7 +5,6 @@
#include <stdexcept>
Pl_QPDFTokenizer::Members::Members() :
filter(nullptr),
buf("tokenizer buffer")
{
}
@ -56,8 +55,7 @@ Pl_QPDFTokenizer::finish()
}
m->filter->handleEOF();
QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(m->filter, nullptr);
Pipeline* next = this->getNext(true);
if (next) {
next->finish();
if (next()) {
next()->finish();
}
}

View File

@ -12,6 +12,9 @@ Pl_RC4::Pl_RC4(
out_bufsize(out_bufsize),
rc4(key_data, key_len)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_RC4 with nullptr as next");
}
this->outbuf = QUtil::make_shared_array<unsigned char>(out_bufsize);
}
@ -31,13 +34,13 @@ Pl_RC4::write(unsigned char const* data, size_t len)
// lgtm[cpp/weak-cryptographic-algorithm]
rc4.process(p, bytes, outbuf.get());
p += bytes;
getNext()->write(outbuf.get(), bytes);
next()->write(outbuf.get(), bytes);
}
}
void
Pl_RC4::finish()
{
this->outbuf = nullptr;
this->getNext()->finish();
outbuf = nullptr;
next()->finish();
}

View File

@ -4,9 +4,7 @@
#include <qpdf/QUtil.hh>
Pl_RunLength::Members::Members(action_e action) :
action(action),
state(st_top),
length(0)
action(action)
{
}
@ -14,6 +12,9 @@ Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, action_e acti
Pipeline(identifier, next),
m(new Members(action))
{
if (!next) {
throw std::logic_error("Attempt to create Pl_RunLength with nullptr as next");
}
}
Pl_RunLength::~Pl_RunLength() // NOLINT (modernize-use-equals-default)
@ -119,12 +120,12 @@ Pl_RunLength::flush_encode()
throw std::logic_error("Pl_RunLength: invalid length in flush_encode for run");
}
auto ch = static_cast<unsigned char>(257 - m->length);
this->getNext()->write(&ch, 1);
this->getNext()->write(&m->buf[0], 1);
next()->write(&ch, 1);
next()->write(&m->buf[0], 1);
} else if (m->length > 0) {
auto ch = static_cast<unsigned char>(m->length - 1);
this->getNext()->write(&ch, 1);
this->getNext()->write(m->buf, m->length);
next()->write(&ch, 1);
next()->write(m->buf, m->length);
}
m->state = st_top;
m->length = 0;
@ -136,13 +137,12 @@ Pl_RunLength::finish()
// When decoding, we might have read a length byte not followed by data, which means the stream
// was terminated early, but we will just ignore this case since this is the only sensible thing
// to do.
auto next = getNext();
if (m->action == a_encode) {
flush_encode();
unsigned char ch = 128;
next->write(&ch, 1);
next()->write(&ch, 1);
} else {
next->writeString(m->out);
next()->writeString(m->out);
}
next->finish();
next()->finish();
}

View File

@ -31,16 +31,16 @@ Pl_SHA2::write(unsigned char const* buf, size_t len)
data += bytes;
}
if (this->getNext(true)) {
this->getNext()->write(buf, len);
if (next()) {
next()->write(buf, len);
}
}
void
Pl_SHA2::finish()
{
if (this->getNext(true)) {
this->getNext()->finish();
if (next()) {
next()->finish();
}
this->crypto->SHA2_finalize();
this->in_progress = false;

View File

@ -25,15 +25,15 @@ Pl_String::write(unsigned char const* buf, size_t len)
return;
}
m->s.append(reinterpret_cast<char const*>(buf), len);
if (getNext(true)) {
getNext()->write(buf, len);
if (next()) {
next()->write(buf, len);
}
}
void
Pl_String::finish()
{
if (getNext(true)) {
getNext()->finish();
if (next()) {
next()->finish();
}
}

View File

@ -23,9 +23,11 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
action(action),
columns(columns),
samples_per_pixel(samples_per_pixel),
bits_per_sample(bits_per_sample),
p_next(getNext())
bits_per_sample(bits_per_sample)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_TIFFPredictor with nullptr as next");
}
if (samples_per_pixel < 1) {
throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel");
}
@ -74,7 +76,7 @@ Pl_TIFFPredictor::processRow()
QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1));
previous.assign(samples_per_pixel, 0);
if (bits_per_sample != 8) {
BitWriter bw(p_next);
BitWriter bw(next());
BitStream in(cur_row.data(), cur_row.size());
for (unsigned int col = 0; col < this->columns; ++col) {
for (auto& prev: previous) {
@ -93,13 +95,14 @@ Pl_TIFFPredictor::processRow()
bw.flush();
} else {
out.clear();
auto next = cur_row.begin();
auto next_it = cur_row.begin();
auto cr_end = cur_row.end();
auto pr_end = previous.end();
while (next != cr_end) {
for (auto prev = previous.begin(); prev != pr_end && next != cr_end; ++prev, ++next) {
long long sample = *next;
while (next_it != cr_end) {
for (auto prev = previous.begin(); prev != pr_end && next_it != cr_end;
++prev, ++next_it) {
long long sample = *next_it;
long long new_sample = sample;
if (action == a_encode) {
new_sample -= *prev;
@ -111,7 +114,7 @@ Pl_TIFFPredictor::processRow()
out.push_back(static_cast<unsigned char>(255U & new_sample));
}
}
p_next->write(out.data(), out.size());
next()->write(out.data(), out.size());
}
}
@ -124,5 +127,5 @@ Pl_TIFFPredictor::finish()
processRow();
}
cur_row.clear();
p_next->finish();
next()->finish();
}

View File

@ -14,19 +14,22 @@ namespace
Pl_Track(char const* identifier, Pipeline* next) :
Pipeline(identifier, next)
{
if (!next) {
throw std::logic_error("Attempt to create Pl_Track with nullptr as next");
}
}
void
write(unsigned char const* data, size_t len) override
write(unsigned char const* data, size_t len) final
{
this->used = true;
getNext()->write(data, len);
used = true;
next()->write(data, len);
}
void
finish() override
finish() final
{
getNext()->finish();
next()->finish();
}
bool

View File

@ -181,13 +181,13 @@ QPDFObjectHandle::ParserCallbacks::terminateParsing()
namespace
{
class LastChar: public Pipeline
class LastChar final: public Pipeline
{
public:
LastChar(Pipeline* next);
~LastChar() override = default;
void write(unsigned char const* data, size_t len) override;
void finish() override;
LastChar(Pipeline& next);
~LastChar() final = default;
void write(unsigned char const* data, size_t len) final;
void finish() final;
unsigned char getLastChar();
private:
@ -195,8 +195,8 @@ namespace
};
} // namespace
LastChar::LastChar(Pipeline* next) :
Pipeline("lastchar", next)
LastChar::LastChar(Pipeline& next) :
Pipeline("lastchar", &next)
{
}
@ -206,13 +206,13 @@ LastChar::write(unsigned char const* data, size_t len)
if (len > 0) {
this->last_char = data[len - 1];
}
getNext()->write(data, len);
next()->write(data, len);
}
void
LastChar::finish()
{
getNext()->finish();
next()->finish();
}
unsigned char
@ -2073,7 +2073,7 @@ QPDFObjectHandle::pipeContentStreams(
if (need_newline) {
buf.writeCStr("\n");
}
LastChar lc(&buf);
LastChar lc(buf);
if (!stream.pipeStreamData(&lc, 0, qpdf_dl_specialized)) {
QTC::TC("qpdf", "QPDFObjectHandle errors in parsecontent");
throw QPDFExc(

View File

@ -7,8 +7,7 @@
// This pipeline implements AES-128 and AES-256 with CBC and block padding as specified in the PDF
// specification.
class Pl_AES_PDF: public Pipeline
class Pl_AES_PDF final: public Pipeline
{
public:
// key should be a pointer to key_bytes bytes of data
@ -18,10 +17,10 @@ class Pl_AES_PDF: public Pipeline
bool encrypt,
unsigned char const* key,
size_t key_bytes);
~Pl_AES_PDF() override = default;
~Pl_AES_PDF() final = default;
void write(unsigned char const* data, size_t len) override;
void finish() override;
void write(unsigned char const* data, size_t len) final;
void finish() final;
// Use zero initialization vector; needed for AESV3
void useZeroIV();
@ -45,18 +44,18 @@ class Pl_AES_PDF: public Pipeline
std::shared_ptr<QPDFCryptoImpl> crypto;
bool encrypt;
bool cbc_mode;
bool first;
size_t offset; // offset into memory buffer
bool cbc_mode{true};
bool first{true};
size_t offset{0}; // offset into memory buffer
std::unique_ptr<unsigned char[]> key;
size_t key_bytes;
size_t key_bytes{0};
unsigned char inbuf[buf_size];
unsigned char outbuf[buf_size];
unsigned char cbc_block[buf_size];
unsigned char specified_iv[buf_size];
bool use_zero_iv;
bool use_specified_iv;
bool disable_padding;
bool use_zero_iv{false};
bool use_specified_iv{false};
bool disable_padding{false};
};
#endif // PL_AES_PDF_HH

View File

@ -3,20 +3,20 @@
#include <qpdf/Pipeline.hh>
class Pl_ASCII85Decoder: public Pipeline
class Pl_ASCII85Decoder final: public Pipeline
{
public:
Pl_ASCII85Decoder(char const* identifier, Pipeline* next);
~Pl_ASCII85Decoder() override = default;
void write(unsigned char const* buf, size_t len) override;
void finish() override;
~Pl_ASCII85Decoder() final = default;
void write(unsigned char const* buf, size_t len) final;
void finish() final;
private:
void flush();
unsigned char inbuf[5];
size_t pos;
size_t eod;
unsigned char inbuf[5]{117, 117, 117, 117, 117};
size_t pos{0};
size_t eod{0};
};
#endif // PL_ASCII85DECODER_HH

View File

@ -3,20 +3,20 @@
#include <qpdf/Pipeline.hh>
class Pl_ASCIIHexDecoder: public Pipeline
class Pl_ASCIIHexDecoder final: public Pipeline
{
public:
Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next);
~Pl_ASCIIHexDecoder() override = default;
void write(unsigned char const* buf, size_t len) override;
void finish() override;
~Pl_ASCIIHexDecoder() final = default;
void write(unsigned char const* buf, size_t len) final;
void finish() final;
private:
void flush();
char inbuf[3];
size_t pos;
bool eod;
char inbuf[3]{'0', '0', '\0'};
size_t pos{0};
bool eod{false};
};
#endif // PL_ASCIIHEXDECODER_HH

View File

@ -3,14 +3,14 @@
#include <qpdf/Pipeline.hh>
class Pl_Base64: public Pipeline
class Pl_Base64 final: public Pipeline
{
public:
enum action_e { a_encode, a_decode };
Pl_Base64(char const* identifier, Pipeline* next, action_e);
~Pl_Base64() override = default;
void write(unsigned char const* buf, size_t len) override;
void finish() override;
~Pl_Base64() final = default;
void write(unsigned char const* buf, size_t len) final;
void finish() final;
private:
void decode(unsigned char const* buf, size_t len);
@ -21,10 +21,10 @@ class Pl_Base64: public Pipeline
void reset();
action_e action;
unsigned char buf[4];
size_t pos;
bool end_of_data;
bool finished;
unsigned char buf[4]{0, 0, 0, 0};
size_t pos{0};
bool end_of_data{false};
bool finished{false};
};
#endif // PL_BASE64_HH

View File

@ -6,13 +6,13 @@
#include <qpdf/Buffer.hh>
#include <vector>
class Pl_LZWDecoder: public Pipeline
class Pl_LZWDecoder final: public Pipeline
{
public:
Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change);
~Pl_LZWDecoder() override = default;
void write(unsigned char const* buf, size_t len) override;
void finish() override;
~Pl_LZWDecoder() final = default;
void write(unsigned char const* buf, size_t len) final;
void finish() final;
private:
void sendNextCode();
@ -21,18 +21,18 @@ class Pl_LZWDecoder: public Pipeline
void addToTable(unsigned char next);
// members used for converting bits to codes
unsigned char buf[3];
unsigned int code_size;
unsigned int next;
unsigned int byte_pos;
unsigned int bit_pos; // left to right: 01234567
unsigned int bits_available;
unsigned char buf[3]{0, 0, 0};
unsigned int code_size{9};
unsigned int next_char_{0};
unsigned int byte_pos{0};
unsigned int bit_pos{0}; // left to right: 01234567
unsigned int bits_available{0};
// members used for handle LZW decompression
bool code_change_delta;
bool eod;
bool code_change_delta{false};
bool eod{false};
std::vector<Buffer> table;
unsigned int last_code;
unsigned int last_code{256};
};
#endif // PL_LZWDECODER_HH

View File

@ -1,22 +1,21 @@
#ifndef PL_MD5_HH
#define PL_MD5_HH
#include <qpdf/MD5.hh>
#include <qpdf/Pipeline.hh>
// This pipeline sends its output to its successor unmodified. After calling finish, the MD5
// checksum of the data that passed through the pipeline is available.
// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first
// call to write() after a call to finish() initializes a new MD5 object.
#include <qpdf/MD5.hh>
#include <qpdf/Pipeline.hh>
class Pl_MD5: public Pipeline
class Pl_MD5 final: public Pipeline
{
public:
Pl_MD5(char const* identifier, Pipeline* next);
~Pl_MD5() override = default;
void write(unsigned char const*, size_t) override;
void finish() override;
~Pl_MD5() final = default;
void write(unsigned char const*, size_t) final;
void finish() final;
std::string getHexDigest();
// Enable/disable. Disabling the pipeline causes it to become a pass-through. This makes it
// possible to stick an MD5 pipeline in a pipeline when it may or may not be required. Disabling
@ -27,10 +26,10 @@ class Pl_MD5: public Pipeline
void persistAcrossFinish(bool);
private:
bool in_progress;
bool in_progress{false};
MD5 md5;
bool enabled;
bool persist_across_finish;
bool enabled{true};
bool persist_across_finish{false};
};
#endif // PL_MD5_HH

View File

@ -1,15 +1,14 @@
#ifndef PL_PNGFILTER_HH
#define PL_PNGFILTER_HH
// This pipeline applies or reverses the application of a PNG filter as described in the PNG
// specification.
// NOTE: In its current implementation, this filter always encodes using the "up" filter, but it
// decodes all the filters.
#include <qpdf/Pipeline.hh>
class Pl_PNGFilter: public Pipeline
// This pipeline applies or reverses the application of a PNG filter as described in the PNG
// specification.
//
// NOTE: In its current implementation, this filter always encodes using the "up" filter, but it
// decodes all the filters.
class Pl_PNGFilter final: public Pipeline
{
public:
// Encoding is only partially supported
@ -22,14 +21,14 @@ class Pl_PNGFilter: public Pipeline
unsigned int columns,
unsigned int samples_per_pixel = 1,
unsigned int bits_per_sample = 8);
~Pl_PNGFilter() override = default;
~Pl_PNGFilter() final = default;
// Limit the memory used.
// NB This is a static option affecting all Pl_PNGFilter instances.
static void setMemoryLimit(unsigned long long limit);
void write(unsigned char const* data, size_t len) override;
void finish() override;
void write(unsigned char const* data, size_t len) final;
void finish() final;
private:
void decodeSub();
@ -44,12 +43,12 @@ class Pl_PNGFilter: public Pipeline
action_e action;
unsigned int bytes_per_row;
unsigned int bytes_per_pixel;
unsigned char* cur_row; // points to buf1 or buf2
unsigned char* prev_row; // points to buf1 or buf2
unsigned char* cur_row{nullptr}; // points to buf1 or buf2
unsigned char* prev_row{nullptr}; // points to buf1 or buf2
std::shared_ptr<unsigned char> buf1;
std::shared_ptr<unsigned char> buf2;
size_t pos;
size_t incoming;
size_t pos{0};
size_t incoming{0};
};
#endif // PL_PNGFILTER_HH

View File

@ -5,7 +5,7 @@
#include <qpdf/RC4.hh>
class Pl_RC4: public Pipeline
class Pl_RC4 final: public Pipeline
{
public:
static size_t const def_bufsize = 65536;
@ -17,10 +17,10 @@ class Pl_RC4: public Pipeline
unsigned char const* key_data,
int key_len = -1,
size_t out_bufsize = def_bufsize);
~Pl_RC4() override = default;
~Pl_RC4() final = default;
void write(unsigned char const* data, size_t len) override;
void finish() override;
void write(unsigned char const* data, size_t len) final;
void finish() final;
private:
std::shared_ptr<unsigned char> outbuf;

View File

@ -1,26 +1,25 @@
#ifndef PL_SHA2_HH
#define PL_SHA2_HH
// Bits must be a supported number of bits, currently only 256, 384, or 512. Passing 0 as bits
// leaves the pipeline uncommitted, in which case resetBits must be called before the pipeline is
// used. If a next is provided, this pipeline sends its output to its successor unmodified. After
// calling finish, the SHA2 checksum of the data that passed through the pipeline is available.
// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first
// call to write() after a call to finish() initializes a new SHA2 object. resetBits may also be
// called between finish and the next call to write.
#include <qpdf/Pipeline.hh>
#include <qpdf/QPDFCryptoImpl.hh>
#include <memory>
class Pl_SHA2: public Pipeline
// Bits must be a supported number of bits, currently only 256, 384, or 512. Passing 0 as bits
// leaves the pipeline uncommitted, in which case resetBits must be called before the pipeline is
// used. If a next is provided, this pipeline sends its output to its successor unmodified. After
// calling finish, the SHA2 checksum of the data that passed through the pipeline is available.
//
// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first
// call to write() after a call to finish() initializes a new SHA2 object. resetBits may also be
// called between finish and the next call to write.
class Pl_SHA2 final: public Pipeline
{
public:
Pl_SHA2(int bits = 0, Pipeline* next = nullptr);
~Pl_SHA2() override = default;
void write(unsigned char const*, size_t) override;
void finish() override;
~Pl_SHA2() final = default;
void write(unsigned char const*, size_t) final;
void finish() final;
void resetBits(int bits);
std::string getHexDigest();
std::string getRawDigest();

View File

@ -40,7 +40,6 @@ class Pl_TIFFPredictor: public Pipeline
std::vector<unsigned char> cur_row;
std::vector<long long> previous;
std::vector<unsigned char> out;
Pipeline* p_next;
};
#endif // PL_TIFFPREDICTOR_HH