Commit 114bffa0894d8bac7151201404cb6d8d62bd9b4a

Authored by m-holger
1 parent 2a2eebca

Add private methods QPDFObjectHandle::asArray etc

Centralise casting of QPDFObjects and reduce repeated dereferencing.
include/qpdf/QPDFObjectHandle.hh
... ... @@ -43,8 +43,18 @@
43 43  
44 44 class Pipeline;
45 45 class QPDF;
46   -class QPDF_Dictionary;
47 46 class QPDF_Array;
  47 +class QPDF_Bool;
  48 +class QPDF_Dictionary;
  49 +class QPDF_InlineImage;
  50 +class QPDF_Integer;
  51 +class QPDF_Name;
  52 +class QPDF_Null;
  53 +class QPDF_Operator;
  54 +class QPDF_Real;
  55 +class QPDF_Reserved;
  56 +class QPDF_Stream;
  57 +class QPDF_String;
48 58 class QPDFTokenizer;
49 59 class QPDFExc;
50 60 class Pl_QPDFTokenizer;
... ... @@ -1480,6 +1490,16 @@ class QPDFObjectHandle
1480 1490 };
1481 1491 return o.obj;
1482 1492 }
  1493 + static QPDF_Array*
  1494 + asArray(QPDFObjectHandle& oh)
  1495 + {
  1496 + return oh.asArray();
  1497 + }
  1498 + static QPDF_Stream*
  1499 + asStream(QPDFObjectHandle& oh)
  1500 + {
  1501 + return oh.asStream();
  1502 + }
1483 1503 };
1484 1504 friend class ObjAccessor;
1485 1505  
... ... @@ -1581,6 +1601,20 @@ class QPDFObjectHandle
1581 1601 qpdf_offset_t offset,
1582 1602 size_t length);
1583 1603  
  1604 + QPDF_Array* asArray();
  1605 + QPDF_Bool* asBool();
  1606 + QPDF_Dictionary* asDictionary();
  1607 + QPDF_InlineImage* asInlineImage();
  1608 + QPDF_Integer* asInteger();
  1609 + QPDF_Name* asName();
  1610 + QPDF_Null* asNull();
  1611 + QPDF_Operator* asOperator();
  1612 + QPDF_Real* asReal();
  1613 + QPDF_Reserved* asReserved();
  1614 + QPDF_Stream* asStream();
  1615 + QPDF_Stream* asStreamWithAssert();
  1616 + QPDF_String* asString();
  1617 +
1584 1618 void typeWarning(char const* expected_type, std::string const& warning);
1585 1619 void objectWarning(std::string const& warning);
1586 1620 void assertType(char const* type_name, bool istype);
... ... @@ -1881,7 +1915,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset)
1881 1915 {
1882 1916 // This is called during parsing on newly created direct objects,
1883 1917 // so we can't call dereference() here.
1884   - if (this->obj.get()) {
  1918 + if (initialized) {
1885 1919 this->obj->setParsedOffset(offset);
1886 1920 }
1887 1921 }
... ...
libqpdf/QPDF.cc
... ... @@ -1420,8 +1420,7 @@ QPDF::fixDanglingReferences(bool force)
1420 1420 to_check.push_back(iter.second);
1421 1421 }
1422 1422 } else if (obj.isArray()) {
1423   - QPDF_Array* arr = dynamic_cast<QPDF_Array*>(
1424   - QPDFObjectHandle::ObjAccessor::getObject(obj).get());
  1423 + auto arr = QPDFObjectHandle::ObjAccessor::asArray(obj);
1425 1424 arr->addExplicitElementsToList(to_check);
1426 1425 }
1427 1426 for (auto sub: to_check) {
... ... @@ -2468,12 +2467,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2468 2467 QPDFObjGen local_og(result.getObjGen());
2469 2468 // Copy information from the foreign stream so we can pipe its
2470 2469 // data later without keeping the original QPDF object around.
  2470 +
2471 2471 QPDF* foreign_stream_qpdf = foreign.getOwningQPDF(
2472 2472 false, "unable to retrieve owning qpdf from foreign stream");
2473 2473  
2474   - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(
2475   - QPDFObjectHandle::ObjAccessor::getObject(foreign).get());
2476   - if (!stream) {
  2474 + auto stream = QPDFObjectHandle::ObjAccessor::asStream(foreign);
  2475 + if (stream == nullptr) {
2477 2476 throw std::logic_error("unable to retrieve underlying"
2478 2477 " stream object from foreign stream");
2479 2478 }
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -277,24 +277,91 @@ QPDFObjectHandle::getTypeName()
277 277 return dereference() ? this->obj->getTypeName() : "uninitialized";
278 278 }
279 279  
280   -namespace
  280 +QPDF_Array*
  281 +QPDFObjectHandle::asArray()
281 282 {
282   - template <class T>
283   - class QPDFObjectTypeAccessor
284   - {
285   - public:
286   - static bool
287   - check(std::shared_ptr<QPDFObject> const& o)
288   - {
289   - return (o && dynamic_cast<T const*>(o.get()));
290   - }
291   - };
292   -} // namespace
  283 + return isArray() ? dynamic_cast<QPDF_Array*>(obj.get()) : nullptr;
  284 +}
  285 +
  286 +QPDF_Bool*
  287 +QPDFObjectHandle::asBool()
  288 +{
  289 + return isBool() ? dynamic_cast<QPDF_Bool*>(obj.get()) : nullptr;
  290 +}
  291 +
  292 +QPDF_Dictionary*
  293 +QPDFObjectHandle::asDictionary()
  294 +{
  295 + return isDictionary() ? dynamic_cast<QPDF_Dictionary*>(obj.get()) : nullptr;
  296 +}
  297 +
  298 +QPDF_InlineImage*
  299 +QPDFObjectHandle::asInlineImage()
  300 +{
  301 + return isInlineImage() ? dynamic_cast<QPDF_InlineImage*>(obj.get())
  302 + : nullptr;
  303 +}
  304 +
  305 +QPDF_Integer*
  306 +QPDFObjectHandle::asInteger()
  307 +{
  308 + return isInteger() ? dynamic_cast<QPDF_Integer*>(obj.get()) : nullptr;
  309 +}
  310 +
  311 +QPDF_Name*
  312 +QPDFObjectHandle::asName()
  313 +{
  314 + return isName() ? dynamic_cast<QPDF_Name*>(obj.get()) : nullptr;
  315 +}
  316 +
  317 +QPDF_Null*
  318 +QPDFObjectHandle::asNull()
  319 +{
  320 + return isNull() ? dynamic_cast<QPDF_Null*>(obj.get()) : nullptr;
  321 +}
  322 +
  323 +QPDF_Operator*
  324 +QPDFObjectHandle::asOperator()
  325 +{
  326 + return isOperator() ? dynamic_cast<QPDF_Operator*>(obj.get()) : nullptr;
  327 +}
  328 +
  329 +QPDF_Real*
  330 +QPDFObjectHandle::asReal()
  331 +{
  332 + return isReal() ? dynamic_cast<QPDF_Real*>(obj.get()) : nullptr;
  333 +}
  334 +
  335 +QPDF_Reserved*
  336 +QPDFObjectHandle::asReserved()
  337 +{
  338 + return isReserved() ? dynamic_cast<QPDF_Reserved*>(obj.get()) : nullptr;
  339 +}
  340 +
  341 +QPDF_Stream*
  342 +QPDFObjectHandle::asStream()
  343 +{
  344 + return isStream() ? dynamic_cast<QPDF_Stream*>(obj.get()) : nullptr;
  345 +}
  346 +
  347 +QPDF_Stream*
  348 +QPDFObjectHandle::asStreamWithAssert()
  349 +{
  350 + auto stream = asStream();
  351 + assertType("stream", stream);
  352 + return stream;
  353 +}
  354 +
  355 +QPDF_String*
  356 +QPDFObjectHandle::asString()
  357 +{
  358 + return isString() ? dynamic_cast<QPDF_String*>(obj.get()) : nullptr;
  359 +}
