From 09020472700fa72bb4d093096888ce5b4bc2b0e5 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 1 Nov 2025 12:39:27 +0000 Subject: [PATCH] Introduce private-API `qpdf::String` class and refactor string handling --- libqpdf/QPDFObjectHandle.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- libqpdf/qpdf/QPDFObjectHandle_private.hh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- libqpdf/qpdf/QPDFObject_private.hh | 8 +++++++- qpdf/qpdf.testcov | 2 -- 4 files changed, 118 insertions(+), 37 deletions(-) diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index ca53199..cf0796f 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -999,50 +999,92 @@ QPDFObjectHandle::getValueAsName(std::string& value) const return true; } -// String accessors +// String methods + +QPDFObjectHandle +QPDFObjectHandle::newString(std::string const& str) +{ + return {QPDFObject::create(str)}; +} + +QPDFObjectHandle +QPDFObjectHandle::newUnicodeString(std::string const& utf8_str) +{ + return {QPDF_String::create_utf16(utf8_str)}; +} + +String::String(std::string const& str) : + BaseHandle(QPDFObject::create(str)) +{ +} + +String::String(std::string&& str) : + BaseHandle(QPDFObject::create(std::move(str))) +{ +} + +std::string const& +String::value() const +{ + auto* s = as(); + if (!s) { + throw invalid_error("String"); + } + return s->val; +} + +std::string +String::utf8_value() const +{ + auto* s = as(); + if (!s) { + throw invalid_error("String"); + } + return s->getUTF8Val(); +} std::string QPDFObjectHandle::getStringValue() const { - if (isString()) { - return obj->getStringValue(); - } else { + try { + return String(obj).value(); + } catch (std::invalid_argument&) { typeWarning("string", "returning empty string"); - QTC::TC("qpdf", "QPDFObjectHandle string returning empty string"); - return ""; + return {}; } } bool QPDFObjectHandle::getValueAsString(std::string& value) const { - if (!isString()) { + try { + value = String(obj).value(); + return true; + } catch (std::invalid_argument&) { return false; } - value = obj->getStringValue(); - return true; } std::string QPDFObjectHandle::getUTF8Value() const { - if (auto str = as()) { - return str->getUTF8Val(); - } else { + try { + return String(obj).utf8_value(); + } catch (std::invalid_argument&) { typeWarning("string", "returning empty string"); - QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8"); - return ""; + return {}; } } bool QPDFObjectHandle::getValueAsUTF8(std::string& value) const { - if (auto str = as()) { - value = str->getUTF8Val(); + try { + value = String(obj).utf8_value(); return true; + } catch (std::invalid_argument&) { + return false; } - return false; } // Operator and Inline Image accessors @@ -1718,18 +1760,6 @@ QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_z } QPDFObjectHandle -QPDFObjectHandle::newString(std::string const& str) -{ - return {QPDFObject::create(str)}; -} - -QPDFObjectHandle -QPDFObjectHandle::newUnicodeString(std::string const& utf8_str) -{ - return {QPDF_String::create_utf16(utf8_str)}; -} - -QPDFObjectHandle QPDFObjectHandle::newOperator(std::string const& value) { return {QPDFObject::create(value)}; diff --git a/libqpdf/qpdf/QPDFObjectHandle_private.hh b/libqpdf/qpdf/QPDFObjectHandle_private.hh index 7cb4890..4b03f13 100644 --- a/libqpdf/qpdf/QPDFObjectHandle_private.hh +++ b/libqpdf/qpdf/QPDFObjectHandle_private.hh @@ -412,15 +412,15 @@ namespace qpdf { } - // Return the name value. If the object is not a valid Name, throw a - // std::invalid_argument exception. + // Return the name value. If the object is not a valid Name, throw a std::invalid_argument + // exception. operator std::string() const& { return value(); } - // Return the integer value. If the object is not a valid integer, throw a - // std::invalid_argument exception. + // Return the name value. If the object is not a valid name, throw a std::invalid_argument + // exception. std::string const& value() const; // Return true if object value is equal to the 'rhs' value. Return false if the object is @@ -589,7 +589,54 @@ namespace qpdf void warn(std::string const& message); static std::map filter_abbreviations; - }; + }; // class Stream + + class String final: public BaseHandle + { + public: + String() = default; + String(String const&) = default; + String(String&&) = default; + String& operator=(String const&) = default; + String& operator=(String&&) = default; + ~String() = default; + + explicit String(std::string const&); + explicit String(std::string&&); + + String(QPDFObjectHandle const& oh) : + BaseHandle(oh.type_code() == ::ot_string ? oh : QPDFObjectHandle()) + { + } + + String(QPDFObjectHandle&& oh) : + BaseHandle(oh.type_code() == ::ot_string ? std::move(oh) : QPDFObjectHandle()) + { + } + + // Return the string value. If the object is not a valid string, throw a + // std::invalid_argument exception. + operator std::string() const& + { + return value(); + } + + // Return the string value. If the object is not a valid string, throw a + // std::invalid_argument exception. + std::string const& value() const; + + // Return the string value. If the object is not a valid string, throw a + // std::invalid_argument exception. + std::string utf8_value() const; + + // Return true if object value is equal to the 'rhs' value. Return false if the object is + // not a valid String. + friend bool + operator==(String const& lhs, std::string_view rhs) + { + return lhs && lhs.value() == rhs; + } + }; // class String template T* diff --git a/libqpdf/qpdf/QPDFObject_private.hh b/libqpdf/qpdf/QPDFObject_private.hh index 70ec885..e2048c7 100644 --- a/libqpdf/qpdf/QPDFObject_private.hh +++ b/libqpdf/qpdf/QPDFObject_private.hh @@ -30,6 +30,7 @@ namespace qpdf class Integer; class Name; class Stream; + class String; namespace impl { @@ -261,6 +262,7 @@ class QPDF_String final { friend class QPDFObject; friend class qpdf::BaseHandle; + friend class qpdf::String; friend class qpdf::impl::Writer; public: @@ -270,7 +272,11 @@ class QPDF_String final std::string getUTF8Val() const; private: - QPDF_String(std::string val) : + QPDF_String(std::string const& val) : + val(val) + { + } + QPDF_String(std::string&& val) : val(std::move(val)) { } diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 0c5ea5e..7ef90c4 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -174,8 +174,6 @@ QPDFParser eof in parse 0 QPDFParser eof in parseRemainder 0 QPDFObjectHandle boolean returning false 0 QPDFObjectHandle real returning 0.0 0 -QPDFObjectHandle string returning empty string 0 -QPDFObjectHandle string returning empty utf8 0 QPDFObjectHandle operator returning fake value 0 QPDFObjectHandle inlineimage returning empty data 0 QPDFObjectHandle array treating as empty vector 0 -- libgit2 0.21.4