Commit 09020472700fa72bb4d093096888ce5b4bc2b0e5

Authored by m-holger
1 parent 906034d9

Introduce private-API `qpdf::String` class and refactor string handling

Added `qpdf::String` class to encapsulate string operations. Updated `QPDFObjectHandle` string methods to utilize `qpdf::String`, streamlined empty string handling, and removed redundant test coverage entries.
libqpdf/QPDFObjectHandle.cc
@@ -999,50 +999,92 @@ QPDFObjectHandle::getValueAsName(std::string& value) const @@ -999,50 +999,92 @@ QPDFObjectHandle::getValueAsName(std::string& value) const
999 return true; 999 return true;
1000 } 1000 }
1001 1001
1002 -// String accessors 1002 +// String methods
  1003 +
  1004 +QPDFObjectHandle
  1005 +QPDFObjectHandle::newString(std::string const& str)
  1006 +{
  1007 + return {QPDFObject::create<QPDF_String>(str)};
  1008 +}
  1009 +
  1010 +QPDFObjectHandle
  1011 +QPDFObjectHandle::newUnicodeString(std::string const& utf8_str)
  1012 +{
  1013 + return {QPDF_String::create_utf16(utf8_str)};
  1014 +}
  1015 +
  1016 +String::String(std::string const& str) :
  1017 + BaseHandle(QPDFObject::create<QPDF_String>(str))
  1018 +{
  1019 +}
  1020 +
  1021 +String::String(std::string&& str) :
  1022 + BaseHandle(QPDFObject::create<QPDF_String>(std::move(str)))
  1023 +{
  1024 +}
  1025 +
  1026 +std::string const&
  1027 +String::value() const
  1028 +{
  1029 + auto* s = as<QPDF_String>();
  1030 + if (!s) {
  1031 + throw invalid_error("String");
  1032 + }
  1033 + return s->val;
  1034 +}
  1035 +
  1036 +std::string
  1037 +String::utf8_value() const
  1038 +{
  1039 + auto* s = as<QPDF_String>();
  1040 + if (!s) {
  1041 + throw invalid_error("String");
  1042 + }
  1043 + return s->getUTF8Val();
  1044 +}
1003 1045
1004 std::string 1046 std::string
1005 QPDFObjectHandle::getStringValue() const 1047 QPDFObjectHandle::getStringValue() const
1006 { 1048 {
1007 - if (isString()) {  
1008 - return obj->getStringValue();  
1009 - } else { 1049 + try {
  1050 + return String(obj).value();
  1051 + } catch (std::invalid_argument&) {
1010 typeWarning("string", "returning empty string"); 1052 typeWarning("string", "returning empty string");
1011 - QTC::TC("qpdf", "QPDFObjectHandle string returning empty string");  
1012 - return ""; 1053 + return {};
1013 } 1054 }
1014 } 1055 }
1015 1056
1016 bool 1057 bool
1017 QPDFObjectHandle::getValueAsString(std::string& value) const 1058 QPDFObjectHandle::getValueAsString(std::string& value) const
1018 { 1059 {
1019 - if (!isString()) { 1060 + try {
  1061 + value = String(obj).value();
  1062 + return true;
  1063 + } catch (std::invalid_argument&) {
1020 return false; 1064 return false;
1021 } 1065 }
1022 - value = obj->getStringValue();  
1023 - return true;  
1024 } 1066 }
1025 1067
1026 std::string 1068 std::string
1027 QPDFObjectHandle::getUTF8Value() const 1069 QPDFObjectHandle::getUTF8Value() const
1028 { 1070 {
1029 - if (auto str = as<QPDF_String>()) {  
1030 - return str->getUTF8Val();  
1031 - } else { 1071 + try {
  1072 + return String(obj).utf8_value();
  1073 + } catch (std::invalid_argument&) {
1032 typeWarning("string", "returning empty string"); 1074 typeWarning("string", "returning empty string");
1033 - QTC::TC("qpdf", "QPDFObjectHandle string returning empty utf8");  
1034 - return ""; 1075 + return {};
1035 } 1076 }
1036 } 1077 }
1037 1078
1038 bool 1079 bool
1039 QPDFObjectHandle::getValueAsUTF8(std::string& value) const 1080 QPDFObjectHandle::getValueAsUTF8(std::string& value) const
1040 { 1081 {
1041 - if (auto str = as<QPDF_String>()) {  
1042 - value = str->getUTF8Val(); 1082 + try {
  1083 + value = String(obj).utf8_value();
1043 return true; 1084 return true;
  1085 + } catch (std::invalid_argument&) {
  1086 + return false;
1044 } 1087 }
1045 - return false;  
1046 } 1088 }
1047 1089
1048 // Operator and Inline Image accessors 1090 // Operator and Inline Image accessors
@@ -1718,18 +1760,6 @@ QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_z @@ -1718,18 +1760,6 @@ QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_z
1718 } 1760 }
1719 1761
1720 QPDFObjectHandle 1762 QPDFObjectHandle
1721 -QPDFObjectHandle::newString(std::string const& str)  
1722 -{  
1723 - return {QPDFObject::create<QPDF_String>(str)};  
1724 -}  
1725 -  
1726 -QPDFObjectHandle  
1727 -QPDFObjectHandle::newUnicodeString(std::string const& utf8_str)  
1728 -{  
1729 - return {QPDF_String::create_utf16(utf8_str)};  
1730 -}  
1731 -  
1732 -QPDFObjectHandle  
1733 QPDFObjectHandle::newOperator(std::string const& value) 1763 QPDFObjectHandle::newOperator(std::string const& value)
1734 { 1764 {
1735 return {QPDFObject::create<QPDF_Operator>(value)}; 1765 return {QPDFObject::create<QPDF_Operator>(value)};
libqpdf/qpdf/QPDFObjectHandle_private.hh
@@ -412,15 +412,15 @@ namespace qpdf @@ -412,15 +412,15 @@ namespace qpdf
412 { 412 {
413 } 413 }
414 414
415 - // Return the name value. If the object is not a valid Name, throw a  
416 - // std::invalid_argument exception. 415 + // Return the name value. If the object is not a valid Name, throw a std::invalid_argument
  416 + // exception.
417 operator std::string() const& 417 operator std::string() const&
418 { 418 {
419 return value(); 419 return value();
420 } 420 }
421 421
422 - // Return the integer value. If the object is not a valid integer, throw a  
423 - // std::invalid_argument exception. 422 + // Return the name value. If the object is not a valid name, throw a std::invalid_argument
  423 + // exception.
424 std::string const& value() const; 424 std::string const& value() const;
425 425
426 // Return true if object value is equal to the 'rhs' value. Return false if the object is 426 // Return true if object value is equal to the 'rhs' value. Return false if the object is
@@ -589,7 +589,54 @@ namespace qpdf @@ -589,7 +589,54 @@ namespace qpdf
589 void warn(std::string const& message); 589 void warn(std::string const& message);
590 590
591 static std::map<std::string, std::string> filter_abbreviations; 591 static std::map<std::string, std::string> filter_abbreviations;
592 - }; 592 + }; // class Stream
  593 +
  594 + class String final: public BaseHandle
  595 + {
  596 + public:
  597 + String() = default;
  598 + String(String const&) = default;
  599 + String(String&&) = default;
  600 + String& operator=(String const&) = default;
  601 + String& operator=(String&&) = default;
  602 + ~String() = default;
  603 +
  604 + explicit String(std::string const&);
  605 + explicit String(std::string&&);
  606 +
  607 + String(QPDFObjectHandle const& oh) :
  608 + BaseHandle(oh.type_code() == ::ot_string ? oh : QPDFObjectHandle())
  609 + {
  610 + }
  611 +
  612 + String(QPDFObjectHandle&& oh) :
  613 + BaseHandle(oh.type_code() == ::ot_string ? std::move(oh) : QPDFObjectHandle())
  614 + {
  615 + }
  616 +
  617 + // Return the string value. If the object is not a valid string, throw a
  618 + // std::invalid_argument exception.
  619 + operator std::string() const&
  620 + {
  621 + return value();
  622 + }
  623 +
  624 + // Return the string value. If the object is not a valid string, throw a
  625 + // std::invalid_argument exception.
  626 + std::string const& value() const;
  627 +
  628 + // Return the string value. If the object is not a valid string, throw a
  629 + // std::invalid_argument exception.
  630 + std::string utf8_value() const;
  631 +
  632 + // Return true if object value is equal to the 'rhs' value. Return false if the object is
  633 + // not a valid String.
  634 + friend bool
  635 + operator==(String const& lhs, std::string_view rhs)
  636 + {
  637 + return lhs && lhs.value() == rhs;
  638 + }
  639 + }; // class String