293 360  
294 361 bool
295 362 QPDFObjectHandle::isBool()
296 363 {
297   - return dereference() && QPDFObjectTypeAccessor<QPDF_Bool>::check(obj);
  364 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_boolean);
298 365 }
299 366  
300 367 bool
... ... @@ -303,26 +370,26 @@ QPDFObjectHandle::isDirectNull() const
303 370 // Don't call dereference() -- this is a const method, and we know
304 371 // objid == 0, so there's nothing to resolve.
305 372 return (
306   - this->initialized && (getObjectID() == 0) &&
307   - QPDFObjectTypeAccessor<QPDF_Null>::check(obj));
  373 + initialized && (getObjectID() == 0) &&
  374 + (obj->getTypeCode() == QPDFObject::ot_null));
308 375 }
309 376  
310 377 bool
311 378 QPDFObjectHandle::isNull()
312 379 {
313   - return dereference() && QPDFObjectTypeAccessor<QPDF_Null>::check(obj);
  380 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_null);
314 381 }
315 382  
316 383 bool
317 384 QPDFObjectHandle::isInteger()
318 385 {
319   - return dereference() && QPDFObjectTypeAccessor<QPDF_Integer>::check(obj);
  386 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_integer);
320 387 }
321 388  
322 389 bool
323 390 QPDFObjectHandle::isReal()
324 391 {
325   - return dereference() && QPDFObjectTypeAccessor<QPDF_Real>::check(obj);
  392 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_real);
326 393 }
327 394  
328 395 bool
... ... @@ -359,51 +426,49 @@ QPDFObjectHandle::getValueAsNumber(double&amp; value)
359 426 bool
360 427 QPDFObjectHandle::isName()
361 428 {
362   - return dereference() && QPDFObjectTypeAccessor<QPDF_Name>::check(obj);
  429 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_name);
363 430 }
364 431  
365 432 bool
366 433 QPDFObjectHandle::isString()
367 434 {
368   - return dereference() && QPDFObjectTypeAccessor<QPDF_String>::check(obj);
  435 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_string);
369 436 }
370 437  
371 438 bool
372 439 QPDFObjectHandle::isOperator()
373 440 {
374   - return dereference() && QPDFObjectTypeAccessor<QPDF_Operator>::check(obj);
  441 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_operator);
375 442 }
376 443  
377 444 bool
378 445 QPDFObjectHandle::isInlineImage()
379 446 {
380   - return dereference() &&
381   - QPDFObjectTypeAccessor<QPDF_InlineImage>::check(obj);
  447 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_inlineimage);
382 448 }
383 449  
384 450 bool
385 451 QPDFObjectHandle::isArray()
386 452 {
387   - return dereference() && QPDFObjectTypeAccessor<QPDF_Array>::check(obj);
  453 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_array);
388 454 }
389 455  
390 456 bool
391 457 QPDFObjectHandle::isDictionary()
392 458 {
393   - return dereference() && QPDFObjectTypeAccessor<QPDF_Dictionary>::check(obj);
  459 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_dictionary);
