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 87 setFilename(std::string const& unicode_name, std::string const& compat_name = "");
88 88  
89 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 91 std::shared_ptr<Members> m;
103 92 };
104 93  
... ...
libqpdf/QPDFFileSpecObjectHelper.cc
1 1 #include <qpdf/QPDFFileSpecObjectHelper.hh>
2 2  
3 3 #include <qpdf/QPDF.hh>
  4 +#include <qpdf/QPDFObjectHandle_private.hh>
4 5 #include <qpdf/QTC.hh>
5 6 #include <qpdf/QUtil.hh>
6 7  
... ... @@ -8,6 +9,11 @@
8 9 #include <string>
9 10  
10 11 using namespace std::literals;
  12 +using namespace qpdf;
  13 +
  14 +class QPDFFileSpecObjectHelper::Members
  15 +{
  16 +};
11 17  
12 18 QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) :
13 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 32 std::string
27 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 38 return {};
34 39 }
... ... @@ -37,12 +42,11 @@ std::string
37 42 QPDFFileSpecObjectHelper::getFilename()
38 43 {
39 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 52 std::map<std::string, std::string>
... ... @@ -50,9 +54,8 @@ QPDFFileSpecObjectHelper::getFilenames()
50 54 {
51 55 std::map<std::string, std::string> result;
52 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 61 return result;
... ... @@ -61,17 +64,16 @@ QPDFFileSpecObjectHelper::getFilenames()
61 64 QPDFObjectHandle
62 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 79 return QPDFObjectHandle::newNull();
... ... @@ -97,21 +99,18 @@ QPDFFileSpecObjectHelper
97 99 QPDFFileSpecObjectHelper::createFileSpec(
98 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 110 QPDFFileSpecObjectHelper&
112 111 QPDFFileSpecObjectHelper::setDescription(std::string const& desc)
113 112 {
114   - oh().replaceKey("/Desc", QPDFObjectHandle::newUnicodeString(desc));
  113 + oh().replaceKey("/Desc", String::utf16(desc));
115 114 return *this;
116 115 }
117 116  
... ... @@ -119,14 +118,12 @@ QPDFFileSpecObjectHelper&amp;
119 118 QPDFFileSpecObjectHelper::setFilename(
120 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 122 oh().replaceKey("/UF", uf);
124 123 if (compat_name.empty()) {
125   - QTC::TC("qpdf", "QPDFFileSpecObjectHelper empty compat_name");
126 124 oh().replaceKey("/F", uf);
127 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 128 return *this;
132 129 }
... ...
qpdf/qpdf.testcov
... ... @@ -325,8 +325,6 @@ QPDFPageObjectHelper::forEachXObject 3
325 325 NNTree erased last kid/item in tree 1
326 326 QPDFPageObjectHelper unresolved names 0
327 327 QPDFPageObjectHelper resolving unresolved 0
328   -QPDFFileSpecObjectHelper empty compat_name 0
329   -QPDFFileSpecObjectHelper non-empty compat_name 0
330 328 QPDFAcroFormDocumentHelper copy annotation 3
331 329 QPDFAcroFormDocumentHelper field with parent 3
332 330 QPDFObjectHandle merge reuse 0
... ...
qpdf/test_driver.cc
... ... @@ -2644,6 +2644,8 @@ test_76(QPDF&amp; pdf, char const* arg2)
2644 2644 "att2", QPDFFileSpecObjectHelper::createFileSpec(pdf, "att2.txt", efs2));
2645 2645 auto fs3 = QPDFFileSpecObjectHelper::createFileSpec(pdf, "att3.txt", efs3);
2646 2646 efdh.replaceEmbeddedFile("att3", fs3);
  2647 + fs3.setFilename("\xcf\x80.txt");
  2648 + assert(fs3.getFilename() == "\xcf\x80.txt");
2647 2649 fs3.setFilename("\xcf\x80.txt", "att3.txt");
2648 2650  
2649 2651 assert(efs1.getCreationDate() == "D:20210207191121-05'00'");
... ...