Commit e58b1174c7f8b617a1253e70df9b95a1cac10fab

Authored by m-holger
Committed by Jay Berkenbilt
1 parent cfaa2de8

Add new QPDFObjectHandle::getValueAs... accessors

include/qpdf/QPDFObjectHandle.hh
... ... @@ -678,6 +678,8 @@ class QPDFObjectHandle
678 678 // Methods for bool objects
679 679 QPDF_DLL
680 680 bool getBoolValue();
  681 + QPDF_DLL
  682 + bool getValueAsBool(bool&);
681 683  
682 684 // Methods for integer objects. Note: if an integer value is too
683 685 // big (too far away from zero in either direction) to fit in the
... ... @@ -688,29 +690,46 @@ class QPDFObjectHandle
688 690 QPDF_DLL
689 691 long long getIntValue();
690 692 QPDF_DLL
  693 + bool getValueAsInt(long long&);
  694 + QPDF_DLL
691 695 int getIntValueAsInt();
692 696 QPDF_DLL
  697 + bool getValueAsInt(int&);
  698 + QPDF_DLL
693 699 unsigned long long getUIntValue();
694 700 QPDF_DLL
  701 + bool getValueAsUInt(unsigned long long&);
  702 + QPDF_DLL
695 703 unsigned int getUIntValueAsUInt();
  704 + QPDF_DLL
  705 + bool getValueAsUInt(unsigned int&);
696 706  
697 707 // Methods for real objects
698 708 QPDF_DLL
699 709 std::string getRealValue();
  710 + QPDF_DLL
  711 + bool getValueAsReal(std::string&);
700 712  
701 713 // Methods that work for both integer and real objects
702 714 QPDF_DLL
703 715 bool isNumber();
704 716 QPDF_DLL
705 717 double getNumericValue();
  718 + QPDF_DLL
  719 + bool getValueAsNumber(double&);
706 720  
707 721 // Methods for name objects; see also name and array objects
708 722 QPDF_DLL
709 723 std::string getName();
  724 + QPDF_DLL
  725 + bool getValueAsName(std::string&);
710 726  
711 727 // Methods for string objects
712 728 QPDF_DLL
713 729 std::string getStringValue();
  730 + QPDF_DLL
  731 + bool getValueAsString(std::string&);
  732 +
714 733 // If a string starts with the UTF-16 marker, it is converted from
715 734 // UTF-16 to UTF-8. Otherwise, it is treated as a string encoded
716 735 // with PDF Doc Encoding. PDF Doc Encoding is identical to
... ... @@ -720,12 +739,18 @@ class QPDFObjectHandle
720 739 // unmapped.
721 740 QPDF_DLL
722 741 std::string getUTF8Value();
  742 + QPDF_DLL
  743 + bool getValueAsUTF8(std::string&);
723 744  
724 745 // Methods for content stream objects
725 746 QPDF_DLL
726 747 std::string getOperatorValue();
727 748 QPDF_DLL
  749 + bool getValueAsOperator(std::string&);
  750 + QPDF_DLL
728 751 std::string getInlineImageValue();
  752 + QPDF_DLL
  753 + bool getValueAsInlineImage(std::string&);
729 754  
730 755 // Methods for array objects; see also name and array objects.
731 756  
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -392,6 +392,17 @@ QPDFObjectHandle::getNumericValue()
392 392 }
393 393  
394 394 bool
  395 +QPDFObjectHandle::getValueAsNumber(double& value)
  396 +{
  397 + if (! isNumber())
  398 + {
  399 + return false;
  400 + }
  401 + value = getNumericValue();
  402 + return true;
  403 +}
  404 +
  405 +bool
395 406 QPDFObjectHandle::isName()
396 407 {
397 408 if (! this->initialized)
... ... @@ -536,6 +547,17 @@ QPDFObjectHandle::getBoolValue()
536 547 }
537 548 }
538 549  
  550 +bool
  551 +QPDFObjectHandle::getValueAsBool(bool& value)
  552 +{
  553 + if (! isBool())
  554 + {
  555 + return false;
  556 + }
  557 + value = dynamic_cast<QPDF_Bool*>(obj.get())->getVal();
  558 + return true;
  559 +}
  560 +
