Commit e58b1174c7f8b617a1253e70df9b95a1cac10fab
Committed by
Jay Berkenbilt
1 parent
cfaa2de8
Add new QPDFObjectHandle::getValueAs... accessors
Showing
4 changed files
with
257 additions
and
3 deletions
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 = ("not a PDF file", # 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->runtest("integer type checks", |
| 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& 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); | ... | ... |