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,8 +43,18 @@
43 43
44 class Pipeline; 44 class Pipeline;
45 class QPDF; 45 class QPDF;
46 -class QPDF_Dictionary;  
47 class QPDF_Array; 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 class QPDFTokenizer; 58 class QPDFTokenizer;
49 class QPDFExc; 59 class QPDFExc;
50 class Pl_QPDFTokenizer; 60 class Pl_QPDFTokenizer;
@@ -1480,6 +1490,16 @@ class QPDFObjectHandle @@ -1480,6 +1490,16 @@ class QPDFObjectHandle
1480 }; 1490 };
1481 return o.obj; 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 friend class ObjAccessor; 1504 friend class ObjAccessor;
1485 1505
@@ -1581,6 +1601,20 @@ class QPDFObjectHandle @@ -1581,6 +1601,20 @@ class QPDFObjectHandle
1581 qpdf_offset_t offset, 1601 qpdf_offset_t offset,
1582 size_t length); 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 void typeWarning(char const* expected_type, std::string const& warning); 1618 void typeWarning(char const* expected_type, std::string const& warning);
1585 void objectWarning(std::string const& warning); 1619 void objectWarning(std::string const& warning);
1586 void assertType(char const* type_name, bool istype); 1620 void assertType(char const* type_name, bool istype);
@@ -1881,7 +1915,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset) @@ -1881,7 +1915,7 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset)
1881 { 1915 {
1882 // This is called during parsing on newly created direct objects, 1916 // This is called during parsing on newly created direct objects,
1883 // so we can't call dereference() here. 1917 // so we can't call dereference() here.
1884 - if (this->obj.get()) { 1918 + if (initialized) {
1885 this->obj->setParsedOffset(offset); 1919 this->obj->setParsedOffset(offset);
1886 } 1920 }
1887 } 1921 }
libqpdf/QPDF.cc
@@ -1420,8 +1420,7 @@ QPDF::fixDanglingReferences(bool force) @@ -1420,8 +1420,7 @@ QPDF::fixDanglingReferences(bool force)
1420 to_check.push_back(iter.second); 1420 to_check.push_back(iter.second);
1421 } 1421 }
1422 } else if (obj.isArray()) { 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 arr->addExplicitElementsToList(to_check); 1424 arr->addExplicitElementsToList(to_check);
1426 } 1425 }
1427 for (auto sub: to_check) { 1426 for (auto sub: to_check) {
@@ -2468,12 +2467,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) @@ -2468,12 +2467,12 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
2468 QPDFObjGen local_og(result.getObjGen()); 2467 QPDFObjGen local_og(result.getObjGen());
2469 // Copy information from the foreign stream so we can pipe its 2468 // Copy information from the foreign stream so we can pipe its
2470 // data later without keeping the original QPDF object around. 2469 // data later without keeping the original QPDF object around.
  2470 +
2471 QPDF* foreign_stream_qpdf = foreign.getOwningQPDF( 2471 QPDF* foreign_stream_qpdf = foreign.getOwningQPDF(
2472 false, "unable to retrieve owning qpdf from foreign stream"); 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 throw std::logic_error("unable to retrieve underlying" 2476 throw std::logic_error("unable to retrieve underlying"
2478 " stream object from foreign stream"); 2477 " stream object from foreign stream");
2479 } 2478 }
libqpdf/QPDFObjectHandle.cc
@@ -277,24 +277,91 @@ QPDFObjectHandle::getTypeName() @@ -277,24 +277,91 @@ QPDFObjectHandle::getTypeName()
277 return dereference() ? this->obj->getTypeName() : "uninitialized"; 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 bool 361 bool
295 QPDFObjectHandle::isBool() 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 bool 367 bool
@@ -303,26 +370,26 @@ QPDFObjectHandle::isDirectNull() const @@ -303,26 +370,26 @@ QPDFObjectHandle::isDirectNull() const
303 // Don't call dereference() -- this is a const method, and we know 370 // Don't call dereference() -- this is a const method, and we know
304 // objid == 0, so there's nothing to resolve. 371 // objid == 0, so there's nothing to resolve.
305 return ( 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 bool 377 bool
311 QPDFObjectHandle::isNull() 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 bool 383 bool
317 QPDFObjectHandle::isInteger() 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 bool 389 bool
323 QPDFObjectHandle::isReal() 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 bool 395 bool
@@ -359,51 +426,49 @@ QPDFObjectHandle::getValueAsNumber(double&amp; value) @@ -359,51 +426,49 @@ QPDFObjectHandle::getValueAsNumber(double&amp; value)
359 bool 426 bool
360 QPDFObjectHandle::isName() 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 bool 432 bool
366 QPDFObjectHandle::isString() 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 bool 438 bool
372 QPDFObjectHandle::isOperator() 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 bool 444 bool
378 QPDFObjectHandle::isInlineImage() 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 bool 450 bool
385 QPDFObjectHandle::isArray() 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 bool 456 bool
391 QPDFObjectHandle::isDictionary() 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 bool 462 bool
397 QPDFObjectHandle::isStream() 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 bool 468 bool
403 QPDFObjectHandle::isReserved() 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 bool 474 bool
@@ -441,8 +506,9 @@ QPDFObjectHandle::isStreamOfType( @@ -441,8 +506,9 @@ QPDFObjectHandle::isStreamOfType(
441 bool 506 bool
442 QPDFObjectHandle::getBoolValue() 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 } else { 512 } else {
447 typeWarning("boolean", "returning false"); 513 typeWarning("boolean", "returning false");
448 QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); 514 QTC::TC("qpdf", "QPDFObjectHandle boolean returning false");
@@ -453,10 +519,11 @@ QPDFObjectHandle::getBoolValue() @@ -453,10 +519,11 @@ QPDFObjectHandle::getBoolValue()
453 bool 519 bool
454 QPDFObjectHandle::getValueAsBool(bool& value) 520 QPDFObjectHandle::getValueAsBool(bool& value)
455 { 521 {
456 - if (!isBool()) { 522 + auto boolean = asBool();
  523 + if (boolean == nullptr) {
457 return false; 524 return false;
458 } 525 }
459 - value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal(); 526 + value = boolean->getVal();
460 return true; 527 return true;
461 } 528 }
462 529
@@ -465,8 +532,9 @@ QPDFObjectHandle::getValueAsBool(bool&amp; value) @@ -465,8 +532,9 @@ QPDFObjectHandle::getValueAsBool(bool&amp; value)
465 long long 532 long long
466 QPDFObjectHandle::getIntValue() 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 } else { 538 } else {
471 typeWarning("integer", "returning 0"); 539 typeWarning("integer", "returning 0");
472 QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); 540 QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
@@ -477,10 +545,11 @@ QPDFObjectHandle::getIntValue() @@ -477,10 +545,11 @@ QPDFObjectHandle::getIntValue()
477 bool 545 bool
478 QPDFObjectHandle::getValueAsInt(long long& value) 546 QPDFObjectHandle::getValueAsInt(long long& value)
479 { 547 {
480 - if (!isInteger()) { 548 + auto integer = asInteger();
  549 + if (integer == nullptr) {
481 return false; 550 return false;
482 } 551 }
483 - value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal(); 552 + value = integer->getVal();
484 return true; 553 return true;
485 } 554 }
486 555
@@ -576,8 +645,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int&amp; value) @@ -576,8 +645,9 @@ QPDFObjectHandle::getValueAsUInt(unsigned int&amp; value)
576 std::string 645 std::string
577 QPDFObjectHandle::getRealValue() 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 } else { 651 } else {
582 typeWarning("real", "returning 0.0"); 652 typeWarning("real", "returning 0.0");
583 QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0"); 653 QTC::TC("qpdf", "QPDFObjectHandle real returning 0.0");
@@ -588,10 +658,11 @@ QPDFObjectHandle::getRealValue() @@ -588,10 +658,11 @@ QPDFObjectHandle::getRealValue()
588 bool 658 bool
589 QPDFObjectHandle::getValueAsReal(std::string& value) 659 QPDFObjectHandle::getValueAsReal(std::string& value)
590 { 660 {
591 - if (!isReal()) { 661 + auto real = asReal();
  662 + if (real == nullptr) {
592 return false; 663 return false;
593 } 664 }
594 - value = dynamic_cast<QPDF_Real*>(obj.get())->getVal(); 665 + value = real->getVal();
595 return true; 666 return true;
596 } 667 }
597 668
@@ -600,8 +671,9 @@ QPDFObjectHandle::getValueAsReal(std::string&amp; value) @@ -600,8 +671,9 @@ QPDFObjectHandle::getValueAsReal(std::string&amp; value)
600 std::string 671 std::string
601 QPDFObjectHandle::getName() 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 } else { 677 } else {
606 typeWarning("name", "returning dummy name"); 678 typeWarning("name", "returning dummy name");
607 QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name"); 679 QTC::TC("qpdf", "QPDFObjectHandle name returning dummy name");
@@ -612,10 +684,11 @@ QPDFObjectHandle::getName() @@ -612,10 +684,11 @@ QPDFObjectHandle::getName()
612 bool 684 bool
613 QPDFObjectHandle::getValueAsName(std::string& value) 685 QPDFObjectHandle::getValueAsName(std::string& value)
614 { 686 {
615 - if (!isName()) { 687 + auto name = asName();
  688 + if (name == nullptr) {
616 return false; 689 return false;
617 } 690 }
618 - value = dynamic_cast<QPDF_Name*>(obj.get())->getName(); 691 + value = name->getName();
619 return true; 692 return true;
620 } 693 }
621 694
@@ -624,8 +697,9 @@ QPDFObjectHandle::getValueAsName(std::string&amp; value) @@ -624,8 +697,9 @@ QPDFObjectHandle::getValueAsName(std::string&amp; value)
624 std::string 697 std::string
625 QPDFObjectHandle::getStringValue() 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 } else { 703 } else {
630 typeWarning("string", "returning empty string"); 704 typeWarning("string", "returning empty string");
631 QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); 705 QTC::TC("qpdf", "QPDFObjectHandle string returning empty string");
@@ -636,18 +710,20 @@ QPDFObjectHandle::getStringValue() @@ -636,18 +710,20 @@ QPDFObjectHandle::getStringValue()
636 bool 710 bool
637 QPDFObjectHandle::getValueAsString(std::string& value) 711 QPDFObjectHandle::getValueAsString(std::string& value)
638 { 712 {
639 - if (!isString()) { 713 + auto str = asString();
  714 + if (str == nullptr) {
640 return false; 715 return false;
641 } 716 }
642 - value = dynamic_cast<QPDF_String*>(obj.get())->getVal(); 717 + value = str->getVal();
643 return true; 718 return true;
644 } 719 }
645 720
646 std::string 721 std::string
647 QPDFObjectHandle::getUTF8Value() 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 } else { 727 } else {
652 typeWarning("string", "returning empty string"); 728 typeWarning("string", "returning empty string");
653 QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); 729 QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8");
@@ -658,10 +734,11 @@ QPDFObjectHandle::getUTF8Value() @@ -658,10 +734,11 @@ QPDFObjectHandle::getUTF8Value()
658 bool 734 bool
659 QPDFObjectHandle::getValueAsUTF8(std::string& value) 735 QPDFObjectHandle::getValueAsUTF8(std::string& value)
660 { 736 {
661 - if (!isString()) { 737 + auto str = asString();
  738 + if (str == nullptr) {
662 return false; 739 return false;
663 } 740 }
664 - value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val(); 741 + value = str->getUTF8Val();
665 return true; 742 return true;
666 } 743 }
667 744
@@ -670,8 +747,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string&amp; value) @@ -670,8 +747,9 @@ QPDFObjectHandle::getValueAsUTF8(std::string&amp; value)
670 std::string 747 std::string
671 QPDFObjectHandle::getOperatorValue() 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 } else { 753 } else {
676 typeWarning("operator", "returning fake value"); 754 typeWarning("operator", "returning fake value");
677 QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value"); 755 QTC::TC("qpdf", "QPDFObjectHandle operator returning fake value");
@@ -682,18 +760,20 @@ QPDFObjectHandle::getOperatorValue() @@ -682,18 +760,20 @@ QPDFObjectHandle::getOperatorValue()
682 bool 760 bool
683 QPDFObjectHandle::getValueAsOperator(std::string& value) 761 QPDFObjectHandle::getValueAsOperator(std::string& value)
684 { 762 {
685 - if (!isOperator()) { 763 + auto op = asOperator();
  764 + if (op == nullptr) {
686 return false; 765 return false;
687 } 766 }
688 - value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal(); 767 + value = op->getVal();
689 return true; 768 return true;
690 } 769 }
691 770
692 std::string 771 std::string
693 QPDFObjectHandle::getInlineImageValue() 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 } else { 777 } else {
698 typeWarning("inlineimage", "returning empty data"); 778 typeWarning("inlineimage", "returning empty data");
699 QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data"); 779 QTC::TC("qpdf", "QPDFObjectHandle inlineimage returning empty data");
@@ -704,10 +784,11 @@ QPDFObjectHandle::getInlineImageValue() @@ -704,10 +784,11 @@ QPDFObjectHandle::getInlineImageValue()
704 bool 784 bool
705 QPDFObjectHandle::getValueAsInlineImage(std::string& value) 785 QPDFObjectHandle::getValueAsInlineImage(std::string& value)
706 { 786 {
707 - if (!isInlineImage()) { 787 + auto image = asInlineImage();
  788 + if (image == nullptr) {
708 return false; 789 return false;
709 } 790 }
710 - value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal(); 791 + value = image->getVal();
711 return true; 792 return true;
712 } 793 }
713 794
@@ -722,8 +803,9 @@ QPDFObjectHandle::aitems() @@ -722,8 +803,9 @@ QPDFObjectHandle::aitems()
722 int 803 int
723 QPDFObjectHandle::getArrayNItems() 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 } else { 809 } else {
728 typeWarning("array", "treating as empty"); 810 typeWarning("array", "treating as empty");
729 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty"); 811 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty");
@@ -735,11 +817,12 @@ QPDFObjectHandle @@ -735,11 +817,12 @@ QPDFObjectHandle
735 QPDFObjectHandle::getArrayItem(int n) 817 QPDFObjectHandle::getArrayItem(int n)
736 { 818 {
737 QPDFObjectHandle result; 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 } else { 823 } else {
741 result = newNull(); 824 result = newNull();
742 - if (isArray()) { 825 + if (array) {
743 objectWarning("returning null for out of bounds array access"); 826 objectWarning("returning null for out of bounds array access");
744 QTC::TC("qpdf", "QPDFObjectHandle array bounds"); 827 QTC::TC("qpdf", "QPDFObjectHandle array bounds");
745 } else { 828 } else {
@@ -748,7 +831,7 @@ QPDFObjectHandle::getArrayItem(int n) @@ -748,7 +831,7 @@ QPDFObjectHandle::getArrayItem(int n)
748 } 831 }
749 QPDF* context = nullptr; 832 QPDF* context = nullptr;
750 std::string description; 833 std::string description;
751 - if (this->obj->getDescription(context, description)) { 834 + if (obj->getDescription(context, description)) {
752 result.setObjectDescription( 835 result.setObjectDescription(
753 context, 836 context,
754 description + " -> null returned from invalid array access"); 837 description + " -> null returned from invalid array access");
@@ -760,14 +843,12 @@ QPDFObjectHandle::getArrayItem(int n) @@ -760,14 +843,12 @@ QPDFObjectHandle::getArrayItem(int n)
760 bool 843 bool
761 QPDFObjectHandle::isRectangle() 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 return false; 848 return false;
768 } 849 }
769 for (int i = 0; i < 4; ++i) { 850 for (int i = 0; i < 4; ++i) {
770 - if (!getArrayItem(i).isNumber()) { 851 + if (!array->getItem(i).isNumber()) {
771 return false; 852 return false;
772 } 853 }
773 } 854 }
@@ -777,14 +858,12 @@ QPDFObjectHandle::isRectangle() @@ -777,14 +858,12 @@ QPDFObjectHandle::isRectangle()
777 bool 858 bool
778 QPDFObjectHandle::isMatrix() 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 return false; 863 return false;
785 } 864 }
786 for (int i = 0; i < 6; ++i) { 865 for (int i = 0; i < 6; ++i) {
787 - if (!getArrayItem(i).isNumber()) { 866 + if (!array->getItem(i).isNumber()) {
788 return false; 867 return false;
789 } 868 }
790 } 869 }
@@ -796,13 +875,14 @@ QPDFObjectHandle::getArrayAsRectangle() @@ -796,13 +875,14 @@ QPDFObjectHandle::getArrayAsRectangle()
796 { 875 {
797 Rectangle result; 876 Rectangle result;
798 if (isRectangle()) { 877 if (isRectangle()) {
  878 + auto array = asArray();
799 // Rectangle coordinates are always supposed to be llx, lly, 879 // Rectangle coordinates are always supposed to be llx, lly,
800 // urx, ury, but files have been found in the wild where 880 // urx, ury, but files have been found in the wild where
801 // llx > urx or lly > ury. 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 result = Rectangle( 886 result = Rectangle(
807 std::min(i0, i2), 887 std::min(i0, i2),
808 std::min(i1, i3), 888 std::min(i1, i3),
@@ -817,13 +897,14 @@ QPDFObjectHandle::getArrayAsMatrix() @@ -817,13 +897,14 @@ QPDFObjectHandle::getArrayAsMatrix()
817 { 897 {
818 Matrix result; 898 Matrix result;
819 if (isMatrix()) { 899 if (isMatrix()) {
  900 + auto array = asArray();
820 result = Matrix( 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 return result; 909 return result;
829 } 910 }
@@ -832,8 +913,9 @@ std::vector&lt;QPDFObjectHandle&gt; @@ -832,8 +913,9 @@ std::vector&lt;QPDFObjectHandle&gt;
832 QPDFObjectHandle::getArrayAsVector() 913 QPDFObjectHandle::getArrayAsVector()
833 { 914 {
834 std::vector<QPDFObjectHandle> result; 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 } else { 919 } else {
838 typeWarning("array", "treating as empty"); 920 typeWarning("array", "treating as empty");
839 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector"); 921 QTC::TC("qpdf", "QPDFObjectHandle array treating as empty vector");
@@ -846,9 +928,10 @@ QPDFObjectHandle::getArrayAsVector() @@ -846,9 +928,10 @@ QPDFObjectHandle::getArrayAsVector()
846 void 928 void
847 QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item) 929 QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const& item)
848 { 930 {
849 - if (isArray()) { 931 + auto array = asArray();
  932 + if (array) {
850 checkOwnership(item); 933 checkOwnership(item);
851 - dynamic_cast<QPDF_Array*>(obj.get())->setItem(n, item); 934 + array->setItem(n, item);
852 } else { 935 } else {
853 typeWarning("array", "ignoring attempt to set item"); 936 typeWarning("array", "ignoring attempt to set item");
854 QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item"); 937 QTC::TC("qpdf", "QPDFObjectHandle array ignoring set item");
@@ -858,11 +941,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const&amp; item) @@ -858,11 +941,12 @@ QPDFObjectHandle::setArrayItem(int n, QPDFObjectHandle const&amp; item)
858 void 941 void
859 QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items) 942 QPDFObjectHandle::setArrayFromVector(std::vector<QPDFObjectHandle> const& items)
860 { 943 {
861 - if (isArray()) { 944 + auto array = asArray();
  945 + if (array) {
862 for (auto const& item: items) { 946 for (auto const& item: items) {
863 checkOwnership(item); 947 checkOwnership(item);
864 } 948 }
865 - dynamic_cast<QPDF_Array*>(obj.get())->setFromVector(items); 949 + array->setFromVector(items);
866 } else { 950 } else {
867 typeWarning("array", "ignoring attempt to replace items"); 951 typeWarning("array", "ignoring attempt to replace items");
868 QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items"); 952 QTC::TC("qpdf", "QPDFObjectHandle array ignoring replace items");
@@ -872,8 +956,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector&lt;QPDFObjectHandle&gt; const&amp; items) @@ -872,8 +956,9 @@ QPDFObjectHandle::setArrayFromVector(std::vector&lt;QPDFObjectHandle&gt; const&amp; items)
872 void 956 void
873 QPDFObjectHandle::insertItem(int at, QPDFObjectHandle const& item) 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 } else { 962 } else {
878 typeWarning("array", "ignoring attempt to insert item"); 963 typeWarning("array", "ignoring attempt to insert item");
879 QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item"); 964 QTC::TC("qpdf", "QPDFObjectHandle array ignoring insert item");
@@ -890,9 +975,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const&amp; item) @@ -890,9 +975,10 @@ QPDFObjectHandle::insertItemAndGetNew(int at, QPDFObjectHandle const&amp; item)
890 void 975 void
891 QPDFObjectHandle::appendItem(QPDFObjectHandle const& item) 976 QPDFObjectHandle::appendItem(QPDFObjectHandle const& item)
892 { 977 {
893 - if (isArray()) { 978 + auto array = asArray();
  979 + if (array) {
894 checkOwnership(item); 980 checkOwnership(item);
895 - dynamic_cast<QPDF_Array*>(obj.get())->appendItem(item); 981 + array->appendItem(item);
896 } else { 982 } else {
897 typeWarning("array", "ignoring attempt to append item"); 983 typeWarning("array", "ignoring attempt to append item");
898 QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item"); 984 QTC::TC("qpdf", "QPDFObjectHandle array ignoring append item");
@@ -909,10 +995,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const&amp; item) @@ -909,10 +995,11 @@ QPDFObjectHandle::appendItemAndGetNew(QPDFObjectHandle const&amp; item)
909 void 995 void
910 QPDFObjectHandle::eraseItem(int at) 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 } else { 1001 } else {
915 - if (isArray()) { 1002 + if (array) {
916 objectWarning("ignoring attempt to erase out of bounds array item"); 1003 objectWarning("ignoring attempt to erase out of bounds array item");
917 QTC::TC("qpdf", "QPDFObjectHandle erase array bounds"); 1004 QTC::TC("qpdf", "QPDFObjectHandle erase array bounds");
918 } else { 1005 } else {
@@ -926,8 +1013,9 @@ QPDFObjectHandle @@ -926,8 +1013,9 @@ QPDFObjectHandle
926 QPDFObjectHandle::eraseItemAndGetOld(int at) 1013 QPDFObjectHandle::eraseItemAndGetOld(int at)
927 { 1014 {
928 auto result = QPDFObjectHandle::newNull(); 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 eraseItem(at); 1020 eraseItem(at);
933 return result; 1021 return result;
@@ -944,8 +1032,9 @@ QPDFObjectHandle::ditems() @@ -944,8 +1032,9 @@ QPDFObjectHandle::ditems()
944 bool 1032 bool
945 QPDFObjectHandle::hasKey(std::string const& key) 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 } else { 1038 } else {
950 typeWarning( 1039 typeWarning(
951 "dictionary", "returning false for a key containment request"); 1040 "dictionary", "returning false for a key containment request");
@@ -958,15 +1047,16 @@ QPDFObjectHandle @@ -958,15 +1047,16 @@ QPDFObjectHandle
958 QPDFObjectHandle::getKey(std::string const& key) 1047 QPDFObjectHandle::getKey(std::string const& key)
959 { 1048 {
960 QPDFObjectHandle result; 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 } else { 1053 } else {
964 typeWarning("dictionary", "returning null for attempted key retrieval"); 1054 typeWarning("dictionary", "returning null for attempted key retrieval");
965 QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey"); 1055 QTC::TC("qpdf", "QPDFObjectHandle dictionary null for getKey");
966 result = newNull(); 1056 result = newNull();
967 QPDF* qpdf = nullptr; 1057 QPDF* qpdf = nullptr;
968 std::string description; 1058 std::string description;
969 - if (this->obj->getDescription(qpdf, description)) { 1059 + if (obj->getDescription(qpdf, description)) {
970 result.setObjectDescription( 1060 result.setObjectDescription(
971 qpdf, 1061 qpdf,
972 (description + " -> null returned from getting key " + key + 1062 (description + " -> null returned from getting key " + key +
@@ -986,8 +1076,9 @@ std::set&lt;std::string&gt; @@ -986,8 +1076,9 @@ std::set&lt;std::string&gt;
986 QPDFObjectHandle::getKeys() 1076 QPDFObjectHandle::getKeys()
987 { 1077 {
988 std::set<std::string> result; 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 } else { 1082 } else {
992 typeWarning("dictionary", "treating as empty"); 1083 typeWarning("dictionary", "treating as empty");
993 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys"); 1084 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty set for getKeys");
@@ -999,8 +1090,9 @@ std::map&lt;std::string, QPDFObjectHandle&gt; @@ -999,8 +1090,9 @@ std::map&lt;std::string, QPDFObjectHandle&gt;
999 QPDFObjectHandle::getDictAsMap() 1090 QPDFObjectHandle::getDictAsMap()
1000 { 1091 {
1001 std::map<std::string, QPDFObjectHandle> result; 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 } else { 1096 } else {
1005 typeWarning("dictionary", "treating as empty"); 1097 typeWarning("dictionary", "treating as empty");
1006 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap"); 1098 QTC::TC("qpdf", "QPDFObjectHandle dictionary empty map for asMap");
@@ -1191,9 +1283,10 @@ void @@ -1191,9 +1283,10 @@ void
1191 QPDFObjectHandle::replaceKey( 1283 QPDFObjectHandle::replaceKey(
1192 std::string const& key, QPDFObjectHandle const& value) 1284 std::string const& key, QPDFObjectHandle const& value)
1193 { 1285 {
1194 - if (isDictionary()) { 1286 + auto dict = asDictionary();
  1287 + if (dict) {
1195 checkOwnership(value); 1288 checkOwnership(value);
1196 - dynamic_cast<QPDF_Dictionary*>(obj.get())->replaceKey(key, value); 1289 + dict->replaceKey(key, value);
1197 } else { 1290 } else {
1198 typeWarning("dictionary", "ignoring key replacement request"); 1291 typeWarning("dictionary", "ignoring key replacement request");
1199 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey"); 1292 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring replaceKey");
@@ -1220,8 +1313,9 @@ QPDFObjectHandle::replaceKeyAndGetOld( @@ -1220,8 +1313,9 @@ QPDFObjectHandle::replaceKeyAndGetOld(
1220 void 1313 void
1221 QPDFObjectHandle::removeKey(std::string const& key) 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 } else { 1319 } else {
1226 typeWarning("dictionary", "ignoring key removal request"); 1320 typeWarning("dictionary", "ignoring key removal request");
1227 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey"); 1321 QTC::TC("qpdf", "QPDFObjectHandle dictionary ignoring removeKey");
@@ -1232,8 +1326,9 @@ QPDFObjectHandle @@ -1232,8 +1326,9 @@ QPDFObjectHandle
1232 QPDFObjectHandle::removeKeyAndGetOld(std::string const& key) 1326 QPDFObjectHandle::removeKeyAndGetOld(std::string const& key)
1233 { 1327 {
1234 auto result = QPDFObjectHandle::newNull(); 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 removeKey(key); 1333 removeKey(key);
1239 return result; 1334 return result;
@@ -1250,50 +1345,43 @@ QPDFObjectHandle::replaceOrRemoveKey( @@ -1250,50 +1345,43 @@ QPDFObjectHandle::replaceOrRemoveKey(
1250 QPDFObjectHandle 1345 QPDFObjectHandle
1251 QPDFObjectHandle::getDict() 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 void 1351 void
1258 QPDFObjectHandle::setFilterOnWrite(bool val) 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 bool 1357 bool
1265 QPDFObjectHandle::getFilterOnWrite() 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 bool 1363 bool
1272 QPDFObjectHandle::isDataModified() 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 void 1369 void
1279 QPDFObjectHandle::replaceDict(QPDFObjectHandle const& new_dict) 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 std::shared_ptr<Buffer> 1375 std::shared_ptr<Buffer>
1286 QPDFObjectHandle::getStreamData(qpdf_stream_decode_level_e level) 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 std::shared_ptr<Buffer> 1381 std::shared_ptr<Buffer>
1293 QPDFObjectHandle::getRawStreamData() 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 bool 1387 bool
@@ -1305,8 +1393,7 @@ QPDFObjectHandle::pipeStreamData( @@ -1305,8 +1393,7 @@ QPDFObjectHandle::pipeStreamData(
1305 bool suppress_warnings, 1393 bool suppress_warnings,
1306 bool will_retry) 1394 bool will_retry)
1307 { 1395 {
1308 - assertStream();  
1309 - return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( 1396 + return asStreamWithAssert()->pipeStreamData(
1310 p, 1397 p,
1311 filtering_attempted, 1398 filtering_attempted,
1312 encode_flags, 1399 encode_flags,
@@ -1323,9 +1410,8 @@ QPDFObjectHandle::pipeStreamData( @@ -1323,9 +1410,8 @@ QPDFObjectHandle::pipeStreamData(
1323 bool suppress_warnings, 1410 bool suppress_warnings,
1324 bool will_retry) 1411 bool will_retry)
1325 { 1412 {
1326 - assertStream();  
1327 bool filtering_attempted; 1413 bool filtering_attempted;
1328 - dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData( 1414 + asStreamWithAssert()->pipeStreamData(
1329 p, 1415 p,
1330 &filtering_attempted, 1416 &filtering_attempted,
1331 encode_flags, 1417 encode_flags,
@@ -1359,9 +1445,7 @@ QPDFObjectHandle::replaceStreamData( @@ -1359,9 +1445,7 @@ QPDFObjectHandle::replaceStreamData(
1359 QPDFObjectHandle const& filter, 1445 QPDFObjectHandle const& filter,
1360 QPDFObjectHandle const& decode_parms) 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 void 1451 void
@@ -1370,14 +1454,12 @@ QPDFObjectHandle::replaceStreamData( @@ -1370,14 +1454,12 @@ QPDFObjectHandle::replaceStreamData(
1370 QPDFObjectHandle const& filter, 1454 QPDFObjectHandle const& filter,
1371 QPDFObjectHandle const& decode_parms) 1455 QPDFObjectHandle const& decode_parms)
1372 { 1456 {
1373 - assertStream();  
1374 auto b = std::make_shared<Buffer>(data.length()); 1457 auto b = std::make_shared<Buffer>(data.length());
1375 unsigned char* bp = b->getBuffer(); 1458 unsigned char* bp = b->getBuffer();
1376 if (bp) { 1459 if (bp) {
1377 memcpy(bp, data.c_str(), data.length()); 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 void 1465 void
@@ -1386,9 +1468,7 @@ QPDFObjectHandle::replaceStreamData( @@ -1386,9 +1468,7 @@ QPDFObjectHandle::replaceStreamData(
1386 QPDFObjectHandle const& filter, 1468 QPDFObjectHandle const& filter,
1387 QPDFObjectHandle const& decode_parms) 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 namespace 1474 namespace
@@ -1437,11 +1517,9 @@ QPDFObjectHandle::replaceStreamData( @@ -1437,11 +1517,9 @@ QPDFObjectHandle::replaceStreamData(
1437 QPDFObjectHandle const& filter, 1517 QPDFObjectHandle const& filter,
1438 QPDFObjectHandle const& decode_parms) 1518 QPDFObjectHandle const& decode_parms)
1439 { 1519 {
1440 - assertStream();  
1441 auto sdp = 1520 auto sdp =
1442 std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); 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 void 1525 void
@@ -1450,11 +1528,9 @@ QPDFObjectHandle::replaceStreamData( @@ -1450,11 +1528,9 @@ QPDFObjectHandle::replaceStreamData(
1450 QPDFObjectHandle const& filter, 1528 QPDFObjectHandle const& filter,
1451 QPDFObjectHandle const& decode_parms) 1529 QPDFObjectHandle const& decode_parms)
1452 { 1530 {
1453 - assertStream();  
1454 auto sdp = 1531 auto sdp =
1455 std::shared_ptr<StreamDataProvider>(new FunctionProvider(provider)); 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 std::map<std::string, QPDFObjectHandle> 1536 std::map<std::string, QPDFObjectHandle>
@@ -1469,10 +1545,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( @@ -1469,10 +1545,11 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
1469 { 1545 {
1470 all_description = description; 1546 all_description = description;
1471 std::vector<QPDFObjectHandle> result; 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 for (int i = 0; i < n_items; ++i) { 1551 for (int i = 0; i < n_items; ++i) {
1475 - QPDFObjectHandle item = getArrayItem(i); 1552 + QPDFObjectHandle item = array->getItem(i);
1476 if (item.isStream()) { 1553 if (item.isStream()) {
1477 result.push_back(item); 1554 result.push_back(item);
1478 } else { 1555 } else {
@@ -1649,8 +1726,9 @@ QPDFObjectHandle::unparseResolved() @@ -1649,8 +1726,9 @@ QPDFObjectHandle::unparseResolved()
1649 std::string 1726 std::string
1650 QPDFObjectHandle::unparseBinary() 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 } else { 1732 } else {
1655 return unparse(); 1733 return unparse();
1656 } 1734 }
@@ -1666,7 +1744,7 @@ QPDFObjectHandle::getJSON(bool dereference_indirect) @@ -1666,7 +1744,7 @@ QPDFObjectHandle::getJSON(bool dereference_indirect)
1666 JSON 1744 JSON
1667 QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) 1745 QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1668 { 1746 {
1669 - if ((!dereference_indirect) && this->isIndirect()) { 1747 + if ((!dereference_indirect) && isIndirect()) {
1670 return JSON::makeString(unparse()); 1748 return JSON::makeString(unparse());
1671 } else if (!dereference()) { 1749 } else if (!dereference()) {
1672 throw std::logic_error( 1750 throw std::logic_error(
@@ -1675,7 +1753,7 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect) @@ -1675,7 +1753,7 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
1675 throw std::logic_error( 1753 throw std::logic_error(
1676 "QPDFObjectHandle: attempting to unparse a reserved object"); 1754 "QPDFObjectHandle: attempting to unparse a reserved object");
1677 } else { 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,8 +1765,7 @@ QPDFObjectHandle::getStreamJSON(
1687 Pipeline* p, 1765 Pipeline* p,
1688 std::string const& data_filename) 1766 std::string const& data_filename)
1689 { 1767 {
1690 - assertStream();  
1691 - return dynamic_cast<QPDF_Stream*>(obj.get())->getStreamJSON( 1768 + return asStreamWithAssert()->getStreamJSON(
1692 json_version, json_data, decode_level, p, data_filename); 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,8 +1985,7 @@ QPDFObjectHandle::addContentTokenFilter(std::shared_ptr&lt;TokenFilter&gt; filter)
1908 void 1985 void
1909 QPDFObjectHandle::addTokenFilter(std::shared_ptr<TokenFilter> filter) 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 QPDFObjectHandle 1991 QPDFObjectHandle
@@ -1946,7 +2022,6 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const&amp; og) @@ -1946,7 +2022,6 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const&amp; og)
1946 QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid"); 2022 QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid");
1947 return newNull(); 2023 return newNull();
1948 } 2024 }
1949 -  
1950 return QPDFObjectHandle(qpdf, og, QPDF_Unresolved::create()); 2025 return QPDFObjectHandle(qpdf, og, QPDF_Unresolved::create());
1951 } 2026 }
1952 2027
@@ -2119,8 +2194,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf) @@ -2119,8 +2194,7 @@ QPDFObjectHandle::newStream(QPDF* qpdf)
2119 QPDFObjectHandle stream_dict = newDictionary(); 2194 QPDFObjectHandle stream_dict = newDictionary();
2120 QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle( 2195 QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle(
2121 QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0))); 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 stream->setObjGen(result.getObjGen()); 2198 stream->setObjGen(result.getObjGen());
2125 return result; 2199 return result;
2126 } 2200 }
@@ -2248,9 +2322,10 @@ QPDFObjectHandle::copyObject( @@ -2248,9 +2322,10 @@ QPDFObjectHandle::copyObject(
2248 new_obj = obj->shallowCopy(); 2322 new_obj = obj->shallowCopy();
2249 } else if (isArray()) { 2323 } else if (isArray()) {
2250 std::vector<QPDFObjectHandle> items; 2324 std::vector<QPDFObjectHandle> items;
2251 - int n = getArrayNItems(); 2325 + auto array = asArray();
  2326 + int n = array->getNItems();
2252 for (int i = 0; i < n; ++i) { 2327 for (int i = 0; i < n; ++i) {
2253 - items.push_back(getArrayItem(i)); 2328 + items.push_back(array->getItem(i));
2254 if ((!first_level_only) && 2329 if ((!first_level_only) &&
2255 (cross_indirect || (!items.back().isIndirect()))) { 2330 (cross_indirect || (!items.back().isIndirect()))) {
2256 items.back().copyObject( 2331 items.back().copyObject(
@@ -2260,8 +2335,9 @@ QPDFObjectHandle::copyObject( @@ -2260,8 +2335,9 @@ QPDFObjectHandle::copyObject(
2260 new_obj = QPDF_Array::create(items); 2335 new_obj = QPDF_Array::create(items);
2261 } else if (isDictionary()) { 2336 } else if (isDictionary()) {
2262 std::map<std::string, QPDFObjectHandle> items; 2337 std::map<std::string, QPDFObjectHandle> items;
  2338 + auto dict = asDictionary();
2263 for (auto const& key: getKeys()) { 2339 for (auto const& key: getKeys()) {
2264 - items[key] = getKey(key); 2340 + items[key] = dict->getKey(key);
2265 if ((!first_level_only) && 2341 if ((!first_level_only) &&
2266 (cross_indirect || (!items[key].isIndirect()))) { 2342 (cross_indirect || (!items[key].isIndirect()))) {
2267 items[key].copyObject( 2343 items[key].copyObject(
@@ -2309,7 +2385,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams) @@ -2309,7 +2385,7 @@ QPDFObjectHandle::makeDirect(bool allow_streams)
2309 void 2385 void
2310 QPDFObjectHandle::assertInitialized() const 2386 QPDFObjectHandle::assertInitialized() const
2311 { 2387 {
2312 - if (!this->initialized) { 2388 + if (!initialized) {
2313 throw std::logic_error("operation attempted on uninitialized " 2389 throw std::logic_error("operation attempted on uninitialized "
2314 "QPDFObjectHandle"); 2390 "QPDFObjectHandle");
2315 } 2391 }
@@ -2551,7 +2627,6 @@ QPDFObjectHandle::dereference() @@ -2551,7 +2627,6 @@ QPDFObjectHandle::dereference()
2551 (getObjectID() && 2627 (getObjectID() &&
2552 QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj))) { 2628 QPDF::Resolver::objectChanged(this->qpdf, getObjGen(), this->obj))) {
2553 this->obj = QPDF::Resolver::resolve(this->qpdf, getObjGen()); 2629 this->obj = QPDF::Resolver::resolve(this->qpdf, getObjGen());
2554 -  
2555 } 2630 }
2556 return true; 2631 return true;
2557 } 2632 }
libqpdf/QPDF_Reserved.cc
@@ -17,14 +17,16 @@ QPDF_Reserved::shallowCopy() @@ -17,14 +17,16 @@ QPDF_Reserved::shallowCopy()
17 std::string 17 std::string
18 QPDF_Reserved::unparse() 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 return ""; 22 return "";
22 } 23 }
23 24
24 JSON 25 JSON
25 QPDF_Reserved::getJSON(int json_version) 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 return JSON::makeNull(); 30 return JSON::makeNull();
29 } 31 }
30 32