Commit 91fb61eda5ae66736ae9e5975ae6f2e0867366e6

Authored by m-holger
1 parent cf945eea

Code tidy: replace if with case statement in QPDFTokenizer::presentCharacter

Showing 1 changed file with 112 additions and 92 deletions
libqpdf/QPDFTokenizer.cc
... ... @@ -198,12 +198,6 @@ QPDFTokenizer::resolveLiteral()
198 198 void
199 199 QPDFTokenizer::presentCharacter(char ch)
200 200 {
201   - if (this->state == st_token_ready) {
202   - throw std::logic_error(
203   - "INTERNAL ERROR: QPDF tokenizer presented character "
204   - "while token is waiting");
205   - }
206   -
207 201 char orig_ch = ch;
208 202  
209 203 // State machine is implemented such that some characters may be
... ... @@ -211,7 +205,14 @@ QPDFTokenizer::presentCharacter(char ch)
211 205 // the character that caused a state change in the new state.
212 206  
213 207 bool handled = true;
214   - if (this->state == st_top) {
  208 +
  209 + switch (this->state) {
  210 + case (st_token_ready):
  211 + throw std::logic_error(
  212 + "INTERNAL ERROR: QPDF tokenizer presented character "
  213 + "while token is waiting");
  214 +
  215 + case (st_top):
215 216 // Note: we specifically do not use ctype here. It is
216 217 // locale-dependent.
217 218 if (isSpace(ch)) {
... ... @@ -258,7 +259,9 @@ QPDFTokenizer::presentCharacter(char ch)
258 259 this->state = st_literal;
259 260 }
260 261 }
261   - } else if (this->state == st_in_space) {
  262 + break;
  263 +
  264 + case st_in_space:
262 265 // We only enter this state if include_ignorable is true.
263 266 if (!isSpace(ch)) {
264 267 this->type = tt_space;
... ... @@ -268,7 +271,9 @@ QPDFTokenizer::presentCharacter(char ch)
268 271 } else {
269 272 this->val += ch;
270 273 }
271   - } else if (this->state == st_in_comment) {
  274 + break;
  275 +
  276 + case st_in_comment:
272 277 if ((ch == '\r') || (ch == '\n')) {
273 278 if (this->include_ignorable) {
274 279 this->type = tt_comment;
... ... @@ -281,7 +286,9 @@ QPDFTokenizer::presentCharacter(char ch)
281 286 } else if (this->include_ignorable) {
282 287 this->val += ch;
283 288 }
284   - } else if (this->state == st_lt) {
  289 + break;
  290 +
  291 + case st_lt:
285 292 if (ch == '<') {
286 293 this->val += "<<";
287 294 this->type = tt_dict_open;
... ... @@ -290,7 +297,9 @@ QPDFTokenizer::presentCharacter(char ch)
290 297 handled = false;
291 298 this->state = st_in_hexstring;
292 299 }
293   - } else if (this->state == st_gt) {
  300 + break;
  301 +
  302 + case st_gt:
294 303 if (ch == '>') {
295 304 this->val += ">>";
296 305 this->type = tt_dict_close;
... ... @@ -304,91 +313,99 @@ QPDFTokenizer::presentCharacter(char ch)
304 313 this->char_to_unread = ch;
305 314 this->state = st_token_ready;
306 315 }
307   - } else if (this->state == st_in_string) {
308   - if (this->string_ignoring_newline && (ch != '\n')) {
309   - this->string_ignoring_newline = false;
310   - }
311   -
312   - size_t bs_num_count = strlen(this->bs_num_register);
313   - bool ch_is_octal = ((ch >= '0') && (ch <= '7'));
314   - if ((bs_num_count == 3) || ((bs_num_count > 0) && (!ch_is_octal))) {
315   - // We've accumulated \ddd. PDF Spec says to ignore
316   - // high-order overflow.
317   - this->val +=
318   - static_cast<char>(strtol(this->bs_num_register, nullptr, 8));
319   - memset(this->bs_num_register, '\0', sizeof(this->bs_num_register));
320   - bs_num_count = 0;
321   - }
322   -
323   - if (this->string_ignoring_newline && (ch == '\n')) {
324   - // ignore
325   - this->string_ignoring_newline = false;
326   - } else if (
327   - ch_is_octal && (this->last_char_was_bs || (bs_num_count > 0))) {
328   - this->bs_num_register[bs_num_count++] = ch;
329   - } else if (this->last_char_was_bs) {
330   - switch (ch) {
331   - case 'n':
332   - this->val += '\n';
333   - break;
334   -
335   - case 'r':
336   - this->val += '\r';
337   - break;
338   -
339   - case 't':
340   - this->val += '\t';
341   - break;
342   -
343   - case 'b':
344   - this->val += '\b';
345   - break;
346   -
347   - case 'f':
348   - this->val += '\f';
349   - break;
  316 + break;
350 317  
351   - case '\n':
352   - break;
  318 + case st_in_string:
  319 + {
  320 + if (this->string_ignoring_newline && (ch != '\n')) {
  321 + this->string_ignoring_newline = false;
  322 + }
353 323  
354   - case '\r':
355   - this->string_ignoring_newline = true;
356   - break;
  324 + size_t bs_num_count = strlen(this->bs_num_register);
  325 + bool ch_is_octal = ((ch >= '0') && (ch <= '7'));
  326 + if ((bs_num_count == 3) || ((bs_num_count > 0) && (!ch_is_octal))) {
  327 + // We've accumulated \ddd. PDF Spec says to ignore
  328 + // high-order overflow.
  329 + this->val += static_cast<char>(
  330 + strtol(this->bs_num_register, nullptr, 8));
  331 + memset(
  332 + this->bs_num_register, '\0', sizeof(this->bs_num_register));
  333 + bs_num_count = 0;
  334 + }
357 335  
358   - default:
359   - // PDF spec says backslash is ignored before anything else
  336 + if (this->string_ignoring_newline && (ch == '\n')) {
  337 + // ignore
  338 + this->string_ignoring_newline = false;
  339 + } else if (
  340 + ch_is_octal && (this->last_char_was_bs || (bs_num_count > 0))) {
  341 + this->bs_num_register[bs_num_count++] = ch;
  342 + } else if (this->last_char_was_bs) {
  343 + switch (ch) {
  344 + case 'n':
  345 + this->val += '\n';
  346 + break;
  347 +
  348 + case 'r':
  349 + this->val += '\r';
  350 + break;
  351 +
  352 + case 't':
  353 + this->val += '\t';
  354 + break;
  355 +
  356 + case 'b':
  357 + this->val += '\b';
  358 + break;
  359 +
  360 + case 'f':
  361 + this->val += '\f';
  362 + break;
  363 +
  364 + case '\n':
  365 + break;
  366 +
  367 + case '\r':
  368 + this->string_ignoring_newline = true;
  369 + break;
  370 +
  371 + default:
  372 + // PDF spec says backslash is ignored before anything else
  373 + this->val += ch;
  374 + break;
  375 + }
  376 + } else if (ch == '\\') {
  377 + // last_char_was_bs is set/cleared below as appropriate
  378 + if (bs_num_count) {
  379 + throw std::logic_error(
  380 + "INTERNAL ERROR: QPDFTokenizer: bs_num_count != 0 "
  381 + "when ch == '\\'");
  382 + }
  383 + } else if (ch == '(') {
360 384 this->val += ch;
361   - break;
362   - }
363   - } else if (ch == '\\') {
364   - // last_char_was_bs is set/cleared below as appropriate
365   - if (bs_num_count) {
366   - throw std::logic_error(
367   - "INTERNAL ERROR: QPDFTokenizer: bs_num_count != 0 "
368   - "when ch == '\\'");
369   - }
370   - } else if (ch == '(') {
371   - this->val += ch;
372   - ++this->string_depth;
373   - } else if ((ch == ')') && (--this->string_depth == 0)) {
374   - this->type = tt_string;
375   - this->state = st_token_ready;
376   - } else if (ch == '\r') {
377   - // CR by itself is converted to LF
378   - this->val += '\n';
379   - } else if (ch == '\n') {
380   - // CR LF is converted to LF
381   - if (!this->last_char_was_cr) {
  385 + ++this->string_depth;
  386 + } else if ((ch == ')') && (--this->string_depth == 0)) {
  387 + this->type = tt_string;
  388 + this->state = st_token_ready;
  389 + } else if (ch == '\r') {
  390 + // CR by itself is converted to LF
  391 + this->val += '\n';
  392 + } else if (ch == '\n') {
  393 + // CR LF is converted to LF
  394 + if (!this->last_char_was_cr) {
  395 + this->val += ch;
  396 + }
  397 + } else {
382 398 this->val += ch;
383 399 }
384   - } else {
385   - this->val += ch;
  400 +
  401 + this->last_char_was_cr =
  402 + ((!this->string_ignoring_newline) && (ch == '\r'));
  403 + this->last_char_was_bs =
  404 + ((!this->last_char_was_bs) && (ch == '\\'));
386 405 }
  406 + break;
387 407  
388   - this->last_char_was_cr =
389   - ((!this->string_ignoring_newline) && (ch == '\r'));
390   - this->last_char_was_bs = ((!this->last_char_was_bs) && (ch == '\\'));
391   - } else if (this->state == st_literal) {
  408 + case st_literal:
392 409 if (isDelimiter(ch)) {
393 410 // A C-locale whitespace character or delimiter terminates
394 411 // token. It is important to unread the whitespace
... ... @@ -405,16 +422,19 @@ QPDFTokenizer::presentCharacter(char ch)
405 422 } else {
406 423 this->val += ch;
407 424 }
408   - } else if (this->state == st_inline_image) {
  425 + break;
  426 +
  427 + case st_inline_image:
409 428 this->val += ch;
410   - size_t len = this->val.length();
411   - if (len == this->inline_image_bytes) {
  429 + if (this->val.length() == this->inline_image_bytes) {
412 430 QTC::TC("qpdf", "QPDFTokenizer found EI by byte count");
413 431 this->type = tt_inline_image;
414 432 this->inline_image_bytes = 0;
415 433 this->state = st_token_ready;
416 434 }
417   - } else {
  435 + break;
  436 +
  437 + default:
418 438 handled = false;
419 439 }
420 440  
... ...