2008-04-29 12:55:25 +00:00
|
|
|
#include <qpdf/Pl_ASCIIHexDecoder.hh>
|
2022-02-04 21:31:31 +00:00
|
|
|
|
2008-04-29 12:55:25 +00:00
|
|
|
#include <qpdf/QTC.hh>
|
2023-05-20 11:22:32 +00:00
|
|
|
#include <cctype>
|
2009-09-26 18:36:04 +00:00
|
|
|
#include <stdexcept>
|
2008-04-29 12:55:25 +00:00
|
|
|
|
|
|
|
Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
|
|
|
|
Pipeline(identifier, next),
|
|
|
|
pos(0),
|
|
|
|
eod(false)
|
|
|
|
{
|
2013-02-28 21:22:54 +00:00
|
|
|
this->inbuf[0] = '0';
|
|
|
|
this->inbuf[1] = '0';
|
|
|
|
this->inbuf[2] = '\0';
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-05-03 21:43:07 +00:00
|
|
|
Pl_ASCIIHexDecoder::write(unsigned char const* buf, size_t len)
|
2008-04-29 12:55:25 +00:00
|
|
|
{
|
|
|
|
if (this->eod) {
|
2022-02-08 14:18:08 +00:00
|
|
|
return;
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
2012-06-20 15:20:57 +00:00
|
|
|
for (size_t i = 0; i < len; ++i) {
|
2022-02-08 14:18:08 +00:00
|
|
|
char ch = static_cast<char>(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;
|
2008-04-29 12:55:25 +00:00
|
|
|
|
2022-02-08 14:18:08 +00:00
|
|
|
case '>':
|
|
|
|
this->eod = true;
|
|
|
|
flush();
|
|
|
|
break;
|
2008-04-29 12:55:25 +00:00
|
|
|
|
2022-02-08 14:18:08 +00:00
|
|
|
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 std::runtime_error(
|
|
|
|
std::string("character out of range"
|
|
|
|
" during base Hex decode: ") +
|
|
|
|
t);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (this->eod) {
|
|
|
|
break;
|
|
|
|
}
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Pl_ASCIIHexDecoder::flush()
|
|
|
|
{
|
|
|
|
if (this->pos == 0) {
|
2022-02-08 14:18:08 +00:00
|
|
|
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
|
|
|
|
return;
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
|
|
|
int b[2];
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
2022-02-08 14:18:08 +00:00
|
|
|
if (this->inbuf[i] >= 'A') {
|
|
|
|
b[i] = this->inbuf[i] - 'A' + 10;
|
|
|
|
} else {
|
|
|
|
b[i] = this->inbuf[i] - '0';
|
|
|
|
}
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
2023-05-20 12:34:53 +00:00
|
|
|
auto ch = static_cast<unsigned char>((b[0] << 4) + b[1]);
|
2008-04-29 12:55:25 +00:00
|
|
|
|
|
|
|
QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush", (this->pos == 2) ? 0 : 1);
|
2021-01-04 16:55:28 +00:00
|
|
|
// Reset before calling getNext()->write in case that throws an
|
|
|
|
// exception.
|
2008-04-29 12:55:25 +00:00
|
|
|
this->pos = 0;
|
2013-02-28 21:22:54 +00:00
|
|
|
this->inbuf[0] = '0';
|
|
|
|
this->inbuf[1] = '0';
|
|
|
|
this->inbuf[2] = '\0';
|
2021-01-04 16:55:28 +00:00
|
|
|
|
|
|
|
getNext()->write(&ch, 1);
|
2008-04-29 12:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Pl_ASCIIHexDecoder::finish()
|
|
|
|
{
|
|
|
|
flush();
|
|
|
|
getNext()->finish();
|
|
|
|
}
|