539 561 // Integer accessors
540 562  
541 563 long long
... ... @@ -553,6 +575,17 @@ QPDFObjectHandle::getIntValue()
553 575 }
554 576 }
555 577  
  578 +bool
  579 +QPDFObjectHandle::getValueAsInt(long long& value)
  580 +{
  581 + if (! isInteger())
  582 + {
  583 + return false;
  584 + }
  585 + value = dynamic_cast<QPDF_Integer*>(obj.get())->getVal();
  586 + return true;
  587 +}
  588 +
556 589 int
557 590 QPDFObjectHandle::getIntValueAsInt()
558 591 {
... ... @@ -581,6 +614,17 @@ QPDFObjectHandle::getIntValueAsInt()
581 614 return result;
582 615 }
583 616  
  617 +bool
  618 +QPDFObjectHandle::getValueAsInt(int& value)
  619 +{
  620 + if (! isInteger())
  621 + {
  622 + return false;
  623 + }
  624 + value = getIntValueAsInt();
  625 + return true;
  626 +}
  627 +
584 628 unsigned long long
585 629 QPDFObjectHandle::getUIntValue()
586 630 {
... ... @@ -600,6 +644,17 @@ QPDFObjectHandle::getUIntValue()
600 644 return result;
601 645 }
602 646  
  647 +bool
  648 +QPDFObjectHandle::getValueAsUInt(unsigned long long& value)
  649 +{
  650 + if (! isInteger())
  651 + {
  652 + return false;
  653 + }
  654 + value = getUIntValue();
  655 + return true;
  656 +}
  657 +
603 658 unsigned int
604 659 QPDFObjectHandle::getUIntValueAsUInt()
605 660 {
... ... @@ -629,6 +684,17 @@ QPDFObjectHandle::getUIntValueAsUInt()
629 684 return result;
630 685 }
631 686  
  687 +bool
  688 +QPDFObjectHandle::getValueAsUInt(unsigned int& value)
  689 +{
  690 + if (! isInteger())
  691 + {
  692 + return false;
  693 + }
  694 + value = getUIntValueAsUInt();
  695 + return true;
  696 +}
  697 +
632 698 // Real accessors
633 699  
634 700 std::string
... ... @@ -646,6 +712,17 @@ QPDFObjectHandle::getRealValue()
646 712 }
647 713 }
648 714  
  715 +bool
  716 +QPDFObjectHandle::getValueAsReal(std::string& value)
  717 +{
  718 + if (! isReal())
  719 + {
  720 + return false;
  721 + }
  722 + value = dynamic_cast<QPDF_Real*>(obj.get())->getVal();
  723 + return true;
  724 +}
  725 +
649 726 // Name accessors
650 727  
651 728 std::string
... ... @@ -663,6 +740,17 @@ QPDFObjectHandle::getName()
663 740 }
664 741 }
665 742  
  743 +bool
  744 +QPDFObjectHandle::getValueAsName(std::string& value)
  745 +{
  746 + if (! isName())
  747 + {
  748 + return false;
  749 + }
  750 + value = dynamic_cast<QPDF_Name*>(obj.get())->getName();
  751 + return true;
  752 +}
  753 +
666 754 // String accessors
667 755  
668 756 std::string
... ... @@ -680,6 +768,17 @@ QPDFObjectHandle::getStringValue()
680 768 }
681 769 }
682 770  
  771 +bool
  772 +QPDFObjectHandle::getValueAsString(std::string& value)
  773 +{
  774 + if (! isString())
  775 + {
  776 + return false;
  777 + }
  778 + value = dynamic_cast<QPDF_String*>(obj.get())->getVal();
  779 + return true;
  780 +}
  781 +
683 782 std::string
684 783 QPDFObjectHandle::getUTF8Value()
685 784 {
... ... @@ -695,6 +794,17 @@ QPDFObjectHandle::getUTF8Value()
695 794 }
696 795 }
697 796  
  797 +bool
  798 +QPDFObjectHandle::getValueAsUTF8(std::string& value)
  799 +{
  800 + if (! isString())
  801 + {
  802 + return false;
  803 + }
  804 + value = dynamic_cast<QPDF_String*>(obj.get())->getUTF8Val();
  805 + return true;
  806 +}
  807 +
