aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDFParser.cc
diff options
context:
space:
mode:
authorm-holger <m-holger@kubitscheck.org>2022-08-30 14:32:54 +0200
committerm-holger <m-holger@kubitscheck.org>2022-08-30 14:32:54 +0200
commit70d985f942cb554837163da8746e6abf7ef0ade3 (patch)
tree2412dd0076a612aea4b606e4214e039fc1ca6917 /libqpdf/QPDFParser.cc
parent97a7ad1d80c24fdda0db2cef0cb9280113f7793e (diff)
downloadqpdf-70d985f942cb554837163da8746e6abf7ef0ade3.tar.zst
Optimise QPDFParser::parse for #311 problem
Avoid creating new null objects that later will be discarded and made implicit. Part of #729
Diffstat (limited to 'libqpdf/QPDFParser.cc')
-rw-r--r--libqpdf/QPDFParser.cc34
1 files changed, 20 insertions, 14 deletions
diff --git a/libqpdf/QPDFParser.cc b/libqpdf/QPDFParser.cc
index 4b8090b3..afa1448f 100644
--- a/libqpdf/QPDFParser.cc
+++ b/libqpdf/QPDFParser.cc
@@ -51,9 +51,12 @@ QPDFParser::parse(bool& empty, bool content_stream)
int bad_count = 0;
int good_count = 0;
bool b_contents = false;
+ bool is_null = false;
+ auto null_oh = QPDFObjectHandle::newNull();
while (!done) {
bool bad = false;
+ is_null = false;
auto& frame = stack.back();
auto& olist = frame.olist;
parser_state_e state = state_stack.back();
@@ -83,7 +86,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
case QPDFTokenizer::tt_bad:
QTC::TC("qpdf", "QPDFParser bad token in parse");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
break;
case QPDFTokenizer::tt_brace_open:
@@ -91,7 +94,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
QTC::TC("qpdf", "QPDFParser bad brace");
warn("treating unexpected brace token as null");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
break;
case QPDFTokenizer::tt_array_close:
@@ -101,7 +104,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
QTC::TC("qpdf", "QPDFParser bad array close");
warn("treating unexpected array close token as null");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
}
break;
@@ -112,7 +115,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
QTC::TC("qpdf", "QPDFParser bad dictionary close");
warn("unexpected dictionary close token");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
}
break;
@@ -122,7 +125,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
QTC::TC("qpdf", "QPDFParser too deep");
warn("ignoring excessively deeply nested data structure");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
state = st_top;
} else {
state = st_start;
@@ -140,7 +143,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
break;
case QPDFTokenizer::tt_null:
- object = QPDFObjectHandle::newNull();
+ is_null = true;
break;
case QPDFTokenizer::tt_integer:
@@ -195,7 +198,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
// We just saw endobj without having read
// anything. Treat this as a null and do not move
// the input source's offset.
- object = QPDFObjectHandle::newNull();
+ is_null = true;
input->seek(input->getLastOffset(), SEEK_SET);
empty = true;
} else {
@@ -228,16 +231,16 @@ QPDFParser::parse(bool& empty, bool content_stream)
warn("treating unknown token type as null while "
"reading object");
bad = true;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
break;
}
- if ((!object.isInitialized()) &&
+ if (!object.isInitialized() && !is_null &&
(!((state == st_start) || (state == st_stop) ||
(state == st_eof)))) {
throw std::logic_error("QPDFObjectHandle::parseInternal: "
"unexpected uninitialized object");
- object = QPDFObjectHandle::newNull();
+ is_null = true;
}
if (bad) {
@@ -254,7 +257,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
// intervening successful objects. Give up.
warn("too many errors; giving up on reading object");
state = st_top;
- object = QPDFObjectHandle::newNull();
+ is_null = true;
}
switch (state) {
@@ -266,7 +269,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
// In content stream mode, leave object uninitialized to
// indicate EOF
if (!content_stream) {
- object = QPDFObjectHandle::newNull();
+ is_null = true;
}
break;
@@ -279,7 +282,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
object.setParsedOffset(input->getLastOffset());
}
set_offset = true;
- olist.push_back(object);
+ olist.push_back(is_null ? null_oh : object);
break;
case st_top:
@@ -387,11 +390,14 @@ QPDFParser::parse(bool& empty, bool content_stream)
if (state_stack.back() == st_top) {
done = true;
} 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) {
setDescriptionFromInput(object, offset);
object.setParsedOffset(offset);