394 460 }
395 461  
396 462 bool
397 463 QPDFObjectHandle::isStream()
398 464 {
399   - return dereference() && QPDFObjectTypeAccessor<QPDF_Stream>::check(obj);
  465 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_stream);
400 466 }
401 467  
402 468 bool
403 469 QPDFObjectHandle::isReserved()
404 470 {
405   - // dereference will clear reserved if this has been replaced
406   - return dereference() && QPDFObjectTypeAccessor<QPDF_Reserved>::check(obj);
  471 + return dereference() && (obj->getTypeCode() == QPDFObject::ot_reserved);
407 472 }
408 473  
409 474 bool
... ... @@ -441,8 +506,9 @@ QPDFObjectHandle::isStreamOfType(
441 506 bool
442 507 QPDFObjectHandle::getBoolValue()
443 508 {
444   - if (isBool()) {
445   - return dynamic_cast<QPDF_Bool*>(obj.get())->getVal();
  509 + auto boolean = asBool();
  510 + if (boolean) {
  511 + return boolean->getVal();
446 512 } else {
447 513 typeWarning("boolean", "returning false");
448 514 QTC::TC("qpdf", "QPDFObjectHandle boolean returning false");
... ... @@ -453,10 +519,11 @@ QPDFObjectHandle::getBoolValue()
453 519 bool
454 520 QPDFObjectHandle::getValueAsBool(bool& value)
455 521 {
456   - if (!isBool()) {
  522 + auto boolean = asBool();
  523 + if (boolean == nullptr) {
457 524 return false;
458 525 }
459   - value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal();
  526 + value = boolean->getVal();
460 527 return true;
461 528 }
462 529  
... ... @@ -465,8 +532,9 @@ QPDFObjectHandle::getValueAsBool(bool&amp; value)
465 532 long long
466 533 QPDFObjectHandle::getIntValue()
467 534 {
468   - if (isInteger()) {
469   - return dynamic_cast<QPDF_Integer*>(obj.get())->getVal();
  535 + auto integer = asInteger();
  536 + if (integer) {
  537 + return integer->getVal();
470 538 } else {
471 539 typeWarning("integer", "returning 0");
472 540 QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
... ... @@ -477,10 +545,11 @@ QPDFObjectHandle::getIntValue()
477 545 bool
478 546 QPDFObjectHandle::getValueAsInt(long long& value)
479 547 {
480   - if (!isInteger()) {
  548 + auto integer = asInteger();
  549 + if (integer == nullptr) {
481 550 return false;
482 551 }
483   - value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal();
  552 + value = integer->getVal();
484 553 return true;
485 554 }
486 555  
... ... @@ -576,8 +645,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int&amp; value)
576 645 std::string
577 646 QPDFObjectHandle::getRealValue()
578 647 {
579   - if (isReal()) {
580   - return dynamic_cast<QPDF_Real*>(obj.get())->getVal();
  648 + auto real = asReal();
  649 + if (real) {
  650 + return real->getVal();
581 651 } else {
582 652 typeWarning("real", "returning 0.0");
583 653 QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0");
... ... @@ -588,10 +658,11 @@ QPDFObjectHandle::getRealValue()
588 658 bool
589 659 QPDFObjectHandle::getValueAsReal(std::string& value)
590 660 {
591   - if (!isReal()) {
  661 + auto real = asReal();
  662 + if (real == nullptr) {
592 663 return false;
593 664 }
594   - value = dynamic_cast<QPDF_Real*>(obj.get())->getVal();
  665 + value = real->getVal();
595 666 return true;
596 667 }
597 668  
... ... @@ -600,8 +671,9 @@ QPDFObjectHandle::getValueAsReal(std::string&amp; value)
600 671 std::string
601 672 QPDFObjectHandle::getName()
602 673 {
603   - if (isName()) {
604   - return dynamic_cast<QPDF_Name*>(obj.get())->getName();
  674 + auto name = asName();
  675 + if (name) {
  676 + return name->getName();
605 677 } else {
606 678 typeWarning("name", "returning dummy name");
607 679 QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name");
... ... @@ -612,10 +684,11 @@ QPDFObjectHandle::getName()
612 684 bool
613 685 QPDFObjectHandle::getValueAsName(std::string& value)
614 686 {
615   - if (!isName()) {
  687 + auto name = asName();
  688 + if (name == nullptr) {
616 689 return false;
617 690 }
618   - value = dynamic_cast<QPDF_Name*>(obj.get())->getName();
  691 + value = name->getName();
619 692 return true;
620 693 }
621 694  
... ... @@ -624,8 +697,9 @@ QPDFObjectHandle::getValueAsName(std::string&amp; value)
624 697 std::string
625 698 QPDFObjectHandle::getStringValue()
626 699 {
627   - if (isString()) {
628   - return dynamic_cast<QPDF_String*>(obj.get())->getVal();
  700 + auto str = asString();
  701 + if (str) {
  702 + return str->getVal();
629 703 } else {
630 704 typeWarning("string", "returning empty string");
631 705 QTC::TC("qpdf", "QPDFObjectHandle string returning empty string");
... ... @@ -636,18 +710,20 @@ QPDFObjectHandle::getStringValue()
636 710 bool
637 711 QPDFObjectHandle::getValueAsString(std::string& value)
638 712 {
639   - if (!isString()) {
  713 + auto str = asString();
  714 + if (str == nullptr) {
640 715 return false;
641 716 }
642   - value = dynamic_cast<QPDF_String*>(obj.get())->getVal();
  717 + value = str->getVal();
643 718 return true;
644 719 }
645 720  
646 721 std::string
647 722 QPDFObjectHandle::getUTF8Value()
648 723 {
649   - if (isString()) {
650   - return dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val();
  724 + auto str = asString();
  725 + if (str) {
  726 + return str->getUTF8Val();
651 727 } else {
652 728 typeWarning("string", "returning empty string");
653 729 QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8");
... ... @@ -658,10 +734,11 @@ QPDFObjectHandle::getUTF8Value()
658 734 bool
659 735 QPDFObjectHandle::getValueAsUTF8(std::string& value)
660 736 {
661   - if (!isString()) {
  737 + auto str = asString();
  738 + if (str == nullptr) {
662 739 return false;
663 740 }
664   - value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val();
  741 + value = str->getUTF8Val();
665 742 return true;
666 743 }
667 744  
... ... @@ -670,8 +747,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string&amp; value)
670 747 std::string
671 748 QPDFObjectHandle::getOperatorValue()
672 749 {
673   - if (isOperator()) {
674   - return dynamic_cast<QPDF_Operator*>(obj.get())->getVal();
  750 + auto op = asOperator();
  751 + if (op) {
  752 + return op->getVal();
675 753 } else {
676 754 typeWarning("operator", "returning fake value");
677 755 QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value");
... ... @@ -682,18 +760,20 @@ QPDFObjectHandle::getOperatorValue()
682 760 bool
683 761 QPDFObjectHandle::getValueAsOperator(std::string& value)
684 762 {
685   - if (!isOperator()) {
  763 + auto op = asOperator();
  764 + if (op == nullptr) {
686 765 return false;
687 766 }
688   - value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal();
  767 + value = op->getVal();
689 768 return true;
690 769 }
691 770  
692 771 std::string
693 772 QPDFObjectHandle::getInlineImageValue()
694 773 {
695   - if (isInlineImage()) {
696   - return dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal();
  774 + auto image = asInlineImage();
  775 + if (image) {
  776 + return image->getVal();
697 777 } else {
698 778 typeWarning("inlineimage", "returning empty data");
699 779 QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data");
... ... @@ -704,10 +784,11 @@ QPDFObjectHandle::getInlineImageValue()
704 784 bool
705 785 QPDFObjectHandle::getValueAsInlineImage(std::string& value)
706 786 {
707   - if (!isInlineImage()) {
  787 + auto image = asInlineImage();
  788 + if (image == nullptr) {
708 789 return false;
709 790 }
710   - value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal();
  791 + value = image->getVal();
711 792 return true;
712 793 }
713 794  
... ... @@ -722,8 +803,9 @@ QPDFObjectHandle::aitems()
722 803 int
723 804 QPDFObjectHandle::getArrayNItems()
724 805 {
725   - if (isArray()) {
726   - return dynamic_cast<QPDF_Array*>(obj.get())->getNItems();
  806 + auto array = asArray();
  807 + if (array) {
  808 + return array->getNItems();
727 809 } else {
728 810 typeWarning("array", "treating as empty");
729 811 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty");
... ... @@ -735,11 +817,12 @@ QPDFObjectHandle
735 817 QPDFObjectHandle::getArrayItem(int n)
736 818 {
737 819 QPDFObjectHandle result;
738   - if (isArray() && (n < getArrayNItems()) && (n >= 0)) {
739   - result = dynamic_cast<QPDF_Array*>(obj.get())->getItem(n);
  820 + auto array = asArray();
  821 + if (array && (n < array->getNItems()) && (n >= 0)) {
  822 + result = array->getItem(n);
740 823 } else {
741 824 result = newNull();
742   - if (isArray()) {
  825 + if (array) {
743 826 objectWarning("returning null for out of bounds array access");
744 827 QTC::TC("qpdf", "QPDFObjectHandle array bounds");
745 828 } else {
... ... @@ -748,7 +831,7 @@ QPDFObjectHandle::getArrayItem(int n)
748 831 }
749 832 QPDF* context = nullptr;
750 833 std::string description;
751   - if (this->obj->getDescription(context, description)) {
  834 + if (obj->getDescription(context, description)) {
752 835 result.setObjectDescription(
753 836 context,
754 837 description + " -> null returned from invalid array access");
... ... @@ -760,14 +843,12 @@ QPDFObjectHandle::getArrayItem(int n)
760 843 bool
761 844 QPDFObjectHandle::isRectangle()
762 845 {
763   - if (!isArray()) {
764   - return false;
765   - }
766   - if (getArrayNItems() != 4) {
  846 + auto array = asArray();
  847 + if ((array == nullptr) || (array->getNItems() != 4)) {
767 848 return false;
768 849 }
769 850 for (int i = 0; i < 4; ++i) {
770   - if (!getArrayItem(i).isNumber()) {
  851 + if (!array->getItem(i).isNumber()) {
771 852 return false;
772 853 }
773 854 }
... ... @@ -777,14 +858,12 @@ QPDFObjectHandle::isRectangle()
777 858 bool
778 859 QPDFObjectHandle::isMatrix()
779 860 {
780   - if (!isArray()) {
781   - return false;
782   - }
783   - if (getArrayNItems() != 6) {
  861 + auto array = asArray();
  862 + if ((array == nullptr) || (array->getNItems() != 6)) {
784 863 return false;
785 864 }
786 865 for (int i = 0; i < 6; ++i) {
787   - if (!getArrayItem(i).isNumber()) {
  866 + if (!array->getItem(i).isNumber()) {
788 867 return false;
789 868 }
790 869 }
... ... @@ -796,13 +875,14 @@ QPDFObjectHandle::getArrayAsRectangle()
796 875 {
797 876 Rectangle result;
798 877 if (isRectangle()) {
  878 + auto array = asArray();
799 879 // Rectangle coordinates are always supposed to be llx, lly,
800 880 // urx, ury, but files have been found in the wild where
801 881 // llx > urx or lly > ury.
802   - double i0 = getArrayItem(0).getNumericValue();
803   - double i1 = getArrayItem(1).getNumericValue();
804   - double i2 = getArrayItem(2).getNumericValue();
805   - double i3 = getArrayItem(3).getNumericValue();
  882 + double i0 = array->getItem(0).getNumericValue();
  883 + double i1 = array->getItem(1).getNumericValue();
  884 + double i2 = array->getItem(2).getNumericValue();
  885 + double i3 = array->getItem(3).getNumericValue();
806 886 result = Rectangle(
807 887 std::min(i0, i2),
808 888 std::min(i1, i3),
... ... @@ -817,13 +897,14 @@ QPDFObjectHandle::getArrayAsMatrix()
817 897 {
818 898 Matrix result;
819 899 if (isMatrix()) {
  900 + auto array = asArray();
820 901 result = Matrix(
821   - getArrayItem(0).getNumericValue(),
822   - getArrayItem(1).getNumericValue(),
823   - getArrayItem(2).getNumericValue(),
824   - getArrayItem(3).getNumericValue(),
825   - getArrayItem(4).getNumericValue(),
826   - getArrayItem(5).getNumericValue());
  902 + array->getItem(0).getNumericValue(),
  903 + array->getItem(1).getNumericValue(),
  904 + array->getItem(2).getNumericValue(),
  905 + array->getItem(3).getNumericValue(),
  906 + array->getItem(4).getNumericValue(),
  907 + array->getItem(5).getNumericValue());
827 908 }
828 909 return result;
829 910 }
... ... @@ -832,8 +913,9 @@ std::vector&lt;QPDFObjectHandle&gt;
832 913 QPDFObjectHandle::getArrayAsVector()
833 914 {
834 915 std::vector<QPDFObjectHandle> result;
835   - if (isArray()) {
836   - dynamic_cast<QPDF_Array*>(obj.get())->getAsVector(result);
  916 + auto array = asArray();
  917 + if (array) {
  918 + array->getAsVector(result);
837 919 } else {
838 920 typeWarning("array", "treating as empty");
839 921 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector");
... ... @@ -846,9 +928,10 @@ QPDFObjectHandle::getArrayAsVector()
846 928 void
847 929 QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item)
848 930 {
849   - if (isArray()) {
  931 + auto array = asArray();
  932 + if (array) {
850 933 checkOwnership(item);
851   - dynamic_cast<QPDF_Array*>(obj.get())->setItem(n, item);
  934 + array->setItem(n, item);
852 935 } else {
853 936 typeWarning("array", "ignoring attempt to set item");
854 937 QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item");
... ... @@ -858,11 +941,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const&amp; item)
858 941 void
859 942 QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items)
860 943 {
861   - if (isArray()) {
  944 + auto array = asArray();
  945 + if (array) {
862 946 for (auto const& item: items) {
863 947 checkOwnership(item);
864 948 }
865   - dynamic_cast<QPDF_Array*>(obj.get())->setFromVector(items);
  949 + array->setFromVector(items);
866 950 } else {
867 951 typeWarning("array", "ignoring attempt to replace items");
868 952 QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items");
... ... @@ -872,8 +956,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector&lt;QPDFObjectHandle&gt; const&amp; items)
872 956 void
873 957 QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item)
874 958 {
875   - if (isArray()) {
876   - dynamic_cast<QPDF_Array*>(obj.get())->insertItem(at, item);
  959 + auto array = asArray();
  960 + if (array) {
  961 + array->insertItem(at, item);
877 962 } else {
878 963 typeWarning("array", "ignoring attempt to insert item");
879 964 QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item");
... ... @@ -890,9 +975,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const&amp; item)
890 975 void
891 976 QPDFObjectHandle::appendItem(QPDFObjectHandle const& item)
892 977 {
893   - if (isArray()) {
  978 + auto array = asArray();
  979 + if (array) {
894 980 checkOwnership(item);
895   - dynamic_cast<QPDF_Array*>(obj.get())->appendItem(item);
  981 + array->appendItem(item);
896 982 } else {
897 983 typeWarning("array", "ignoring attempt to append item");
898 984 QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item");
... ... @@ -909,10 +995,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const&amp; item)
909 995 void
910 996 QPDFObjectHandle::eraseItem(int at)
911 997 {
912   - if (isArray() && (at < getArrayNItems()) && (at >= 0)) {
913   - dynamic_cast<QPDF_Array*>(obj.get())->eraseItem(at);
  998 + auto array = asArray();
  999 + if (array && (at < array->getNItems()) && (at >= 0)) {
  1000 + array->eraseItem(at);
914 1001 } else {
915   - if (isArray()) {
  1002 + if (array) {
916 1003 objectWarning("ignoring attempt to erase out of bounds array item");
917 1004 QTC::TC("qpdf", "QPDFObjectHandle erase array bounds");
918 1005 } else {
... ... @@ -926,8 +1013,9 @@ QPDFObjectHandle
926 1013 QPDFObjectHandle::eraseItemAndGetOld(int at)
927 1014 {
928 1015 auto result = QPDFObjectHandle::newNull();
929   - if (isArray() && (at < getArrayNItems()) && (at >= 0)) {
930   - result = getArrayItem(at);
  1016 + auto array = asArray();
  1017 + if (array && (at < array->getNItems()) && (at >= 0)) {
  1018 + result = array->getItem(at);
931 1019 }
932 1020 eraseItem(at);
933 1021 return result;
... ... @@ -944,8 +1032,9 @@ QPDFObjectHandle::ditems()
944 1032 bool
945 1033 QPDFObjectHandle::hasKey(std::string const& key)
946 1034 {
947   - if (isDictionary()) {
948   - return dynamic_cast<QPDF_Dictionary*>(obj.get())->hasKey(key);
  1035 + auto dict = asDictionary();
  1036 + if (dict) {
  1037 + return dict->hasKey(key);
949 1038 } else {
950 1039 typeWarning(
951 1040 "dictionary", "returning false for a key containment request");
... ... @@ -958,15 +1047,16 @@ QPDFObjectHandle
958 1047 QPDFObjectHandle::getKey(std::string const& key)
959 1048 {
960 1049 QPDFObjectHandle result;
961   - if (isDictionary()) {
962   - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKey(key);
  1050 + auto dict = asDictionary();
  1051 + if (dict) {
  1052 + result = dict->getKey(key);
963 1053 } else {
964 1054 typeWarning("dictionary", "returning null for attempted key retrieval");
965 1055 QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey");
966 1056 result = newNull();
967 1057 QPDF* qpdf = nullptr;
968 1058 std::string description;
969   - if (this->obj->getDescription(qpdf, description)) {
  1059 + if (obj->getDescription(qpdf, description)) {
970 1060 result.setObjectDescription(
971 1061 qpdf,
972 1062 (description + " -> null returned from getting key " + key +
... ... @@ -986,8 +1076,9 @@ std::set&lt;std::string&gt;
986 1076 QPDFObjectHandle::getKeys()
987 1077 {
988 1078 std::set<std::string> result;
989   - if (isDictionary()) {
990   - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getKeys();
  1079 + auto dict = asDictionary();
  1080 + if (dict) {
  1081 + result = dict->getKeys();
991 1082 } else {
992 1083 typeWarning("dictionary", "treating as empty");
993 1084 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys");
... ... @@ -999,8 +1090,9 @@ std::map&lt;std::string, QPDFObjectHandle&gt;
999 1090 QPDFObjectHandle::getDictAsMap()
1000 1091 {
1001 1092 std::map<std::string, QPDFObjectHandle> result;
1002   - if (isDictionary()) {
1003   - result = dynamic_cast<QPDF_Dictionary*>(obj.get())->getAsMap();
  1093 + auto dict = asDictionary();
  1094 + if (dict) {
  1095 + result = dict->getAsMap();
1004 1096 } else {
1005 1097 typeWarning("dictionary", "treating as empty");
1006 1098 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap");
... ... @@ -1191,9 +1283,10 @@ void
1191 1283 QPDFObjectHandle::replaceKey(
1192 1284 std::string const& key, QPDFObjectHandle const& value)
1193 1285 {
1194   - if (isDictionary()) {
  1286 + auto dict = asDictionary();
  1287 + if (dict) {
1195 1288 checkOwnership(value);
1196   - dynamic_cast<QPDF_Dictionary*>(obj.get())->replaceKey(key, value);
  1289 + dict->replaceKey(key, value);
1197 1290 } else {
1198 1291 typeWarning("dictionary", "ignoring key replacement request");
1199 1292 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey");
... ... @@ -1220,8 +1313,9 @@ QPDFObjectHandle::replaceKeyAndGetOld(
1220 1313 void
1221 1314 QPDFObjectHandle::removeKey(std::string const& key)
1222 1315 {
1223   - if (isDictionary()) {
1224   - dynamic_cast<QPDF_Dictionary*>(obj.get())->removeKey(key);
  1316 + auto dict = asDictionary();
  1317 + if (dict) {
  1318 + dict->removeKey(key);
1225 1319 } else {
1226 1320 typeWarning("dictionary", "ignoring key removal request");
1227 1321 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey");
... ... @@ -1232,8 +1326,9 @@ QPDFObjectHandle
1232 1326 QPDFObjectHandle::removeKeyAndGetOld(std::string const& key)
1233 1327 {
1234 1328 auto result = QPDFObjectHandle::newNull();
1235   - if (isDictionary()) {
1236   - result = getKey(key);
  1329 + auto dict = asDictionary();
  1330 + if (dict) {
  1331 + result = dict->getKey(key);
1237 1332 }
1238 1333 removeKey(key);
1239 1334 return result;
... ... @@ -1250,50 +1345,43 @@ QPDFObjectHandle::replaceOrRemoveKey(
1250 1345 QPDFObjectHandle
1251 1346 QPDFObjectHandle::getDict()
1252 1347 {
1253   - assertStream();
1254   - return dynamic_cast<QPDF_Stream*>(obj.get())->getDict();
  1348 + return asStreamWithAssert()->getDict();
1255 1349 }
1256 1350  
1257 1351 void
1258 1352 QPDFObjectHandle::setFilterOnWrite(bool val)
1259 1353 {
1260   - assertStream();
1261   - dynamic_cast<QPDF_Stream*>(obj.get())->setFilterOnWrite(val);
  1354 + asStreamWithAssert()->setFilterOnWrite(val);
1262 1355 }
1263 1356  
1264 1357 bool
1265 1358 QPDFObjectHandle::getFilterOnWrite()
1266 1359 {
1267   - assertStream();
1268   - return dynamic_cast<QPDF_Stream*>(obj.get())->getFilterOnWrite();
  1360 + return asStreamWithAssert()->getFilterOnWrite();
1269 1361 }
1270 1362  
1271 1363 bool
1272 1364 QPDFObjectHandle::isDataModified()
1273 1365 {
1274   - assertStream();
1275   - return dynamic_cast<QPDF_Stream*>(obj.get())->isDataModified();
  1366 + return asStreamWithAssert()->isDataModified();
1276 1367 }
1277 1368  
1278 1369 void
1279 1370 QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict)
1280 1371 {
1281   - assertStream();
1282   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceDict(new_dict);
  1372 + asStreamWithAssert()->replaceDict(new_dict);
1283 1373 }
1284 1374  
1285 1375 std::shared_ptr<Buffer>
1286 1376 QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level)
1287 1377 {
1288   - assertStream();
1289   - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamData(level);
  1378 + return asStreamWithAssert()->getStreamData(level);
1290 1379 }
1291 1380  
1292 1381 std::shared_ptr<Buffer>
1293 1382 QPDFObjectHandle::getRawStreamData()
1294 1383 {
1295   - assertStream();
1296   - return dynamic_cast<QPDF_Stream*>(obj.get())->getRawStreamData();
  1384 + return asStreamWithAssert()->getRawStreamData();
1297 1385 }
1298 1386  
1299 1387 bool
... ... @@ -1305,8 +1393,7 @@ QPDFObjectHandle::pipeStreamData(
1305 1393 bool suppress_warnings,
1306 1394 bool will_retry)
1307 1395 {
1308   - assertStream();
1309   - return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData(
  1396 + return asStreamWithAssert()->pipeStreamData(
1310 1397 p,
1311 1398 filtering_attempted,
1312 1399 encode_flags,
... ... @@ -1323,9 +1410,8 @@ QPDFObjectHandle::pipeStreamData(
1323 1410 bool suppress_warnings,
1324 1411 bool will_retry)
1325 1412 {
1326   - assertStream();
1327 1413 bool filtering_attempted;
1328   - dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData(
  1414 + asStreamWithAssert()->pipeStreamData(
1329 1415 p,
1330 1416 &filtering_attempted,
1331 1417 encode_flags,
... ... @@ -1359,9 +1445,7 @@ QPDFObjectHandle::replaceStreamData(
1359 1445 QPDFObjectHandle const& filter,
1360 1446 QPDFObjectHandle const& decode_parms)
1361 1447 {
1362   - assertStream();
1363   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
1364   - data, filter, decode_parms);
  1448 + asStreamWithAssert()->replaceStreamData(data, filter, decode_parms);
1365 1449 }
1366 1450  
1367 1451 void
... ... @@ -1370,14 +1454,12 @@ QPDFObjectHandle::replaceStreamData(
1370 1454 QPDFObjectHandle const& filter,
1371 1455 QPDFObjectHandle const& decode_parms)
1372 1456 {
1373   - assertStream();
1374 1457 auto b = std::make_shared<Buffer>(data.length());
1375 1458 unsigned char* bp = b->getBuffer();
1376 1459 if (bp) {
1377 1460 memcpy(bp, data.c_str(), data.length());
1378 1461 }
1379   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
1380   - b, filter, decode_parms);
  1462 + asStreamWithAssert()->replaceStreamData(b, filter, decode_parms);
1381 1463 }
1382 1464  
1383 1465 void
... ... @@ -1386,9 +1468,7 @@ QPDFObjectHandle::replaceStreamData(
1386 1468 QPDFObjectHandle const& filter,
1387 1469 QPDFObjectHandle const& decode_parms)
1388 1470 {
1389   - assertStream();
1390   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
1391   - provider, filter, decode_parms);
  1471 + asStreamWithAssert()->replaceStreamData(provider, filter, decode_parms);
1392 1472 }
1393 1473  
1394 1474 namespace
... ... @@ -1437,11 +1517,9 @@ QPDFObjectHandle::replaceStreamData(
1437 1517 QPDFObjectHandle const& filter,
1438 1518 QPDFObjectHandle const& decode_parms)
1439 1519 {
1440   - assertStream();
1441 1520 auto sdp =
1442 1521 std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider));
1443   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
1444   - sdp, filter, decode_parms);
  1522 + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms);
1445 1523 }
1446 1524  
1447 1525 void
... ... @@ -1450,11 +1528,9 @@ QPDFObjectHandle::replaceStreamData(
1450 1528 QPDFObjectHandle const& filter,
1451 1529 QPDFObjectHandle const& decode_parms)
1452 1530 {
1453   - assertStream();
1454 1531 auto sdp =
1455 1532 std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider));
1456   - dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
1457   - sdp, filter, decode_parms);
  1533 + asStreamWithAssert()->replaceStreamData(sdp, filter, decode_parms);
1458 1534 }
1459 1535  
1460 1536 std::map<std::string, QPDFObjectHandle>
... ... @@ -1469,10 +1545,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
1469 1545 {
1470 1546 all_description = description;
1471 1547 std::vector<QPDFObjectHandle> result;
1472   - if (isArray()) {
1473   - int n_items = getArrayNItems();
  1548 + auto array = asArray();
  1549 + if (array) {
  1550 + int n_items = array->getNItems();
1474 1551 for (int i = 0; i < n_items; ++i) {
1475   - QPDFObjectHandle item = getArrayItem(i);
  1552 + QPDFObjectHandle item = array->getItem(i);
1476 1553 if (item.isStream()) {
1477 1554 result.push_back(item);
1478 1555 } else {
... ... @@ -1649,8 +1726,9 @@ QPDFObjectHandle::unparseResolved()
1649 1726 std::string
1650 1727 QPDFObjectHandle::unparseBinary()
1651 1728 {
1652   - if (this->isString()) {
1653   - return dynamic_cast<QPDF_String*>(this->obj.get())->unparse(true);
  1729 + auto str = asString();
  1730 + if (str) {
  1731 + return str->unparse(true);
1654 1732 } else {
1655 1733 return unparse();
1656 1734 }
... ... @@ -1666,7 +1744,7 @@ QPDFObjectHandle::getJSON(bool dereference_indirect)
1666 1744 JSON
1667 1745 QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1668 1746 {
1669   - if ((!dereference_indirect) && this->isIndirect()) {
  1747 + if ((!dereference_indirect) && isIndirect()) {
1670 1748 return JSON::makeString(unparse());
1671 1749 } else if (!dereference()) {
1672 1750 throw std::logic_error(
... ... @@ -1675,7 +1753,7 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1675 1753 throw std::logic_error(
1676 1754 "QPDFObjectHandle: attempting to unparse a reserved object");
1677 1755 } else {
1678   - return this->obj->getJSON(json_version);
  1756 + return obj->getJSON(json_version);
1679 1757 }
1680 1758 }
1681 1759  
... ... @@ -1687,8 +1765,7 @@ QPDFObjectHandle::getStreamJSON(
1687 1765 Pipeline* p,
1688 1766 std::string const& data_filename)
1689 1767 {
1690   - assertStream();
1691   - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamJSON(
  1768 + return asStreamWithAssert()->getStreamJSON(
1692 1769 json_version, json_data, decode_level, p, data_filename);
1693 1770 }
1694 1771  
... ... @@ -1908,8 +1985,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr&lt;TokenFilter&gt; filter)
1908 1985 void
1909 1986 QPDFObjectHandle::addTokenFilter(std::shared_ptr<TokenFilter> filter)
1910 1987 {
1911   - assertStream();
1912   - return dynamic_cast<QPDF_Stream*>(obj.get())->addTokenFilter(filter);
  1988 + return asStreamWithAssert()->addTokenFilter(filter);
1913 1989 }
1914 1990  
1915 1991 QPDFObjectHandle
... ... @@ -1946,7 +2022,6 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const&amp; og)
1946 2022 QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid");
1947 2023 return newNull();
1948 2024 }
1949   -
1950 2025 return QPDFObjectHandle(qpdf, og, QPDF_Unresolved::create());
1951 2026 }
1952 2027  
... ... @@ -2119,8 +2194,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf)
2119 2194 QPDFObjectHandle stream_dict = newDictionary();
2120 2195 QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle(
2121 2196 QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0)));
2122   - result.dereference();
2123   - QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get());
  2197 + auto stream = result.asStream();
2124 2198 stream->setObjGen(result.getObjGen());
2125 2199 return result;
2126 2200 }
... ... @@ -2248,9 +2322,10 @@ QPDFObjectHandle::copyObject(
2248 2322 new_obj = obj->shallowCopy();
2249 2323 } else if (isArray()) {
2250 2324 std::vector<QPDFObjectHandle> items;
2251   - int n = getArrayNItems();
  2325 + auto array = asArray();
  2326 + int n = array->getNItems();
2252 2327 for (int i = 0; i < n; ++i) {
2253   - items.push_back(getArrayItem(i));
  2328 + items.push_back(array->getItem(i));
2254 2329 if ((!first_level_only) &&
2255 2330 (cross_indirect || (!items.back().isIndirect()))) {
2256 2331 items.back().copyObject(
... ... @@ -2260,8 +2335,9 @@ QPDFObjectHandle::copyObject(
2260 2335 new_obj = QPDF_Array::create(items);
2261 2336 } else if (isDictionary()) {
2262 2337 std::map<std::string, QPDFObjectHandle> items;
  2338 + auto dict = asDictionary();
2263 2339 for (auto const& key: getKeys()) {
2264   - items[key] = getKey(key);
  2340 + items[key] = dict->getKey(key);
2265 2341 if ((!first_level_only) &&
2266 2342 (cross_indirect || (!items[key].isIndirect()))) {
2267 2343 items[key].copyObject(
... ... @@ -2309,7 +2385,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams)
2309 2385 void
2310 2386 QPDFObjectHandle::assertInitialized() const
2311 2387 {
2312   - if (!this->initialized) {
  2388 + if (!initialized) {
2313 2389 throw std::logic_error("operation attempted on uninitialized "
2314 2390 "QPDFObjectHandle");
2315 2391 }
... ... @@ -2551,7 +2627,6 @@ QPDFObjectHandle::dereference()
2551 2627 (getObjectID() &&
2552 2628 QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj))) {
2553 2629 this->obj = QPDF::Resolver::resolve(this->qpdf, getObjGen());
2554   -
2555 2630 }
2556 2631 return true;
2557 2632 }
... ...
libqpdf/QPDF_Reserved.cc
... ... @@ -17,14 +17,16 @@ QPDF_Reserved::shallowCopy()
17 17 std::string
18 18 QPDF_Reserved::unparse()
19 19 {
20   - throw std::logic_error("attempt to unparse QPDF_Reserved");
  20 + throw std::logic_error(
  21 + "QPDFObjectHandle: attempting to unparse a reserved object");
21 22 return "";
22 23 }
23 24  
24 25 JSON
25 26 QPDF_Reserved::getJSON(int json_version)
26 27 {
27   - throw std::logic_error("attempt to generate JSON from QPDF_Reserved");
  28 + throw std::logic_error(
  29 + "QPDFObjectHandle: attempting to unparse a reserved object");
28 30 return JSON::makeNull();
29 31 }
30 32  
... ...