aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorm-holger <m-holger@kubitscheck.org>2022-11-14 23:06:04 +0100
committerJay Berkenbilt <jberkenbilt@users.noreply.github.com>2022-11-20 18:07:22 +0100
commitb1eb1a958438025efbf90f7a7f45dbe33c746d91 (patch)
treef9ff3400204d1ca1e878c94b240eb0d1e1704e3f
parent3e3b79a774a294ca2020a7bad8ee6ddd2c0179de (diff)
downloadqpdf-b1eb1a958438025efbf90f7a7f45dbe33c746d91.tar.zst
Refactor QPDFObjectHandle::copyObject1
-rw-r--r--libqpdf/QPDFObjectHandle.cc37
-rw-r--r--libqpdf/QPDF_Array.cc2
-rw-r--r--libqpdf/QPDF_Dictionary.cc12
-rw-r--r--libqpdf/QPDF_Stream.cc1
-rw-r--r--libqpdf/SparseOHArray.cc13
-rw-r--r--libqpdf/qpdf/SparseOHArray.hh1
-rw-r--r--qpdf/qpdf.testcov2
-rw-r--r--qpdf/qtest/qpdf/shallow_stream.out2
8 files changed, 38 insertions, 32 deletions
diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc
index 3e37a966..2990b019 100644
--- a/libqpdf/QPDFObjectHandle.cc
+++ b/libqpdf/QPDFObjectHandle.cc
@@ -2211,8 +2211,7 @@ QPDFObjectHandle::shallowCopyInternal1(QPDFObjectHandle& new_obj)
assertInitialized();
if (isStream()) {
- QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream");
- throw std::runtime_error("attempt to make a shallow copy of a stream");
+ // Handled bt QPDF_Stream::copy()
}
new_obj = QPDFObjectHandle(obj->copy(true));
@@ -2225,9 +2224,10 @@ QPDFObjectHandle::copyObject1(std::set<QPDFObjGen>& visited)
{
assertInitialized();
+ std::shared_ptr<QPDFObject> new_obj;
+
if (isStream()) {
- throw std::runtime_error(
- "attempt to make a stream into a direct object");
+ new_obj = obj->copy();
}
auto cur_og = getObjGen();
@@ -2241,36 +2241,17 @@ QPDFObjectHandle::copyObject1(std::set<QPDFObjGen>& visited)
}
if (isReserved()) {
- throw std::logic_error("QPDFObjectHandle: attempting to make a"
- " reserved object handle direct");
+ new_obj = obj->copy();
}
- std::shared_ptr<QPDFObject> new_obj;
-
if (isBool() || isInteger() || isName() || isNull() || isReal() ||
isString()) {
- new_obj = obj->copy(true);
+ // copy(true) and copy(false) are the same
+ new_obj = obj->copy();
} else if (isArray()) {
- std::vector<QPDFObjectHandle> items;
- auto array = asArray();
- int n = array->getNItems();
- for (int i = 0; i < n; ++i) {
- items.push_back(array->getItem(i));
- if (!items.back().isIndirect()) {
- items.back().copyObject1(visited);
- }
- }
- new_obj = QPDF_Array::create(items);
+ new_obj = obj->copy();
} else if (isDictionary()) {
- std::map<std::string, QPDFObjectHandle> items;
- auto dict = asDictionary();
- for (auto const& key: getKeys()) {
- items[key] = dict->getKey(key);
- if (!items[key].isIndirect()) {
- items[key].copyObject1(visited);
- }
- }
- new_obj = QPDF_Dictionary::create(items);
+ new_obj = obj->copy();
} else {
throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
"unknown object type");
diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc
index f33ad99d..6e8db5e9 100644
--- a/libqpdf/QPDF_Array.cc
+++ b/libqpdf/QPDF_Array.cc
@@ -31,7 +31,7 @@ QPDF_Array::create(SparseOHArray const& items)
std::shared_ptr<QPDFObject>
QPDF_Array::copy(bool shallow)
{
- return create(elements);
+ return create(shallow ? elements : elements.copy());
}
void
diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc
index 5b1e03d8..1df4f8f0 100644
--- a/libqpdf/QPDF_Dictionary.cc
+++ b/libqpdf/QPDF_Dictionary.cc
@@ -18,7 +18,17 @@ QPDF_Dictionary::create(std::map<std::string, QPDFObjectHandle> const& items)
std::shared_ptr<QPDFObject>
QPDF_Dictionary::copy(bool shallow)
{
- return create(items);
+ if (shallow) {
+ return create(items);
+ } else {
+ std::map<std::string, QPDFObjectHandle> new_items;
+ for (auto const& item: this->items) {
+ auto value = item.second;
+ new_items[item.first] =
+ value.isIndirect() ? value : value.shallowCopy();
+ }
+ return create(new_items);
+ }
}
void
diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc
index 332eaa37..480bb6e9 100644
--- a/libqpdf/QPDF_Stream.cc
+++ b/libqpdf/QPDF_Stream.cc
@@ -142,6 +142,7 @@ QPDF_Stream::create(
std::shared_ptr<QPDFObject>
QPDF_Stream::copy(bool shallow)
{
+ QTC::TC("qpdf", "QPDF_Stream ERR shallow copy stream");
throw std::runtime_error("stream objects cannot be cloned");
}
diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc
index 6ff02f6c..567f9d0b 100644
--- a/libqpdf/SparseOHArray.cc
+++ b/libqpdf/SparseOHArray.cc
@@ -110,6 +110,19 @@ SparseOHArray::insert(size_t idx, QPDFObjectHandle oh)
}
}
+SparseOHArray
+SparseOHArray::copy()
+{
+ SparseOHArray result;
+ result.n_elements = this->n_elements;
+ for (auto const& element: this->elements) {
+ auto value = element.second;
+ result.elements[element.first] =
+ value.isIndirect() ? value : value.shallowCopy();
+ }
+ return result;
+}
+
SparseOHArray::const_iterator
SparseOHArray::begin() const
{
diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh
index 440c0b2d..b6918cb5 100644
--- a/libqpdf/qpdf/SparseOHArray.hh
+++ b/libqpdf/qpdf/SparseOHArray.hh
@@ -15,6 +15,7 @@ class SparseOHArray
void setAt(size_t idx, QPDFObjectHandle oh);
void erase(size_t idx);
void insert(size_t idx, QPDFObjectHandle oh);
+ SparseOHArray copy();
void disconnect();
typedef std::unordered_map<size_t, QPDFObjectHandle>::const_iterator
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index f99d3f74..d9215dd1 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -192,7 +192,7 @@ QPDF insert page 2
QPDF updateAllPagesCache 0
QPDF insert non-indirect page 0
QPDF insert indirect page 0
-QPDFObjectHandle ERR shallow copy stream 0
+QPDF_Stream ERR shallow copy stream 0
QPDFObjectHandle newStream with string 0
QPDF unknown key not inherited 0
QPDF_Stream provider length not provided 0
diff --git a/qpdf/qtest/qpdf/shallow_stream.out b/qpdf/qtest/qpdf/shallow_stream.out
index fec1aa83..f77e9de5 100644
--- a/qpdf/qtest/qpdf/shallow_stream.out
+++ b/qpdf/qtest/qpdf/shallow_stream.out
@@ -1 +1 @@
-attempt to make a shallow copy of a stream
+stream objects cannot be cloned