mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
cb769c62e5
This comment expands all tabs using an 8-character tab-width. You should ignore this commit when using git blame or use git blame -w. In the early days, I used to use tabs where possible for indentation, since emacs did this automatically. In recent years, I have switched to only using spaces, which means qpdf source code has been a mixture of spaces and tabs. I have avoided cleaning this up because of not wanting gratuitous whitespaces change to cloud the output of git blame, but I changed my mind after discussing with users who view qpdf source code in editors/IDEs that have other tab widths by default and in light of the fact that I am planning to start applying automatic code formatting soon.
138 lines
3.0 KiB
C++
138 lines
3.0 KiB
C++
#include <qpdf/Pl_ASCII85Decoder.hh>
|
|
|
|
#include <qpdf/QTC.hh>
|
|
#include <stdexcept>
|
|
#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, size_t len)
|
|
{
|
|
if (eod > 1)
|
|
{
|
|
return;
|
|
}
|
|
for (size_t i = 0; i < len; ++i)
|
|
{
|
|
if (eod > 1)
|
|
{
|
|
break;
|
|
}
|
|
else if (eod == 1)
|
|
{
|
|
if (buf[i] == '>')
|
|
{
|
|
flush();
|
|
eod = 2;
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error(
|
|
"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 std::runtime_error(
|
|
"unexpected z during base 85 decode");
|
|
}
|
|
else
|
|
{
|
|
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
|
unsigned char zeroes[4];
|
|
memset(zeroes, '\0', 4);
|
|
getNext()->write(zeroes, 4);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if ((buf[i] < 33) || (buf[i] > 117))
|
|
{
|
|
throw std::runtime_error(
|
|
"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] - 33U);
|
|
}
|
|
|
|
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);
|
|
// Reset before calling getNext()->write in case that throws an
|
|
// exception.
|
|
auto t = this->pos - 1;
|
|
this->pos = 0;
|
|
memset(this->inbuf, 117, 5);
|
|
|
|
getNext()->write(outbuf, t);
|
|
}
|
|
|
|
void
|
|
Pl_ASCII85Decoder::finish()
|
|
{
|
|
flush();
|
|
getNext()->finish();
|
|
}
|