Commit 70d985f942cb554837163da8746e6abf7ef0ade3

Authored by m-holger
1 parent 97a7ad1d

Optimise QPDFParser::parse for #311 problem

Avoid creating new null objects that later will be discarded and made
implicit.

Part of #729
Showing 1 changed file with 20 additions and 14 deletions
libqpdf/QPDFParser.cc
... ... @@ -51,9 +51,12 @@ QPDFParser::parse(bool& empty, bool content_stream)
51 51 int bad_count = 0;
52 52 int good_count = 0;
53 53 bool b_contents = false;
  54 + bool is_null = false;
  55 + auto null_oh = QPDFObjectHandle::newNull();
54 56  
55 57 while (!done) {
56 58 bool bad = false;
  59 + is_null = false;
57 60 auto& frame = stack.back();
58 61 auto& olist = frame.olist;
59 62 parser_state_e state = state_stack.back();
... ... @@ -83,7 +86,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
83 86 case QPDFTokenizer::tt_bad:
84 87 QTC::TC("qpdf", "QPDFParser bad token in parse");
85 88 bad = true;
86   - object = QPDFObjectHandle::newNull();
  89 + is_null = true;
87 90 break;
88 91  
89 92 case QPDFTokenizer::tt_brace_open:
... ... @@ -91,7 +94,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
91 94 QTC::TC("qpdf", "QPDFParser bad brace");
92 95 warn("treating unexpected brace token as null");
93 96 bad = true;
94   - object = QPDFObjectHandle::newNull();
  97 + is_null = true;
95 98 break;
96 99  
97 100 case QPDFTokenizer::tt_array_close:
... ... @@ -101,7 +104,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
101 104 QTC::TC("qpdf", "QPDFParser bad array close");
102 105 warn("treating unexpected array close token as null");
103 106 bad = true;
104   - object = QPDFObjectHandle::newNull();
  107 + is_null = true;
105 108 }
106 109 break;
107 110  
... ... @@ -112,7 +115,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
112 115 QTC::TC("qpdf", "QPDFParser bad dictionary close");
113 116 warn("unexpected dictionary close token");
114 117 bad = true;
115   - object = QPDFObjectHandle::newNull();
  118 + is_null = true;
116 119 }
117 120 break;
118 121  
... ... @@ -122,7 +125,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
122 125 QTC::TC("qpdf", "QPDFParser too deep");
123 126 warn("ignoring excessively deeply nested data structure");
124 127 bad = true;
125   - object = QPDFObjectHandle::newNull();
  128 + is_null = true;
126 129 state = st_top;
127 130 } else {
128 131 state = st_start;
... ... @@ -140,7 +143,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
140 143 break;
141 144  
142 145 case QPDFTokenizer::tt_null:
143   - object = QPDFObjectHandle::newNull();
  146 + is_null = true;
144 147 break;
145 148  
146 149 case QPDFTokenizer::tt_integer:
... ... @@ -195,7 +198,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
195 198 // We just saw endobj without having read
196 199 // anything. Treat this as a null and do not move
197 200 // the input source's offset.
198   - object = QPDFObjectHandle::newNull();
  201 + is_null = true;
199 202 input->seek(input->getLastOffset(), SEEK_SET);
200 203 empty = true;
201 204 } else {
... ... @@ -228,16 +231,16 @@ QPDFParser::parse(bool& empty, bool content_stream)
228 231 warn("treating unknown token type as null while "
229 232 "reading object");
230 233 bad = true;
231   - object = QPDFObjectHandle::newNull();
  234 + is_null = true;
232 235 break;
233 236 }
234 237  
235   - if ((!object.isInitialized()) &&
  238 + if (!object.isInitialized() && !is_null &&
236 239 (!((state == st_start) || (state == st_stop) ||
237 240 (state == st_eof)))) {
238 241 throw std::logic_error("QPDFObjectHandle::parseInternal: "
239 242 "unexpected uninitialized object");
240   - object = QPDFObjectHandle::newNull();
  243 + is_null = true;
241 244 }
242 245  
243 246 if (bad) {
... ... @@ -254,7 +257,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
254 257 // intervening successful objects. Give up.
255 258 warn("too many errors; giving up on reading object");
256 259 state = st_top;
257   - object = QPDFObjectHandle::newNull();
  260 + is_null = true;
258 261 }
259 262  
260 263 switch (state) {
... ... @@ -266,7 +269,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
266 269 // In content stream mode, leave object uninitialized to
267 270 // indicate EOF
268 271 if (!content_stream) {
269   - object = QPDFObjectHandle::newNull();
  272 + is_null = true;
270 273 }
271 274 break;
272 275  
... ... @@ -279,7 +282,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
279 282 object.setParsedOffset(input->getLastOffset());
280 283 }
281 284 set_offset = true;
282   - olist.push_back(object);
  285 + olist.push_back(is_null ? null_oh : object);
283 286 break;
284 287  
285 288 case st_top:
... ... @@ -387,11 +390,14 @@ QPDFParser::parse(bool& empty, bool content_stream)
387 390 if (state_stack.back() == st_top) {
388 391 done = true;
389 392 } else {
390   - stack.back().olist.push_back(object);
  393 + stack.back().olist.push_back(is_null ? null_oh : object);
391 394 }
392 395 }
393 396 }
394 397  
  398 + if (is_null) {
  399 + object = QPDFObjectHandle::newNull();
  400 + }
395 401 if (!set_offset) {
396 402 setDescriptionFromInput(object, offset);
397 403 object.setParsedOffset(offset);
... ...