Commit 9cbc87e10c50e1560fb53f34abe01cb744fc2c4b

Authored by m-holger
1 parent 9a95497e

Refactor `QPDFFileSpecObjectHelper`: simplify dictionary access, streamline stri…

…ng handling with `qpdf::String`, and clean up `Members` class implementation.
include/qpdf/QPDFFileSpecObjectHelper.hh
@@ -87,18 +87,7 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper @@ -87,18 +87,7 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper
87 setFilename(std::string const& unicode_name, std::string const& compat_name = ""); 87 setFilename(std::string const& unicode_name, std::string const& compat_name = "");
88 88
89 private: 89 private:
90 - class Members  
91 - {  
92 - friend class QPDFFileSpecObjectHelper;  
93 -  
94 - public:  
95 - ~Members() = default;  
96 -  
97 - private:  
98 - Members() = default;  
99 - Members(Members const&) = delete;  
100 - };  
101 - 90 + class Members;
102 std::shared_ptr<Members> m; 91 std::shared_ptr<Members> m;
103 }; 92 };
104 93
libqpdf/QPDFFileSpecObjectHelper.cc
1 #include <qpdf/QPDFFileSpecObjectHelper.hh> 1 #include <qpdf/QPDFFileSpecObjectHelper.hh>
2 2
3 #include <qpdf/QPDF.hh> 3 #include <qpdf/QPDF.hh>
  4 +#include <qpdf/QPDFObjectHandle_private.hh>
4 #include <qpdf/QTC.hh> 5 #include <qpdf/QTC.hh>
5 #include <qpdf/QUtil.hh> 6 #include <qpdf/QUtil.hh>
6 7
@@ -8,6 +9,11 @@ @@ -8,6 +9,11 @@
8 #include <string> 9 #include <string>
9 10
10 using namespace std::literals; 11 using namespace std::literals;
  12 +using namespace qpdf;
  13 +
  14 +class QPDFFileSpecObjectHelper::Members
  15 +{
  16 +};
