diff --git a/include/qpdf/ObjectHandle.hh b/include/qpdf/ObjectHandle.hh index 6655322..50649ff 100644 --- a/include/qpdf/ObjectHandle.hh +++ b/include/qpdf/ObjectHandle.hh @@ -54,6 +54,7 @@ namespace qpdf // The rest of the header file is for qpdf internal use only. + std::shared_ptr copy(bool shallow = false) const; inline QPDFObjGen id_gen() const; inline bool indirect() const; inline bool null() const; diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 13f04fd..d7ceec5 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -289,29 +289,29 @@ Name::normalize(std::string const& name) } std::shared_ptr -QPDFObject::copy(bool shallow) +BaseHandle::copy(bool shallow) const { - switch (getResolvedTypeCode()) { + switch (type_code()) { case ::ot_uninitialized: throw std::logic_error("QPDFObjectHandle: attempting to copy an uninitialized object"); return {}; // does not return case ::ot_reserved: - return create(); + return QPDFObject::create(); case ::ot_null: - return create(); + return QPDFObject::create(); case ::ot_boolean: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_integer: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_real: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_string: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_name: - return create(std::get(value).name); + return QPDFObject::create(std::get(obj->value).name); case ::ot_array: { - auto const& a = std::get(value); + auto const& a = std::get(obj->value); if (shallow) { return QPDFObject::create(a); } else { @@ -321,7 +321,7 @@ QPDFObject::copy(bool shallow) result.sp = std::make_unique(); result.sp->size = a.sp->size; for (auto const& [idx, oh]: a.sp->elements) { - result.sp->elements[idx] = oh.indirect() ? oh : oh.getObj()->copy(); + result.sp->elements[idx] = oh.indirect() ? oh : oh.copy(); } return QPDFObject::create(std::move(result)); } else { @@ -329,8 +329,7 @@ QPDFObject::copy(bool shallow) result.reserve(a.elements.size()); for (auto const& element: a.elements) { result.emplace_back( - element ? (element.indirect() ? element : element.getObj()->copy()) - : element); + element ? (element.indirect() ? element : element.copy()) : element); } return QPDFObject::create(std::move(result), false); } @@ -338,13 +337,13 @@ QPDFObject::copy(bool shallow) } case ::ot_dictionary: { - auto const& d = std::get(value); + auto const& d = std::get(obj->value); if (shallow) { return QPDFObject::create(d.items); } else { std::map new_items; for (auto const& [key, val]: d.items) { - new_items[key] = val.indirect() ? val : val.getObj()->copy(); + new_items[key] = val.indirect() ? val : val.copy(); } return QPDFObject::create(new_items); } @@ -354,9 +353,9 @@ QPDFObject::copy(bool shallow) throw std::runtime_error("stream objects cannot be cloned"); return {}; // does not return case ::ot_operator: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_inlineimage: - return create(std::get(value).val); + return QPDFObject::create(std::get(obj->value).val); case ::ot_unresolved: throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); return {}; // does not return @@ -364,7 +363,7 @@ QPDFObject::copy(bool shallow) throw std::logic_error("attempted to shallow copy QPDFObjectHandle from destroyed QPDF"); return {}; // does not return case ::ot_reference: - return qpdf->getObject(og).getObj(); + return obj->qpdf->getObject(obj->og).getObj(); } return {}; // unreachable } @@ -1902,7 +1901,7 @@ QPDFObjectHandle::shallowCopy() if (!obj) { throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); } - return {obj->copy()}; + return {copy()}; } QPDFObjectHandle @@ -1911,7 +1910,7 @@ QPDFObjectHandle::unsafeShallowCopy() if (!obj) { throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); } - return {obj->copy(true)}; + return {copy(true)}; } void @@ -1926,7 +1925,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) } if (isBool() || isInteger() || isName() || isNull() || isReal() || isString()) { - this->obj = obj->copy(true); + this->obj = copy(true); } else if (auto a = as_array(strict)) { std::vector items; for (auto const& item: a) { diff --git a/libqpdf/qpdf/QPDFObject_private.hh b/libqpdf/qpdf/QPDFObject_private.hh index 25db481..91c5e36 100644 --- a/libqpdf/qpdf/QPDFObject_private.hh +++ b/libqpdf/qpdf/QPDFObject_private.hh @@ -50,7 +50,9 @@ class QPDF_Array final private: friend class QPDFObject; + friend class qpdf::BaseHandle; friend class qpdf::Array; + QPDF_Array(std::vector const& items) : elements(items) { @@ -75,6 +77,7 @@ class QPDF_Array final class QPDF_Bool final { friend class QPDFObject; + friend class qpdf::BaseHandle; friend class QPDFObjectHandle; explicit QPDF_Bool(bool val) : @@ -92,6 +95,7 @@ class QPDF_Dictionary final { friend class QPDFObject; friend class qpdf::BaseDictionary; + friend class qpdf::BaseHandle; QPDF_Dictionary(std::map const& items) : items(items) @@ -105,6 +109,7 @@ class QPDF_Dictionary final class QPDF_InlineImage final { friend class QPDFObject; + friend class qpdf::BaseHandle; explicit QPDF_InlineImage(std::string val) : val(std::move(val)) @@ -116,6 +121,7 @@ class QPDF_InlineImage final class QPDF_Integer final { friend class QPDFObject; + friend class qpdf::BaseHandle; friend class QPDFObjectHandle; QPDF_Integer(long long val) : @@ -128,6 +134,7 @@ class QPDF_Integer final class QPDF_Name final { friend class QPDFObject; + friend class qpdf::BaseHandle; explicit QPDF_Name(std::string name) : name(std::move(name)) @@ -139,6 +146,7 @@ class QPDF_Name final class QPDF_Null final { friend class QPDFObject; + friend class qpdf::BaseHandle; public: static inline std::shared_ptr create( @@ -150,6 +158,7 @@ class QPDF_Null final class QPDF_Operator final { friend class QPDFObject; + friend class qpdf::BaseHandle; QPDF_Operator(std::string val) : val(std::move(val)) @@ -162,6 +171,7 @@ class QPDF_Operator final class QPDF_Real final { friend class QPDFObject; + friend class qpdf::BaseHandle; QPDF_Real(std::string val) : val(std::move(val)) @@ -235,6 +245,7 @@ class QPDF_Stream final class QPDF_String final { friend class QPDFObject; + friend class qpdf::BaseHandle; friend class QPDFWriter; public: @@ -284,7 +295,6 @@ class QPDFObject qpdf, og, std::forward(T(std::forward(args)...))); } - std::shared_ptr copy(bool shallow = false); std::string unparse(); void write_json(int json_version, JSON::Writer& p); void disconnect(); diff --git a/libtests/sparse_array.cc b/libtests/sparse_array.cc index a930ee7..1412ff0 100644 --- a/libtests/sparse_array.cc +++ b/libtests/sparse_array.cc @@ -96,11 +96,11 @@ main() assert(b.at(8).second.isNull()); assert(b.at(5).second.isIndirect()); assert(obj->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); - auto c = obj->copy(true); - auto d = obj->copy(false); + auto c = QPDFObjectHandle(obj).unsafeShallowCopy(); + auto d = QPDFObjectHandle(obj).shallowCopy(); b.at(7).second.setArrayItem(2, "42"_qpdf); - assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); - assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); + assert(c.unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); + assert(d.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); try { b.setAt(3, {});