aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/Pl_ASCIIHexDecoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf/Pl_ASCIIHexDecoder.cc')
-rw-r--r--libqpdf/Pl_ASCIIHexDecoder.cc108
1 files changed, 108 insertions, 0 deletions
diff --git a/libqpdf/Pl_ASCIIHexDecoder.cc b/libqpdf/Pl_ASCIIHexDecoder.cc
new file mode 100644
index 00000000..d1b4ef1c
--- /dev/null
+++ b/libqpdf/Pl_ASCIIHexDecoder.cc
@@ -0,0 +1,108 @@
+#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();
+}