11 17
12 QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) : 18 QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) :
13 QPDFObjectHelper(oh) 19 QPDFObjectHelper(oh)
@@ -26,9 +32,8 @@ static const std::array&lt;std::string, 5&gt; name_keys = {&quot;/UF&quot;s, &quot;/F&quot;s, &quot;/Unix&quot;s, &quot;/ @@ -26,9 +32,8 @@ static const std::array&lt;std::string, 5&gt; name_keys = {&quot;/UF&quot;s, &quot;/F&quot;s, &quot;/Unix&quot;s, &quot;/
26 std::string 32 std::string
27 QPDFFileSpecObjectHelper::getDescription() 33 QPDFFileSpecObjectHelper::getDescription()
28 { 34 {
29 - auto desc = oh().getKey("/Desc");  
30 - if (desc.isString()) {  
31 - return desc.getUTF8Value(); 35 + if (String Desc = oh().getKey("/Desc")) {
  36 + return Desc.utf8_value();
32 } 37 }
33 return {}; 38 return {};
34 } 39 }
@@ -37,12 +42,11 @@ std::string @@ -37,12 +42,11 @@ std::string
37 QPDFFileSpecObjectHelper::getFilename() 42 QPDFFileSpecObjectHelper::getFilename()
38 { 43 {
39 for (auto const& i: name_keys) { 44 for (auto const& i: name_keys) {
40 - auto k = oh().getKey(i);  
41 - if (k.isString()) {  
42 - return k.getUTF8Value(); 45 + if (String k = oh()[i]) {
  46 + return k.utf8_value();
43 } 47 }
44 } 48 }
45 - return ""; 49 + return {};
46 } 50 }
47 51
48 std::map<std::string, std::string> 52 std::map<std::string, std::string>
@@ -50,9 +54,8 @@ QPDFFileSpecObjectHelper::getFilenames() @@ -50,9 +54,8 @@ QPDFFileSpecObjectHelper::getFilenames()
50 { 54 {
51 std::map<std::string, std::string> result; 55 std::map<std::string, std::string> result;
52 for (auto const& i: name_keys) { 56 for (auto const& i: name_keys) {
53 - auto k = oh().getKey(i);  
54 - if (k.isString()) {  
55 - result[i] = k.getUTF8Value(); 57 + if (String k = oh()[i]) {
  58 + result[i] = k.utf8_value();
56 } 59 }
57 } 60 }
58 return result; 61 return result;
@@ -61,17 +64,16 @@ QPDFFileSpecObjectHelper::getFilenames() @@ -61,17 +64,16 @@ QPDFFileSpecObjectHelper::getFilenames()
61 QPDFObjectHandle 64 QPDFObjectHandle
62 QPDFFileSpecObjectHelper::getEmbeddedFileStream(std::string const& key) 65 QPDFFileSpecObjectHelper::getEmbeddedFileStream(std::string const& key)
63 { 66 {
64 - auto ef = oh().getKey("/EF");  
65 - if (!ef.isDictionary()) {  
66 - return QPDFObjectHandle::newNull();  
67 - }  
68 - if (!key.empty()) {  
69 - return ef.getKey(key);  
70 - }  
71 - for (auto const& i: name_keys) {  
72 - auto k = ef.getKey(i);  
73 - if (k.isStream()) {  
74 - return k; 67 + if (Dictionary EF = oh()["/EF"]) {
  68 + if (!key.empty() && EF.contains(key)) {
  69 + if (auto result = EF[key]) {
  70 + return result;
  71 + }
  72 + }
  73 + for (auto const& i: name_keys) {
  74 + if (Stream k = EF[i]) {
  75 + return k;
  76 + }
75 } 77 }
76 } 78 }
77 return QPDFObjectHandle::newNull(); 79 return QPDFObjectHandle::newNull();
@@ -97,21 +99,18 @@ QPDFFileSpecObjectHelper @@ -97,21 +99,18 @@ QPDFFileSpecObjectHelper
97 QPDFFileSpecObjectHelper::createFileSpec( 99 QPDFFileSpecObjectHelper::createFileSpec(
98 QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper efsoh) 100 QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper efsoh)
99 { 101 {
100 - auto oh = qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary());  
101 - oh.replaceKey("/Type", QPDFObjectHandle::newName("/Filespec"));  
102 - QPDFFileSpecObjectHelper result(oh);  
103 - result.setFilename(filename);  
104 - auto ef = QPDFObjectHandle::newDictionary();  
105 - ef.replaceKey("/F", efsoh.getObjectHandle());  
106 - ef.replaceKey("/UF", efsoh.getObjectHandle());  
107 - oh.replaceKey("/EF", ef);  
108 - return result; 102 + auto UF = String::utf16(filename);
  103 + return {qpdf.makeIndirectObject(Dictionary(
  104 + {{"/Type", Name("/Filespec")},
  105 + {"/F", UF},
  106 + {"/UF", UF},
  107 + {"/EF", Dictionary({{"/F", efsoh}, {"/UF", efsoh}})}}))};
109 } 108 }
110 109
111 QPDFFileSpecObjectHelper& 110 QPDFFileSpecObjectHelper&
112 QPDFFileSpecObjectHelper::setDescription(std::string const& desc) 111 QPDFFileSpecObjectHelper::setDescription(std::string const& desc)
113 { 112 {
114 - oh().replaceKey("/Desc", QPDFObjectHandle::newUnicodeString(desc)); 113 + oh().replaceKey("/Desc", String::utf16(desc));
115 return *this; 114 return *this;
116 } 115 }
117 116
@@ -119,14 +118,12 @@ QPDFFileSpecObjectHelper&amp; @@ -119,14 +118,12 @@ QPDFFileSpecObjectHelper&amp;
119 QPDFFileSpecObjectHelper::setFilename( 118 QPDFFileSpecObjectHelper::setFilename(
120 std::string const& unicode_name, std::string const& compat_name) 119 std::string const& unicode_name, std::string const& compat_name)
121 { 120 {
122 - auto uf = QPDFObjectHandle::newUnicodeString(unicode_name); 121 + auto uf = String::utf16(unicode_name);
123 oh().replaceKey("/UF", uf); 122 oh().replaceKey("/UF", uf);
124 if (compat_name.empty()) { 123 if (compat_name.empty()) {
125 - QTC::TC("qpdf", "QPDFFileSpecObjectHelper empty compat_name");  
126 oh().replaceKey("/F", uf); 124 oh().replaceKey("/F", uf);
127 } else { 125 } else {
128 - QTC::TC("qpdf", "QPDFFileSpecObjectHelper non-empty compat_name");  
129 - oh().replaceKey("/F", QPDFObjectHandle::newString(compat_name)); 126 + oh().replaceKey("/F", String(compat_name));
130 } 127 }
131 return *this; 128 return *this;
132 } 129 }
qpdf/qpdf.testcov
@@ -325,8 +325,6 @@ QPDFPageObjectHelper::forEachXObject 3 @@ -325,8 +325,6 @@ QPDFPageObjectHelper::forEachXObject 3
325 NNTree erased last kid/item in tree 1 325 NNTree erased last kid/item in tree 1
326 QPDFPageObjectHelper unresolved names 0 326 QPDFPageObjectHelper unresolved names 0
327 QPDFPageObjectHelper resolving unresolved 0 327 QPDFPageObjectHelper resolving unresolved 0
328 -QPDFFileSpecObjectHelper empty compat_name 0  
329 -QPDFFileSpecObjectHelper non-empty compat_name 0  
330 QPDFAcroFormDocumentHelper copy annotation 3 328 QPDFAcroFormDocumentHelper copy annotation 3
331 QPDFAcroFormDocumentHelper field with parent 3 329 QPDFAcroFormDocumentHelper field with parent 3
332 QPDFObjectHandle merge reuse 0 330 QPDFObjectHandle merge reuse 0
qpdf/test_driver.cc
@@ -2644,6 +2644,8 @@ test_76(QPDF&amp; pdf, char const* arg2) @@ -2644,6 +2644,8 @@ test_76(QPDF&amp; pdf, char const* arg2)
2644 "att2", QPDFFileSpecObjectHelper::createFileSpec(pdf, "att2.txt", efs2)); 2644 "att2", QPDFFileSpecObjectHelper::createFileSpec(pdf, "att2.txt", efs2));
2645 auto fs3 = QPDFFileSpecObjectHelper::createFileSpec(pdf, "att3.txt", efs3); 2645 auto fs3 = QPDFFileSpecObjectHelper::createFileSpec(pdf, "att3.txt", efs3);
2646 efdh.replaceEmbeddedFile("att3", fs3); 2646 efdh.replaceEmbeddedFile("att3", fs3);
  2647 + fs3.setFilename("\xcf\x80.txt");
  2648 + assert(fs3.getFilename() == "\xcf\x80.txt");
2647 fs3.setFilename("\xcf\x80.txt", "att3.txt"); 2649 fs3.setFilename("\xcf\x80.txt", "att3.txt");
2648 2650
2649 assert(efs1.getCreationDate() == "D:20210207191121-05'00'"); 2651 assert(efs1.getCreationDate() == "D:20210207191121-05'00'");