593 640
594 template <typename T> 641 template <typename T>
595 T* 642 T*
libqpdf/qpdf/QPDFObject_private.hh
@@ -30,6 +30,7 @@ namespace qpdf @@ -30,6 +30,7 @@ namespace qpdf
30 class Integer; 30 class Integer;
31 class Name; 31 class Name;
32 class Stream; 32 class Stream;
  33 + class String;
33 34
34 namespace impl 35 namespace impl
35 { 36 {
@@ -261,6 +262,7 @@ class QPDF_String final @@ -261,6 +262,7 @@ class QPDF_String final
261 { 262 {
262 friend class QPDFObject; 263 friend class QPDFObject;
263 friend class qpdf::BaseHandle; 264 friend class qpdf::BaseHandle;
  265 + friend class qpdf::String;
264 friend class qpdf::impl::Writer; 266 friend class qpdf::impl::Writer;
265 267
266 public: 268 public:
@@ -270,7 +272,11 @@ class QPDF_String final @@ -270,7 +272,11 @@ class QPDF_String final
270 std::string getUTF8Val() const; 272 std::string getUTF8Val() const;
271 273
272 private: 274 private:
273 - QPDF_String(std::string val) : 275 + QPDF_String(std::string const& val) :
  276 + val(val)
  277 + {
  278 + }
  279 + QPDF_String(std::string&& val) :
274 val(std::move(val)) 280 val(std::move(val))
275 { 281 {
276 } 282 }
qpdf/qpdf.testcov
@@ -174,8 +174,6 @@ QPDFParser eof in parse 0 @@ -174,8 +174,6 @@ QPDFParser eof in parse 0
174 QPDFParser eof in parseRemainder 0 174 QPDFParser eof in parseRemainder 0
175 QPDFObjectHandle boolean returning false 0 175 QPDFObjectHandle boolean returning false 0
176 QPDFObjectHandle real returning 0.0 0 176 QPDFObjectHandle real returning 0.0 0
177 -QPDFObjectHandle string returning empty string 0  
178 -QPDFObjectHandle string returning empty utf8 0  
179 QPDFObjectHandle operator returning fake value 0 177 QPDFObjectHandle operator returning fake value 0
180 QPDFObjectHandle inlineimage returning empty data 0 178 QPDFObjectHandle inlineimage returning empty data 0
181 QPDFObjectHandle array treating as empty vector 0 179 QPDFObjectHandle array treating as empty vector 0