Commit fc27221ab23431878c0a013f1204f2bda84bd389

Authored by m-holger
1 parent 4c23d2c0

Refactor `JSONReactor::dictionaryItem`: remove redundant `QTC::TC` calls, enhance assert usage.

libqpdf/QPDF_json.cc
... ... @@ -460,104 +460,111 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
460 460 next_state = st_ignore;
461 461 auto state = stack.back().state;
462 462 if (state == st_ignore) {
463   - QTC::TC("qpdf", "QPDF_json ignoring in st_ignore");
464   - // ignore
465   - } else if (state == st_top) {
  463 + return true; // ignore
  464 + }
  465 + if (state == st_top) {
466 466 if (key == "qpdf") {
467   - this->saw_qpdf = true;
  467 + saw_qpdf = true;
468 468 if (!value.isArray()) {
469 469 error(value.getStart(), "\"qpdf\" must be an array");
470 470 } else {
471 471 next_state = st_qpdf;
472 472 }
473   - } else {
474   - // Ignore all other fields.
475   - QTC::TC("qpdf", "QPDF_json ignoring unknown top-level key");
  473 + return true;
476 474 }
477   - } else if (state == st_qpdf_meta) {
  475 + return true; // Ignore all other fields.
  476 + }
  477 +
  478 + if (state == st_qpdf_meta) {
478 479 if (key == "pdfversion") {
479   - this->saw_pdf_version = true;
  480 + saw_pdf_version = true;
480 481 std::string v;
481   - bool okay = false;
482 482 if (value.getString(v)) {
483 483 std::string version;
484 484 char const* p = v.c_str();
485 485 if (QPDF::validatePDFVersion(p, version) && (*p == '\0')) {
486   - this->pdf.m->pdf_version = version;
487   - okay = true;
  486 + pdf.m->pdf_version = version;
  487 + return true;
488 488 }
489 489 }
490   - if (!okay) {
491   - error(value.getStart(), "invalid PDF version (must be \"x.y\")");
492   - }
493   - } else if (key == "jsonversion") {
494   - this->saw_json_version = true;
  490 + error(value.getStart(), "invalid PDF version (must be \"x.y\")");
  491 + return true;
  492 + }
  493 + if (key == "jsonversion") {
  494 + saw_json_version = true;
495 495 std::string v;
496   - bool okay = false;
497 496 if (value.getNumber(v)) {
498 497 std::string version;
499 498 if (QUtil::string_to_int(v.c_str()) == 2) {
500   - okay = true;
  499 + return true;
501 500 }
502 501 }
503   - if (!okay) {
504   - error(value.getStart(), "invalid JSON version (must be numeric value 2)");
505   - }
506   - } else if (key == "pushedinheritedpageresources") {
  502 + error(value.getStart(), "invalid JSON version (must be numeric value 2)");
  503 + return true;
  504 + }
  505 + if (key == "pushedinheritedpageresources") {
507 506 bool v;
508 507 if (value.getBool(v)) {
509   - if (!this->must_be_complete && v) {
510   - this->pdf.pushInheritedAttributesToPage();
  508 + if (!must_be_complete && v) {
  509 + pdf.pushInheritedAttributesToPage();
511 510 }
512   - } else {
513   - error(value.getStart(), "pushedinheritedpageresources must be a boolean");
  511 + return true;
514 512 }
515   - } else if (key == "calledgetallpages") {
  513 + error(value.getStart(), "pushedinheritedpageresources must be a boolean");
  514 + return true;
  515 + }
  516 + if (key == "calledgetallpages") {
516 517 bool v;
517 518 if (value.getBool(v)) {
518   - if (!this->must_be_complete && v) {
  519 + if (!must_be_complete && v) {
519 520 (void)pdf.doc().pages().all();
520 521 }
521   - } else {
522   - error(value.getStart(), "calledgetallpages must be a boolean");
  522 + return true;
523 523 }
524   - } else {
525   - // ignore unknown keys for forward compatibility and to skip keys we don't care about
526   - // like "maxobjectid".
527   - QTC::TC("qpdf", "QPDF_json ignore second-level key");
  524 + error(value.getStart(), "calledgetallpages must be a boolean");
  525 + return true;
528 526 }
529   - } else if (state == st_objects) {
530   - int obj = 0;
531   - int gen = 0;
  527 + // ignore unknown keys for forward compatibility and to skip keys we don't care about
  528 + // like "maxobjectid".
  529 + return true;
  530 + }
  531 +
  532 + if (state == st_objects) {
532 533 if (key == "trailer") {
533   - this->saw_trailer = true;
534   - this->cur_object = "trailer";
  534 + saw_trailer = true;
  535 + cur_object = "trailer";
535 536 setNextStateIfDictionary(key, value, st_trailer);
536   - } else if (is_obj_key(key, obj, gen)) {
537   - this->cur_object = key;
  537 + return true;
  538 + }
  539 +
  540 + int obj = 0;
  541 + int gen = 0;
  542 + if (is_obj_key(key, obj, gen)) {
  543 + cur_object = key;
538 544 if (setNextStateIfDictionary(key, value, st_object_top)) {
539 545 next_obj = objects.getObjectForJSON(obj, gen);
540 546 }
541   - } else {
542   - error(value.getStart(), "object key should be \"trailer\" or \"obj:n n R\"");
543   - }
544   - } else if (state == st_object_top) {
545   - if (stack.empty()) {
546   - throw std::logic_error("stack empty in st_object_top");
  547 + return true;
547 548 }
  549 + error(value.getStart(), "object key should be \"trailer\" or \"obj:n n R\"");
  550 + return true;
  551 + }
  552 +
  553 + if (state == st_object_top) {
  554 + util::assertion(!stack.empty(), "QPDF_json: stack empty in st_object_top");
548 555 auto& tos = stack.back();
549   - if (!tos.object) {
550   - throw std::logic_error("current object uninitialized in st_object_top");
551   - }
  556 + util::assertion(!!tos.object, "current object uninitialized in st_object_top");
552 557 if (key == "value") {
553 558 // Don't use setNextStateIfDictionary since this can have any type.
554   - this->saw_value = true;
  559 + saw_value = true;
555 560 replaceObject(makeObject(value), value);
556 561 next_state = st_object;
557   - } else if (key == "stream") {
558   - this->saw_stream = true;
  562 + return true;
  563 + }
  564 + if (key == "stream") {
  565 + saw_stream = true;
559 566 if (setNextStateIfDictionary(key, value, st_stream)) {
560   - this->this_stream_needs_data = false;
  567 + this_stream_needs_data = false;
561 568 if (tos.object.isStream()) {
562 569 QTC::TC("qpdf", "QPDF_json updating existing stream");
563 570 } else {
... ... @@ -568,95 +575,87 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
568 575 value);
569 576 }
570 577 next_obj = tos.object;
571   - } else {
572   - // Error message already given above
573   - QTC::TC("qpdf", "QPDF_json stream not a dictionary");
  578 + return true;
574 579 }
575   - } else {
576   - // Ignore unknown keys for forward compatibility
577   - QTC::TC("qpdf", "QPDF_json ignore unknown key in object_top");
  580 + return true; // Error message already given above
578 581 }
579   - } else if (state == st_trailer) {
  582 + return true; // Ignore unknown keys for forward compatibility
  583 + }
  584 +
  585 + if (state == st_trailer) {
580 586 if (key == "value") {
581   - this->saw_value = true;
  587 + saw_value = true;
582 588 // The trailer must be a dictionary, so we can use setNextStateIfDictionary.
583 589 if (setNextStateIfDictionary("trailer.value", value, st_object)) {
584   - this->pdf.m->trailer = makeObject(value);
585   - setObjectDescription(this->pdf.m->trailer, value);
  590 + pdf.m->trailer = makeObject(value);
  591 + setObjectDescription(pdf.m->trailer, value);
586 592 }
587   - } else if (key == "stream") {
  593 + return true;
  594 + }
  595 + if (key == "stream") {
588 596 // Don't need to set saw_stream here since there's already an error.
589 597 error(value.getStart(), "the trailer may not be a stream");
590   - } else {
591   - // Ignore unknown keys for forward compatibility
592   - QTC::TC("qpdf", "QPDF_json ignore unknown key in trailer");
593   - }
594   - } else if (state == st_stream) {
595   - if (stack.empty()) {
596   - throw std::logic_error("stack empty in st_stream");
  598 + return true;
597 599 }
  600 + return true; // Ignore unknown keys for forward compatibility
  601 + }
  602 +
  603 + if (state == st_stream) {
  604 + util::assertion(!stack.empty(), "stack empty in st_stream");
598 605 auto& tos = stack.back();
599   - if (!tos.object.isStream()) {
600   - throw std::logic_error("current object is not stream in st_stream");
601   - }
  606 + util::assertion(tos.object.isStream(), "current object is not stream in st_stream");
602 607 if (key == "dict") {
603   - this->saw_dict = true;
  608 + saw_dict = true;
604 609 if (setNextStateIfDictionary("stream.dict", value, st_object)) {
605 610 tos.object.replaceDict(makeObject(value));
606   - } else {
607   - // An error had already been given by setNextStateIfDictionary
608   - QTC::TC("qpdf", "QPDF_json stream dict not dict");
  611 + return true;
609 612 }
610   - } else if (key == "data") {
611   - this->saw_data = true;
  613 + return true; // An error had already been given by setNextStateIfDictionary
  614 + }
  615 + if (key == "data") {
  616 + saw_data = true;
612 617 std::string v;
613 618 if (!value.getString(v)) {
614 619 error(value.getStart(), "\"stream.data\" must be a string");
615 620 tos.object.replaceStreamData("", {}, {});
616   - } else {
617   - // The range includes the quotes.
618   - auto start = value.getStart() + 1;
619   - auto end = value.getEnd() - 1;
620   - if (end < start) {
621   - throw std::logic_error("QPDF_json: JSON string length < 0");
622   - }
623   - tos.object.replaceStreamData(provide_data(is, start, end), {}, {});
  621 + return true;
624 622 }
625   - } else if (key == "datafile") {
626   - this->saw_datafile = true;
  623 + // The range includes the quotes.
  624 + auto start = value.getStart() + 1;
  625 + auto end = value.getEnd() - 1;
  626 + util::assertion(end >= start, "QPDF_json: JSON string length < 0");
  627 + tos.object.replaceStreamData(provide_data(is, start, end), {}, {});
  628 + return true;
  629 + }
  630 + if (key == "datafile") {
  631 + saw_datafile = true;
627 632 std::string filename;
628 633 if (!value.getString(filename)) {
629   - QTC::TC("qpdf", "QPDF_json stream datafile not string");
630 634 error(
631 635 value.getStart(),
632 636 "\"stream.datafile\" must be a string containing a file name");
633 637 tos.object.replaceStreamData("", {}, {});
634   - } else {
635   - tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
  638 + return true;
636 639 }
637   - } else {
638   - // Ignore unknown keys for forward compatibility.
639   - QTC::TC("qpdf", "QPDF_json ignore unknown key in stream");
640   - }
641   - } else if (state == st_object) {
642   - if (stack.empty()) {
643   - throw std::logic_error("stack empty in st_object");
  640 + tos.object.replaceStreamData(QUtil::file_provider(filename), {}, {});
  641 + return true;
644 642 }
645   - auto& tos = stack.back();
646   - auto dict = tos.object;
647   - if (dict.isStream()) {
648   - dict = dict.getDict();
649   - }
650   - if (!dict.isDictionary()) {
651   - throw std::logic_error(
652   - "current object is not stream or dictionary in st_object dictionary item");
653   - }
654   - dict.replaceKey(
655   - is_pdf_name(key) ? QPDFObjectHandle::parse(key.substr(2)).getName() : key,
656   - makeObject(value));
657   - } else {
658   - throw std::logic_error("QPDF_json: unknown state " + std::to_string(state));
  643 + return true; // Ignore unknown keys for forward compatibility.
659 644 }
  645 +
  646 + util::assertion(state == st_object, "QPDF_json: unknown state " + std::to_string(state));
  647 + util::assertion(!stack.empty(), "stack empty in st_object");
  648 + auto& tos = stack.back();
  649 + auto dict = tos.object;
  650 + if (dict.isStream()) {
  651 + dict = dict.getDict();
  652 + }
  653 + util::assertion(
  654 + dict.isDictionary(),
  655 + "current object is not stream or dictionary in st_object dictionary item");
  656 + dict.replaceKey(
  657 + is_pdf_name(key) ? QPDFObjectHandle::parse(key.substr(2)).getName() : key,
  658 + makeObject(value));
660 659 return true;
661 660 }
662 661  
... ...
qpdf/qpdf.testcov
... ... @@ -423,8 +423,6 @@ QPDF_json top-level scalar 0
423 423 QPDF_json top-level array 0
424 424 QPDF_json missing trailer 0
425 425 QPDF_json missing objects 0
426   -QPDF_json ignoring in st_ignore 0
427   -QPDF_json stream dict not dict 0
428 426 QPDF_json unrecognized string value 0
429 427 QPDF_json data datafile both or neither 0
430 428 QPDF_json stream no dict 0
... ... @@ -433,11 +431,6 @@ QPDF_json value stream both or neither 0
433 431 QPDFJob need json-stream-prefix for stdout 0
434 432 QPDFJob write json to stdout 0
435 433 QPDFJob write json to file 0
436   -QPDF_json ignoring unknown top-level key 0
437   -QPDF_json ignore second-level key 0
438   -QPDF_json ignore unknown key in object_top 0
439   -QPDF_json ignore unknown key in trailer 0
440   -QPDF_json ignore unknown key in stream 0
441 434 QPDF_json data and datafile 0
442 435 QPDF_json no stream data in update mode 0
443 436 QPDF_json updating existing stream 0
... ... @@ -448,5 +441,3 @@ QPDF skipping cache for known unchecked object 0
448 441 QPDF recover xref stream 0
449 442 QPDFJob json over/under no file 0
450 443 QPDF_Array copy 1
451   -QPDF_json stream datafile not string 0
452   -QPDF_json stream not a dictionary 0
... ...