Commit b1eb1a958438025efbf90f7a7f45dbe33c746d91

Authored by m-holger
Committed by Jay Berkenbilt
1 parent 3e3b79a7

Refactor QPDFObjectHandle::copyObject1

libqpdf/QPDFObjectHandle.cc
@@ -2211,8 +2211,7 @@ QPDFObjectHandle::shallowCopyInternal1(QPDFObjectHandle& new_obj) @@ -2211,8 +2211,7 @@ QPDFObjectHandle::shallowCopyInternal1(QPDFObjectHandle& new_obj)
2211 assertInitialized(); 2211 assertInitialized();
2212 2212
2213 if (isStream()) { 2213 if (isStream()) {
2214 - QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream");  
2215 - throw std::runtime_error("attempt to make a shallow copy of a stream"); 2214 + // Handled bt QPDF_Stream::copy()
2216 } 2215 }
2217 new_obj = QPDFObjectHandle(obj->copy(true)); 2216 new_obj = QPDFObjectHandle(obj->copy(true));
2218 2217
@@ -2225,9 +2224,10 @@ QPDFObjectHandle::copyObject1(std::set<QPDFObjGen>& visited) @@ -2225,9 +2224,10 @@ QPDFObjectHandle::copyObject1(std::set<QPDFObjGen>& visited)
2225 { 2224 {
2226 assertInitialized(); 2225 assertInitialized();
2227 2226
  2227 + std::shared_ptr<QPDFObject> new_obj;
  2228 +
2228 if (isStream()) { 2229 if (isStream()) {
2229 - throw std::runtime_error(  
2230 - "attempt to make a stream into a direct object"); 2230 + new_obj = obj->copy();
2231 } 2231 }
2232 2232
2233 auto cur_og = getObjGen(); 2233 auto cur_og = getObjGen();
@@ -2241,36 +2241,17 @@ QPDFObjectHandle::copyObject1(std::set&lt;QPDFObjGen&gt;&amp; visited) @@ -2241,36 +2241,17 @@ QPDFObjectHandle::copyObject1(std::set&lt;QPDFObjGen&gt;&amp; visited)
2241 } 2241 }
2242 2242
2243 if (isReserved()) { 2243 if (isReserved()) {
2244 - throw std::logic_error("QPDFObjectHandle: attempting to make a"  
2245 - " reserved object handle direct"); 2244 + new_obj = obj->copy();
2246 } 2245 }
2247 2246
2248 - std::shared_ptr<QPDFObject> new_obj;  
2249 -  
2250 if (isBool() || isInteger() || isName() || isNull() || isReal() || 2247 if (isBool() || isInteger() || isName() || isNull() || isReal() ||
2251 isString()) { 2248 isString()) {
2252 - new_obj = obj->copy(true); 2249 + // copy(true) and copy(false) are the same
  2250 + new_obj = obj->copy();
2253 } else if (isArray()) { 2251 } else if (isArray()) {
2254 - std::vector<QPDFObjectHandle> items;  
2255 - auto array = asArray();  
2256 - int n = array->getNItems();  
2257 - for (int i = 0; i < n; ++i) {  
2258 - items.push_back(array->getItem(i));  
2259 - if (!items.back().isIndirect()) {  
2260 - items.back().copyObject1(visited);  
2261 - }  
2262 - }  
2263 - new_obj = QPDF_Array::create(items); 2252 + new_obj = obj->copy();
2264 } else if (isDictionary()) { 2253 } else if (isDictionary()) {
2265 - std::map<std::string, QPDFObjectHandle> items;  
2266 - auto dict = asDictionary();  
2267 - for (auto const& key: getKeys()) {  
2268 - items[key] = dict->getKey(key);  
2269 - if (!items[key].isIndirect()) {  
2270 - items[key].copyObject1(visited);  
2271 - }  
2272 - }  
2273 - new_obj = QPDF_Dictionary::create(items); 2254 + new_obj = obj->copy();
2274 } else { 2255 } else {
2275 throw std::logic_error("QPDFObjectHandle::makeDirectInternal: " 2256 throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
2276 "unknown object type"); 2257 "unknown object type");
libqpdf/QPDF_Array.cc
@@ -31,7 +31,7 @@ QPDF_Array::create(SparseOHArray const&amp; items) @@ -31,7 +31,7 @@ QPDF_Array::create(SparseOHArray const&amp; items)
31 std::shared_ptr<QPDFObject> 31 std::shared_ptr<QPDFObject>
32 QPDF_Array::copy(bool shallow) 32 QPDF_Array::copy(bool shallow)
33 { 33 {
34 - return create(elements); 34 + return create(shallow ? elements : elements.copy());
35 } 35 }
36 36
37 void 37 void
libqpdf/QPDF_Dictionary.cc
@@ -18,7 +18,17 @@ QPDF_Dictionary::create(std::map&lt;std::string, QPDFObjectHandle&gt; const&amp; items) @@ -18,7 +18,17 @@ QPDF_Dictionary::create(std::map&lt;std::string, QPDFObjectHandle&gt; const&amp; items)
18 std::shared_ptr<QPDFObject> 18 std::shared_ptr<QPDFObject>
19 QPDF_Dictionary::copy(bool shallow) 19 QPDF_Dictionary::copy(bool shallow)
20 { 20 {
21 - return create(items); 21 + if (shallow) {
  22 + return create(items);
  23 + } else {
  24 + std::map<std::string, QPDFObjectHandle> new_items;
  25 + for (auto const& item: this->items) {
  26 + auto value = item.second;
  27 + new_items[item.first] =
  28 + value.isIndirect() ? value : value.shallowCopy();
  29 + }
  30 + return create(new_items);
  31 + }
22 } 32 }
23 33
24 void 34 void
libqpdf/QPDF_Stream.cc
@@ -142,6 +142,7 @@ QPDF_Stream::create( @@ -142,6 +142,7 @@ QPDF_Stream::create(
142 std::shared_ptr<QPDFObject> 142 std::shared_ptr<QPDFObject>
143 QPDF_Stream::copy(bool shallow) 143 QPDF_Stream::copy(bool shallow)
144 { 144 {
  145 + QTC::TC("qpdf", "QPDF_Stream ERR shallow copy stream");
145 throw std::runtime_error("stream objects cannot be cloned"); 146 throw std::runtime_error("stream objects cannot be cloned");
146 } 147 }
147 148
libqpdf/SparseOHArray.cc
@@ -110,6 +110,19 @@ SparseOHArray::insert(size_t idx, QPDFObjectHandle oh) @@ -110,6 +110,19 @@ SparseOHArray::insert(size_t idx, QPDFObjectHandle oh)
110 } 110 }
111 } 111 }
112 112
  113 +SparseOHArray
  114 +SparseOHArray::copy()
  115 +{
  116 + SparseOHArray result;
  117 + result.n_elements = this->n_elements;
  118 + for (auto const& element: this->elements) {
  119 + auto value = element.second;
  120 + result.elements[element.first] =
  121 + value.isIndirect() ? value : value.shallowCopy();
  122 + }
  123 + return result;
  124 +}
  125 +
