Commit b1eb1a958438025efbf90f7a7f45dbe33c746d91
Committed by
Jay Berkenbilt
1 parent
3e3b79a7
Refactor QPDFObjectHandle::copyObject1
Showing
8 changed files
with
38 additions
and
32 deletions
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<QPDFObjGen>& visited) | @@ -2241,36 +2241,17 @@ QPDFObjectHandle::copyObject1(std::set<QPDFObjGen>& 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& items) | @@ -31,7 +31,7 @@ QPDF_Array::create(SparseOHArray const& 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<std::string, QPDFObjectHandle> const& items) | @@ -18,7 +18,17 @@ QPDF_Dictionary::create(std::map<std::string, QPDFObjectHandle> const& 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