698 808 // Operator and Inline Image accessors
699 809  
700 810 std::string
... ... @@ -712,6 +822,17 @@ QPDFObjectHandle::getOperatorValue()
712 822 }
713 823 }
714 824  
  825 +bool
  826 +QPDFObjectHandle::getValueAsOperator(std::string& value)
  827 +{
  828 + if (! isOperator())
  829 + {
  830 + return false;
  831 + }
  832 + value = dynamic_cast<QPDF_Operator*>(obj.get())->getVal();
  833 + return true;
  834 +}
  835 +
715 836 std::string
716 837 QPDFObjectHandle::getInlineImageValue()
717 838 {
... ... @@ -727,6 +848,17 @@ QPDFObjectHandle::getInlineImageValue()
727 848 }
728 849 }
729 850  
  851 +bool
  852 +QPDFObjectHandle::getValueAsInlineImage(std::string& value)
  853 +{
  854 + if (! isInlineImage())
  855 + {
  856 + return false;
  857 + }
  858 + value = dynamic_cast<QPDF_InlineImage*>(obj.get())->getVal();
  859 + return true;
  860 +}
  861 +
730 862 // Array accessors
731 863  
732 864 QPDFObjectHandle::QPDFArrayItems
... ...
qpdf/qtest/qpdf.test
... ... @@ -3285,7 +3285,7 @@ my @badfiles = (&quot;not a PDF file&quot;, # 1
3285 3285 "startxref to space then eof", # 38
3286 3286 );
3287 3287  
3288   -$n_tests += @badfiles + 7;
  3288 +$n_tests += @badfiles + 8;
3289 3289  
3290 3290 # Test 6 contains errors in the free table consistency, but we no
3291 3291 # longer have any consistency check for this since it is not important
... ... @@ -3341,6 +3341,10 @@ $td-&gt;runtest(&quot;integer type checks&quot;,
3341 3341 {$td->COMMAND => "test_driver 62 minimal.pdf"},
3342 3342 {$td->STRING => "test 62 done\n", $td->EXIT_STATUS => 0},
3343 3343 $td->NORMALIZE_NEWLINES);
  3344 +$td->runtest("getValueAs... accessor checks",
  3345 + {$td->COMMAND => "test_driver 85 -"},
  3346 + {$td->STRING => "test 85 done\n", $td->EXIT_STATUS => 0},
  3347 + $td->NORMALIZE_NEWLINES);
