qpdf/libqpdf/Pl_ASCIIHexDecoder.cc

109 lines
1.8 KiB
C++

#include <qpdf/Pl_ASCIIHexDecoder.hh>
#include <qpdf/QEXC.hh>
#include <qpdf/QTC.hh>
#include <string.h>
#include <ctype.h>
Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
Pipeline(identifier, next),
pos(0),
eod(false)
{
strcpy(this->inbuf, "00");
}
Pl_ASCIIHexDecoder::~Pl_ASCIIHexDecoder()
{
}
void
Pl_ASCIIHexDecoder::write(unsigned char* buf, int len)
{
if (this->eod)
{
return;
}
for (int i = 0; i < len; ++i)
{
char ch = toupper(buf[i]);
switch (ch)
{
case ' ':
case '\f':
case '\v':
case '\t':
case '\r':
case '\n':
QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
// ignore whitespace
break;
case '>':
this->eod = true;
flush();
break;
default:
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'F')))
{
this->inbuf[this->pos++] = ch;
if (this->pos == 2)
{
flush();
}
}
else
{
char t[2];
t[0] = ch;
t[1] = 0;
throw QEXC::General(
std::string("character out of range during base Hex decode: ") + t);
}
break;
}
if (this->eod)
{
break;
}
}
}
void
Pl_ASCIIHexDecoder::flush()
{
if (this->pos == 0)
{
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
return;
}
int b[2];
for (int i = 0; i < 2; ++i)
{
if (this->inbuf[i] >= 'A')
{
b[i] = this->inbuf[i] - 'A' + 10;
}
else
{
b[i] = this->inbuf[i] - '0';
}
}
unsigned char ch = (unsigned char)((b[0] << 4) + b[1]);
QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush",
(this->pos == 2) ? 0 : 1);
getNext()->write(&ch, 1);
this->pos = 0;
strcpy(this->inbuf, "00");
}
void
Pl_ASCIIHexDecoder::finish()
{
flush();
getNext()->finish();
}