113 SparseOHArray::const_iterator 126 SparseOHArray::const_iterator
114 SparseOHArray::begin() const 127 SparseOHArray::begin() const
115 { 128 {
libqpdf/qpdf/SparseOHArray.hh
@@ -15,6 +15,7 @@ class SparseOHArray @@ -15,6 +15,7 @@ class SparseOHArray
15 void setAt(size_t idx, QPDFObjectHandle oh); 15 void setAt(size_t idx, QPDFObjectHandle oh);
16 void erase(size_t idx); 16 void erase(size_t idx);
17 void insert(size_t idx, QPDFObjectHandle oh); 17 void insert(size_t idx, QPDFObjectHandle oh);
  18 + SparseOHArray copy();
18 void disconnect(); 19 void disconnect();
19 20
20 typedef std::unordered_map<size_t, QPDFObjectHandle>::const_iterator 21 typedef std::unordered_map<size_t, QPDFObjectHandle>::const_iterator
qpdf/qpdf.testcov
@@ -192,7 +192,7 @@ QPDF insert page 2 @@ -192,7 +192,7 @@ QPDF insert page 2
192 QPDF updateAllPagesCache 0 192 QPDF updateAllPagesCache 0
193 QPDF insert non-indirect page 0 193 QPDF insert non-indirect page 0
194 QPDF insert indirect page 0 194 QPDF insert indirect page 0
195 -QPDFObjectHandle ERR shallow copy stream 0 195 +QPDF_Stream ERR shallow copy stream 0
196 QPDFObjectHandle newStream with string 0 196 QPDFObjectHandle newStream with string 0
197 QPDF unknown key not inherited 0 197 QPDF unknown key not inherited 0
198 QPDF_Stream provider length not provided 0 198 QPDF_Stream provider length not provided 0
qpdf/qtest/qpdf/shallow_stream.out
1 -attempt to make a shallow copy of a stream 1 +stream objects cannot be cloned