mirror of
https://github.com/qpdf/qpdf.git
synced 2024-11-02 03:42:30 +00:00
Optimise QPDFParser::parse for #311 problem
Avoid creating new null objects that later will be discarded and made implicit. Part of #729
This commit is contained in:
parent
97a7ad1d80
commit
70d985f942
@ -51,9 +51,12 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
int bad_count = 0;
|
int bad_count = 0;
|
||||||
int good_count = 0;
|
int good_count = 0;
|
||||||
bool b_contents = false;
|
bool b_contents = false;
|
||||||
|
bool is_null = false;
|
||||||
|
auto null_oh = QPDFObjectHandle::newNull();
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
bool bad = false;
|
bool bad = false;
|
||||||
|
is_null = false;
|
||||||
auto& frame = stack.back();
|
auto& frame = stack.back();
|
||||||
auto& olist = frame.olist;
|
auto& olist = frame.olist;
|
||||||
parser_state_e state = state_stack.back();
|
parser_state_e state = state_stack.back();
|
||||||
@ -83,7 +86,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
case QPDFTokenizer::tt_bad:
|
case QPDFTokenizer::tt_bad:
|
||||||
QTC::TC("qpdf", "QPDFParser bad token in parse");
|
QTC::TC("qpdf", "QPDFParser bad token in parse");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_brace_open:
|
case QPDFTokenizer::tt_brace_open:
|
||||||
@ -91,7 +94,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
QTC::TC("qpdf", "QPDFParser bad brace");
|
QTC::TC("qpdf", "QPDFParser bad brace");
|
||||||
warn("treating unexpected brace token as null");
|
warn("treating unexpected brace token as null");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_array_close:
|
case QPDFTokenizer::tt_array_close:
|
||||||
@ -101,7 +104,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
QTC::TC("qpdf", "QPDFParser bad array close");
|
QTC::TC("qpdf", "QPDFParser bad array close");
|
||||||
warn("treating unexpected array close token as null");
|
warn("treating unexpected array close token as null");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -112,7 +115,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
QTC::TC("qpdf", "QPDFParser bad dictionary close");
|
QTC::TC("qpdf", "QPDFParser bad dictionary close");
|
||||||
warn("unexpected dictionary close token");
|
warn("unexpected dictionary close token");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -122,7 +125,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
QTC::TC("qpdf", "QPDFParser too deep");
|
QTC::TC("qpdf", "QPDFParser too deep");
|
||||||
warn("ignoring excessively deeply nested data structure");
|
warn("ignoring excessively deeply nested data structure");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
state = st_top;
|
state = st_top;
|
||||||
} else {
|
} else {
|
||||||
state = st_start;
|
state = st_start;
|
||||||
@ -140,7 +143,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_null:
|
case QPDFTokenizer::tt_null:
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_integer:
|
case QPDFTokenizer::tt_integer:
|
||||||
@ -195,7 +198,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
// We just saw endobj without having read
|
// We just saw endobj without having read
|
||||||
// anything. Treat this as a null and do not move
|
// anything. Treat this as a null and do not move
|
||||||
// the input source's offset.
|
// the input source's offset.
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
input->seek(input->getLastOffset(), SEEK_SET);
|
input->seek(input->getLastOffset(), SEEK_SET);
|
||||||
empty = true;
|
empty = true;
|
||||||
} else {
|
} else {
|
||||||
@ -228,16 +231,16 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
warn("treating unknown token type as null while "
|
warn("treating unknown token type as null while "
|
||||||
"reading object");
|
"reading object");
|
||||||
bad = true;
|
bad = true;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!object.isInitialized()) &&
|
if (!object.isInitialized() && !is_null &&
|
||||||
(!((state == st_start) || (state == st_stop) ||
|
(!((state == st_start) || (state == st_stop) ||
|
||||||
(state == st_eof)))) {
|
(state == st_eof)))) {
|
||||||
throw std::logic_error("QPDFObjectHandle::parseInternal: "
|
throw std::logic_error("QPDFObjectHandle::parseInternal: "
|
||||||
"unexpected uninitialized object");
|
"unexpected uninitialized object");
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bad) {
|
if (bad) {
|
||||||
@ -254,7 +257,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
// intervening successful objects. Give up.
|
// intervening successful objects. Give up.
|
||||||
warn("too many errors; giving up on reading object");
|
warn("too many errors; giving up on reading object");
|
||||||
state = st_top;
|
state = st_top;
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -266,7 +269,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
// In content stream mode, leave object uninitialized to
|
// In content stream mode, leave object uninitialized to
|
||||||
// indicate EOF
|
// indicate EOF
|
||||||
if (!content_stream) {
|
if (!content_stream) {
|
||||||
object = QPDFObjectHandle::newNull();
|
is_null = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -279,7 +282,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
object.setParsedOffset(input->getLastOffset());
|
object.setParsedOffset(input->getLastOffset());
|
||||||
}
|
}
|
||||||
set_offset = true;
|
set_offset = true;
|
||||||
olist.push_back(object);
|
olist.push_back(is_null ? null_oh : object);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case st_top:
|
case st_top:
|
||||||
@ -387,11 +390,14 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
|||||||
if (state_stack.back() == st_top) {
|
if (state_stack.back() == st_top) {
|
||||||
done = true;
|
done = true;
|
||||||
} else {
|
} else {
|
||||||
stack.back().olist.push_back(object);
|
stack.back().olist.push_back(is_null ? null_oh : object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_null) {
|
||||||
|
object = QPDFObjectHandle::newNull();
|
||||||
|
}
|
||||||
if (!set_offset) {
|
if (!set_offset) {
|
||||||
setDescriptionFromInput(object, offset);
|
setDescriptionFromInput(object, offset);
|
||||||
object.setParsedOffset(offset);
|
object.setParsedOffset(offset);
|
||||||
|
Loading…
Reference in New Issue
Block a user