From e58b1174c7f8b617a1253e70df9b95a1cac10fab Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 5 Feb 2022 14:46:25 +0000 Subject: Add new QPDFObjectHandle::getValueAs... accessors --- include/qpdf/QPDFObjectHandle.hh | 25 ++++++++ libqpdf/QPDFObjectHandle.cc | 132 +++++++++++++++++++++++++++++++++++++++ qpdf/qtest/qpdf.test | 6 +- qpdf/test_driver.cc | 97 +++++++++++++++++++++++++++- 4 files changed, 257 insertions(+), 3 deletions(-) diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index c632574e..855c14c2 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -678,6 +678,8 @@ class QPDFObjectHandle // Methods for bool objects QPDF_DLL bool getBoolValue(); + QPDF_DLL + bool getValueAsBool(bool&); // Methods for integer objects. Note: if an integer value is too // big (too far away from zero in either direction) to fit in the @@ -688,29 +690,46 @@ class QPDFObjectHandle QPDF_DLL long long getIntValue(); QPDF_DLL + bool getValueAsInt(long long&); + QPDF_DLL int getIntValueAsInt(); QPDF_DLL + bool getValueAsInt(int&); + QPDF_DLL unsigned long long getUIntValue(); QPDF_DLL + bool getValueAsUInt(unsigned long long&); + QPDF_DLL unsigned int getUIntValueAsUInt(); + QPDF_DLL + bool getValueAsUInt(unsigned int&); // Methods for real objects QPDF_DLL std::string getRealValue(); + QPDF_DLL + bool getValueAsReal(std::string&); // Methods that work for both integer and real objects QPDF_DLL bool isNumber(); QPDF_DLL double getNumericValue(); + QPDF_DLL + bool getValueAsNumber(double&); // Methods for name objects; see also name and array objects QPDF_DLL std::string getName(); + QPDF_DLL + bool getValueAsName(std::string&); // Methods for string objects QPDF_DLL std::string getStringValue(); + QPDF_DLL + bool getValueAsString(std::string&); + // If a string starts with the UTF-16 marker, it is converted from // UTF-16 to UTF-8. Otherwise, it is treated as a string encoded // with PDF Doc Encoding. PDF Doc Encoding is identical to @@ -720,12 +739,18 @@ class QPDFObjectHandle // unmapped. QPDF_DLL std::string getUTF8Value(); + QPDF_DLL + bool getValueAsUTF8(std::string&); // Methods for content stream objects QPDF_DLL std::string getOperatorValue(); QPDF_DLL + bool getValueAsOperator(std::string&); + QPDF_DLL std::string getInlineImageValue(); + QPDF_DLL + bool getValueAsInlineImage(std::string&); // Methods for array objects; see also name and array objects. diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 0bcd816b..d754448f 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -391,6 +391,17 @@ QPDFObjectHandle::getNumericValue() return result; } +bool +QPDFObjectHandle::getValueAsNumber(double& value) +{ + if (! isNumber()) + { + return false; + } + value = getNumericValue(); + return true; +} + bool QPDFObjectHandle::isName() { @@ -536,6 +547,17 @@ QPDFObjectHandle::getBoolValue() } } +bool +QPDFObjectHandle::getValueAsBool(bool& value) +{ + if (! isBool()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + // Integer accessors long long @@ -553,6 +575,17 @@ QPDFObjectHandle::getIntValue() } } +bool +QPDFObjectHandle::getValueAsInt(long long& value) +{ + if (! isInteger()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + int QPDFObjectHandle::getIntValueAsInt() { @@ -581,6 +614,17 @@ QPDFObjectHandle::getIntValueAsInt() return result; } +bool +QPDFObjectHandle::getValueAsInt(int& value) +{ + if (! isInteger()) + { + return false; + } + value = getIntValueAsInt(); + return true; +} + unsigned long long QPDFObjectHandle::getUIntValue() { @@ -600,6 +644,17 @@ QPDFObjectHandle::getUIntValue() return result; } +bool +QPDFObjectHandle::getValueAsUInt(unsigned long long& value) +{ + if (! isInteger()) + { + return false; + } + value = getUIntValue(); + return true; +} + unsigned int QPDFObjectHandle::getUIntValueAsUInt() { @@ -629,6 +684,17 @@ QPDFObjectHandle::getUIntValueAsUInt() return result; } +bool +QPDFObjectHandle::getValueAsUInt(unsigned int& value) +{ + if (! isInteger()) + { + return false; + } + value = getUIntValueAsUInt(); + return true; +} + // Real accessors std::string @@ -646,6 +712,17 @@ QPDFObjectHandle::getRealValue() } } +bool +QPDFObjectHandle::getValueAsReal(std::string& value) +{ + if (! isReal()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + // Name accessors std::string @@ -663,6 +740,17 @@ QPDFObjectHandle::getName() } } +bool +QPDFObjectHandle::getValueAsName(std::string& value) +{ + if (! isName()) + { + return false; + } + value = dynamic_cast(obj.get())->getName(); + return true; +} + // String accessors std::string @@ -680,6 +768,17 @@ QPDFObjectHandle::getStringValue() } } +bool +QPDFObjectHandle::getValueAsString(std::string& value) +{ + if (! isString()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + std::string QPDFObjectHandle::getUTF8Value() { @@ -695,6 +794,17 @@ QPDFObjectHandle::getUTF8Value() } } +bool +QPDFObjectHandle::getValueAsUTF8(std::string& value) +{ + if (! isString()) + { + return false; + } + value = dynamic_cast(obj.get())->getUTF8Val(); + return true; +} + // Operator and Inline Image accessors std::string @@ -712,6 +822,17 @@ QPDFObjectHandle::getOperatorValue() } } +bool +QPDFObjectHandle::getValueAsOperator(std::string& value) +{ + if (! isOperator()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + std::string QPDFObjectHandle::getInlineImageValue() { @@ -727,6 +848,17 @@ QPDFObjectHandle::getInlineImageValue() } } +bool +QPDFObjectHandle::getValueAsInlineImage(std::string& value) +{ + if (! isInlineImage()) + { + return false; + } + value = dynamic_cast(obj.get())->getVal(); + return true; +} + // Array accessors QPDFObjectHandle::QPDFArrayItems diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 58d4102f..bf386168 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -3285,7 +3285,7 @@ my @badfiles = ("not a PDF file", # 1 "startxref to space then eof", # 38 ); -$n_tests += @badfiles + 7; +$n_tests += @badfiles + 8; # Test 6 contains errors in the free table consistency, but we no # longer have any consistency check for this since it is not important @@ -3341,6 +3341,10 @@ $td->runtest("integer type checks", {$td->COMMAND => "test_driver 62 minimal.pdf"}, {$td->STRING => "test 62 done\n", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +$td->runtest("getValueAs... accessor checks", + {$td->COMMAND => "test_driver 85 -"}, + {$td->STRING => "test 85 done\n", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); show_ntests(); # ---------- diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 6381d731..8d28184b 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3220,6 +3220,99 @@ static void test_84(QPDF& pdf, char const* arg2) } } +static void test_85(QPDF& pdf, char const* arg2) +{ + // Test QPDFObjectHandle::getValueAs... accessors + + auto oh_b = QPDFObjectHandle::newBool(false); + auto oh_i = QPDFObjectHandle::newInteger(1); + auto oh_i_maxplus = + QPDFObjectHandle::newInteger(QIntC::to_longlong(INT_MAX) + 1LL); + auto oh_i_umaxplus = + QPDFObjectHandle::newInteger(QIntC::to_longlong(UINT_MAX) + 1LL); + auto oh_i_minminus = + QPDFObjectHandle::newInteger(QIntC::to_longlong(INT_MIN) - 1LL); + auto oh_i_neg = QPDFObjectHandle::newInteger(-1); + auto oh_r = QPDFObjectHandle::newReal("42.0"); + auto oh_n = QPDFObjectHandle::newName("/Test"); + auto oh_s = QPDFObjectHandle::newString("/Test"); + auto oh_o = QPDFObjectHandle::newOperator("/Test"); + auto oh_ii = QPDFObjectHandle::newInlineImage("/Test"); + + bool b = true; + assert(oh_b.getValueAsBool(b)); + assert(! b); + assert(! oh_i.getValueAsBool(b)); + assert(! b); + long long li = 0LL; + assert(oh_i.getValueAsInt(li)); + assert(li == 1LL); + assert(! oh_b.getValueAsInt(li)); + assert(li == 1LL); + int i = 0; + assert(oh_i.getValueAsInt(i)); + assert(i == 1); + assert(! oh_b.getValueAsInt(i)); + assert(i == 1); + assert(oh_i_maxplus.getValueAsInt(i)); + assert(i == INT_MAX); + assert(oh_i_minminus.getValueAsInt(i)); + assert(i == INT_MIN); + unsigned long long uli = 0U; + assert(oh_i.getValueAsUInt(uli)); + assert(uli == 1u); + assert(! oh_b.getValueAsUInt(uli)); + assert(uli == 1u); + assert(oh_i_neg.getValueAsUInt(uli)); + assert(uli == 0u); + unsigned int ui = 0U; + assert(oh_i.getValueAsUInt(ui)); + assert(ui == 1u); + assert(! oh_b.getValueAsUInt(ui)); + assert(ui == 1u); + assert(oh_i_neg.getValueAsUInt(ui)); + assert(ui == 0u); + assert(oh_i_umaxplus.getValueAsUInt(ui)); + assert(ui == UINT_MAX); + std::string s = "0"; + assert(oh_r.getValueAsReal(s)); + assert(s == "42.0"); + assert(! oh_i.getValueAsReal(s)); + assert(s == "42.0"); + double num = 0.0; + assert(oh_i.getValueAsNumber(num)); + assert(abs(num - 1.0) < 1e-100); + assert(oh_r.getValueAsNumber(num)); + assert(abs(num - 42.0) < 1e-100); + assert(! oh_b.getValueAsNumber(num)); + assert(abs(num - 42.0) < 1e-100); + s = ""; + assert(oh_n.getValueAsName(s)); + assert(s == "/Test") ; + assert(! oh_r.getValueAsName(s)); + assert(s == "/Test"); + s = ""; + assert(oh_s.getValueAsUTF8(s)); + assert(s == "/Test"); + assert(! oh_r.getValueAsUTF8(s)); + assert(s == "/Test"); + s = ""; + assert(oh_s.getValueAsUTF8(s)); + assert(s == "/Test"); + assert(! oh_r.getValueAsUTF8(s)); + assert(s == "/Test"); + s = ""; + assert(oh_o.getValueAsOperator(s)); + assert(s == "/Test"); + assert(! oh_r.getValueAsOperator(s)); + assert(s == "/Test"); + s = ""; + assert(oh_ii.getValueAsInlineImage(s)); + assert(s == "/Test"); + assert(! oh_r.getValueAsInlineImage(s)); + assert(s == "/Test"); +} + void runtest(int n, char const* filename1, char const* arg2) { // 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) pdf.processMemoryFile((std::string(filename1) + ".pdf").c_str(), p, size); } - else if ((n == 61) || (n == 81) || (n == 83) || (n == 84)) + else if ((n == 61) || (n == 81) || (n == 83) || (n == 84) || (n == 85)) { // Ignore filename argument entirely } @@ -3334,7 +3427,7 @@ void runtest(int n, char const* filename1, char const* arg2) {72, test_72}, {73, test_73}, {74, test_74}, {75, test_75}, {76, test_76}, {77, test_77}, {78, test_78}, {79, test_79}, {80, test_80}, {81, test_81}, {82, test_82}, {83, test_83}, - {84, test_84}, + {84, test_84}, {85, test_85}, }; auto fn = test_functions.find(n); -- cgit v1.2.3-54-g00ecf