3344 3348  
3345 3349 show_ntests();
3346 3350 # ----------
... ...
qpdf/test_driver.cc
... ... @@ -3220,6 +3220,99 @@ static void test_84(QPDF&amp; pdf, char const* arg2)
3220 3220 }
3221 3221 }
3222 3222  
  3223 +static void test_85(QPDF& pdf, char const* arg2)
  3224 +{
  3225 + // Test QPDFObjectHandle::getValueAs... accessors
  3226 +
  3227 + auto oh_b = QPDFObjectHandle::newBool(false);
  3228 + auto oh_i = QPDFObjectHandle::newInteger(1);
  3229 + auto oh_i_maxplus =
  3230 + QPDFObjectHandle::newInteger(QIntC::to_longlong(INT_MAX) + 1LL);
  3231 + auto oh_i_umaxplus =
  3232 + QPDFObjectHandle::newInteger(QIntC::to_longlong(UINT_MAX) + 1LL);
  3233 + auto oh_i_minminus =
  3234 + QPDFObjectHandle::newInteger(QIntC::to_longlong(INT_MIN) - 1LL);
  3235 + auto oh_i_neg = QPDFObjectHandle::newInteger(-1);
  3236 + auto oh_r = QPDFObjectHandle::newReal("42.0");
  3237 + auto oh_n = QPDFObjectHandle::newName("/Test");
  3238 + auto oh_s = QPDFObjectHandle::newString("/Test");
  3239 + auto oh_o = QPDFObjectHandle::newOperator("/Test");
  3240 + auto oh_ii = QPDFObjectHandle::newInlineImage("/Test");
  3241 +
  3242 + bool b = true;
  3243 + assert(oh_b.getValueAsBool(b));
  3244 + assert(! b);
  3245 + assert(! oh_i.getValueAsBool(b));
  3246 + assert(! b);
  3247 + long long li = 0LL;
  3248 + assert(oh_i.getValueAsInt(li));
  3249 + assert(li == 1LL);
  3250 + assert(! oh_b.getValueAsInt(li));
  3251 + assert(li == 1LL);
  3252 + int i = 0;
  3253 + assert(oh_i.getValueAsInt(i));
  3254 + assert(i == 1);
  3255 + assert(! oh_b.getValueAsInt(i));
  3256 + assert(i == 1);
  3257 + assert(oh_i_maxplus.getValueAsInt(i));
  3258 + assert(i == INT_MAX);
  3259 + assert(oh_i_minminus.getValueAsInt(i));
  3260 + assert(i == INT_MIN);
  3261 + unsigned long long uli = 0U;
  3262 + assert(oh_i.getValueAsUInt(uli));
  3263 + assert(uli == 1u);
  3264 + assert(! oh_b.getValueAsUInt(uli));
  3265 + assert(uli == 1u);
  3266 + assert(oh_i_neg.getValueAsUInt(uli));
  3267 + assert(uli == 0u);
  3268 + unsigned int ui = 0U;
  3269 + assert(oh_i.getValueAsUInt(ui));
  3270 + assert(ui == 1u);
  3271 + assert(! oh_b.getValueAsUInt(ui));
  3272 + assert(ui == 1u);
  3273 + assert(oh_i_neg.getValueAsUInt(ui));
  3274 + assert(ui == 0u);
  3275 + assert(oh_i_umaxplus.getValueAsUInt(ui));
  3276 + assert(ui == UINT_MAX);
  3277 + std::string s = "0";
  3278 + assert(oh_r.getValueAsReal(s));
  3279 + assert(s == "42.0");
  3280 + assert(! oh_i.getValueAsReal(s));
  3281 + assert(s == "42.0");
  3282 + double num = 0.0;
  3283 + assert(oh_i.getValueAsNumber(num));
  3284 + assert(abs(num - 1.0) < 1e-100);
  3285 + assert(oh_r.getValueAsNumber(num));
  3286 + assert(abs(num - 42.0) < 1e-100);
  3287 + assert(! oh_b.getValueAsNumber(num));
  3288 + assert(abs(num - 42.0) < 1e-100);
  3289 + s = "";
  3290 + assert(oh_n.getValueAsName(s));
  3291 + assert(s == "/Test") ;
  3292 + assert(! oh_r.getValueAsName(s));
  3293 + assert(s == "/Test");
  3294 + s = "";
  3295 + assert(oh_s.getValueAsUTF8(s));
  3296 + assert(s == "/Test");
  3297 + assert(! oh_r.getValueAsUTF8(s));
  3298 + assert(s == "/Test");
  3299 + s = "";
  3300 + assert(oh_s.getValueAsUTF8(s));
  3301 + assert(s == "/Test");
  3302 + assert(! oh_r.getValueAsUTF8(s));
  3303 + assert(s == "/Test");
  3304 + s = "";
  3305 + assert(oh_o.getValueAsOperator(s));
  3306 + assert(s == "/Test");
  3307 + assert(! oh_r.getValueAsOperator(s));
  3308 + assert(s == "/Test");
  3309 + s = "";
  3310 + assert(oh_ii.getValueAsInlineImage(s));
  3311 + assert(s == "/Test");
  3312 + assert(! oh_r.getValueAsInlineImage(s));
  3313 + assert(s == "/Test");
  3314 +}
  3315 +
3223 3316 void runtest(int n, char const* filename1, char const* arg2)
3224 3317 {
3225 3318 // Most tests here are crafted to work on specific files. Look at
... ... @@ -3286,7 +3379,7 @@ void runtest(int n, char const* filename1, char const* arg2)
3286 3379 pdf.processMemoryFile((std::string(filename1) + ".pdf").c_str(),
3287 3380 p, size);
3288 3381 }
3289   - else if ((n == 61) || (n == 81) || (n == 83) || (n == 84))
  3382 + else if ((n == 61) || (n == 81) || (n == 83) || (n == 84) || (n == 85))
3290 3383 {
3291 3384 // Ignore filename argument entirely
3292 3385 }
... ... @@ -3334,7 +3427,7 @@ void runtest(int n, char const* filename1, char const* arg2)
3334 3427 {72, test_72}, {73, test_73}, {74, test_74}, {75, test_75},
3335 3428 {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79},
3336 3429 {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83},
3337   - {84, test_84},
  3430 + {84, test_84}, {85, test_85},
3338 3431 };
3339 3432  
3340 3433 auto fn = test_functions.find(n);
... ...