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 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 1046 std::string
1005 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 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 1057 bool
1017 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 1064 return false;
1021 1065 }
1022   - value = obj->getStringValue();
1023   - return true;
1024 1066 }
1025 1067  
1026 1068 std::string
1027 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 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 1079 bool
1039 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 1084 return true;
  1085 + } catch (std::invalid_argument&) {
  1086 + return false;
1044 1087 }
1045   - return false;
1046 1088 }
1047 1089  
1048 1090 // Operator and Inline Image accessors
... ... @@ -1718,18 +1760,6 @@ QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_z
1718 1760 }
1719 1761  
1720 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 1763 QPDFObjectHandle::newOperator(std::string const& value)
1734 1764 {
1735 1765 return {QPDFObject::create<QPDF_Operator>(value)};
... ...
libqpdf/qpdf/QPDFObjectHandle_private.hh
... ... @@ -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 417 operator std::string() const&
418 418 {
419 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 424 std::string const& value() const;
425 425  
426 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 589 void warn(std::string const& message);
590 590  
591 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 641 template <typename T>
595 642 T*
... ...
libqpdf/qpdf/QPDFObject_private.hh
... ... @@ -30,6 +30,7 @@ namespace qpdf
30 30 class Integer;
31 31 class Name;
32 32 class Stream;
  33 + class String;
33 34  
34 35 namespace impl
35 36 {
... ... @@ -261,6 +262,7 @@ class QPDF_String final
261 262 {
262 263 friend class QPDFObject;
263 264 friend class qpdf::BaseHandle;
  265 + friend class qpdf::String;
264 266 friend class qpdf::impl::Writer;
265 267  
266 268 public:
... ... @@ -270,7 +272,11 @@ class QPDF_String final
270 272 std::string getUTF8Val() const;
271 273  
272 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 280 val(std::move(val))
275 281 {
276 282 }
... ...
qpdf/qpdf.testcov
... ... @@ -174,8 +174,6 @@ QPDFParser eof in parse 0
174 174 QPDFParser eof in parseRemainder 0
175 175 QPDFObjectHandle boolean returning false 0
176 176 QPDFObjectHandle real returning 0.0 0
177   -QPDFObjectHandle string returning empty string 0
178   -QPDFObjectHandle string returning empty utf8 0
179 177 QPDFObjectHandle operator returning fake value 0
180 178 QPDFObjectHandle inlineimage returning empty data 0
181 179 QPDFObjectHandle array treating as empty vector 0
... ...