diff options
Diffstat (limited to 'libqpdf/Pl_ASCII85Decoder.cc')
-rw-r--r-- | libqpdf/Pl_ASCII85Decoder.cc | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/libqpdf/Pl_ASCII85Decoder.cc b/libqpdf/Pl_ASCII85Decoder.cc new file mode 100644 index 00000000..4ecdaf41 --- /dev/null +++ b/libqpdf/Pl_ASCII85Decoder.cc @@ -0,0 +1,131 @@ +#include <qpdf/Pl_ASCII85Decoder.hh> +#include <qpdf/QEXC.hh> +#include <qpdf/QTC.hh> +#include <string.h> + +Pl_ASCII85Decoder::Pl_ASCII85Decoder(char const* identifier, Pipeline* next) : + Pipeline(identifier, next), + pos(0), + eod(0) +{ + memset(this->inbuf, 117, 5); +} + +Pl_ASCII85Decoder::~Pl_ASCII85Decoder() +{ +} + +void +Pl_ASCII85Decoder::write(unsigned char* buf, int len) +{ + if (eod > 1) + { + return; + } + for (int i = 0; i < len; ++i) + { + if (eod > 1) + { + break; + } + else if (eod == 1) + { + if (buf[i] == '>') + { + flush(); + eod = 2; + } + else + { + throw QEXC::General( + "broken end-of-data sequence in base 85 data"); + } + } + else + { + switch (buf[i]) + { + case ' ': + case '\f': + case '\v': + case '\t': + case '\r': + case '\n': + QTC::TC("libtests", "Pl_ASCII85Decoder ignore space"); + // ignore whitespace + break; + + case '~': + eod = 1; + break; + + case 'z': + if (pos != 0) + { + throw QEXC::General( + "unexpected z during base 85 decode"); + } + else + { + QTC::TC("libtests", "Pl_ASCII85Decoder read z"); + getNext()->write((unsigned char*)"\000\000\000\000", 4); + } + break; + + default: + if ((buf[i] < 33) || (buf[i] > 117)) + { + throw QEXC::General + ("character out of range during base 85 decode"); + } + else + { + this->inbuf[this->pos++] = buf[i]; + if (pos == 5) + { + flush(); + } + } + break; + } + } + } +} + +void +Pl_ASCII85Decoder::flush() +{ + if (this->pos == 0) + { + QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush"); + return; + } + unsigned long lval = 0; + for (int i = 0; i < 5; ++i) + { + lval *= 85; + lval += (this->inbuf[i] - 33); + } + + unsigned char outbuf[4]; + memset(outbuf, 0, 4); + for (int i = 3; i >= 0; --i) + { + outbuf[i] = lval & 0xff; + lval >>= 8; + } + + QTC::TC("libtests", "Pl_ASCII85Decoder partial flush", + (this->pos == 5) ? 0 : 1); + getNext()->write(outbuf, this->pos - 1); + + this->pos = 0; + memset(this->inbuf, 117, 5); +} + +void +Pl_ASCII85Decoder::finish() +{ + flush(); + getNext()->finish(); +} |