2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-09-27 20:49:06 +00:00

Add new method QPDFTokenizer::nextToken

This commit is contained in:
m-holger 2022-10-04 20:50:36 +01:00 committed by Jay Berkenbilt
parent a07d2b4190
commit 863d95e567
2 changed files with 51 additions and 25 deletions

View File

@ -204,6 +204,18 @@ class QPDFTokenizer
QPDF_DLL QPDF_DLL
void expectInlineImage(std::shared_ptr<InputSource> input); void expectInlineImage(std::shared_ptr<InputSource> input);
// Read a token from an input source. Context describes the
// context in which the token is being read and is used in the
// exception thrown if there is an error. After a token is read,
// the position of the input source returned by input->tell()
// points to just after the token, and the input source's "last
// offset" as returned by input->getLastOffset() points to the
// beginning of the token. Returns false if the token is bad
// or if scanning produced an error message for any reason.
QPDF_DLL
bool nextToken(
InputSource& input, std::string const& context, size_t max_len = 0);
private: private:
QPDFTokenizer(QPDFTokenizer const&) = delete; QPDFTokenizer(QPDFTokenizer const&) = delete;
QPDFTokenizer& operator=(QPDFTokenizer const&) = delete; QPDFTokenizer& operator=(QPDFTokenizer const&) = delete;

View File

@ -805,7 +805,9 @@ QPDFTokenizer::presentEOF()
void void
QPDFTokenizer::expectInlineImage(std::shared_ptr<InputSource> input) QPDFTokenizer::expectInlineImage(std::shared_ptr<InputSource> input)
{ {
if (this->state != st_before_token) { if (this->state == st_token_ready) {
reset();
} else if (this->state != st_before_token) {
throw std::logic_error("QPDFTokenizer::expectInlineImage called" throw std::logic_error("QPDFTokenizer::expectInlineImage called"
" when tokenizer is in improper state"); " when tokenizer is in improper state");
} }
@ -941,11 +943,40 @@ QPDFTokenizer::readToken(
bool allow_bad, bool allow_bad,
size_t max_len) size_t max_len)
{ {
qpdf_offset_t offset = input->fastTell(); nextToken(*input, context, max_len);
Token token;
bool unread_char;
char char_to_unread;
getToken(token, unread_char, char_to_unread);
if (token.getType() == tt_bad) {
if (allow_bad) {
QTC::TC("qpdf", "QPDFTokenizer allowing bad token");
} else {
throw QPDFExc(
qpdf_e_damaged_pdf,
input->getName(),
context,
input->getLastOffset(),
token.getErrorMessage());
}
}
return token;
}
bool
QPDFTokenizer::nextToken(
InputSource& input, std::string const& context, size_t max_len)
{
if (this->state != st_inline_image) {
reset();
}
qpdf_offset_t offset = input.fastTell();
while (this->state != st_token_ready) { while (this->state != st_token_ready) {
char ch; char ch;
if (!input->fastRead(ch)) { if (!input.fastRead(ch)) {
presentEOF(); presentEOF();
if ((this->type == tt_eof) && (!this->allow_eof)) { if ((this->type == tt_eof) && (!this->allow_eof)) {
@ -954,7 +985,7 @@ QPDFTokenizer::readToken(
// exercised. // exercised.
this->type = tt_bad; this->type = tt_bad;
this->error_message = "unexpected EOF"; this->error_message = "unexpected EOF";
offset = input->getLastOffset(); offset = input.getLastOffset();
} }
} else { } else {
handleCharacter(ch); handleCharacter(ch);
@ -976,28 +1007,11 @@ QPDFTokenizer::readToken(
} }
} }
Token token; input.fastUnread(!this->in_token && !this->before_token);
bool unread_char;
char char_to_unread;
getToken(token, unread_char, char_to_unread);
input->fastUnread(unread_char);
if (token.getType() != tt_eof) { if (this->type != tt_eof) {
input->setLastOffset(offset); input.setLastOffset(offset);
} }
if (token.getType() == tt_bad) { return this->error_message.empty();
if (allow_bad) {
QTC::TC("qpdf", "QPDFTokenizer allowing bad token");
} else {
throw QPDFExc(
qpdf_e_damaged_pdf,
input->getName(),
context,
offset,
token.getErrorMessage());
}
}
return token;
} }