Commit 1acb5dd7 authored by Adam Reichold's avatar Adam Reichold

Make object deep-copying fallible to avoid having to implement it for the...

Make object deep-copying fallible to avoid having to implement it for the whole Stream class hierarchy
parent 4d0983e5
Pipeline #27401 passed with stage
in 9 minutes and 57 seconds
......@@ -28,6 +28,7 @@
#include <config.h>
#include <cassert>
#include <memory>
#include "Object.h"
#include "Array.h"
......@@ -48,12 +49,20 @@ Array::~Array() {
Array *Array::copy(XRef *xrefA, bool deep) const {
arrayLocker();
Array *a = new Array(xrefA);
auto a = std::make_unique<Array>(xrefA);
a->elems.reserve(elems.size());
for (const auto& elem : elems) {
a->elems.push_back(deep ? elem.deepCopy(xrefA) : elem.copy());
if (deep) {
auto copiedElem = elem.deepCopy(xrefA);
if (copiedElem.isNone()) {
return nullptr;
}
a->elems.push_back(std::move(copiedElem));
} else {
a->elems.push_back(elem.copy());
}
}
return a;
return a.release();
}
void Array::add(Object &&elem) {
......
......@@ -32,6 +32,7 @@
#include <config.h>
#include <algorithm>
#include <memory>
#include "XRef.h"
#include "Dict.h"
......@@ -65,16 +66,24 @@ Dict::Dict(XRef *xrefA) {
Dict *Dict::copy(XRef *xrefA, bool deep) const {
dictLocker();
Dict *dictA = new Dict(xrefA);
auto dictA = std::make_unique<Dict>(xrefA);
dictA->entries.reserve(entries.size());
for (const auto& entry : entries) {
dictA->entries.emplace_back(entry.first, deep ? entry.second.deepCopy(xrefA) : entry.second.copy());
if (deep) {
auto copiedObj = entry.second.deepCopy(xrefA);
if (copiedObj.isNone()) {
return nullptr;
}
dictA->entries.emplace_back(entry.first, std::move(copiedObj));
} else {
dictA->entries.emplace_back(entry.first, entry.second.copy());
}
}
dictA->sorted = sorted.load();
return dictA;
return dictA.release();
}
void Dict::add(const char *key, Object &&val) {
......
......@@ -72,6 +72,10 @@ Object Object::doCopy(XRef *xref) const {
case objArray:
if (xref) {
obj.array = array->copy(xref, true);
if (!obj.array) {
// Deep-copying the array elements failed.
obj.type = objNone;
}
} else {
array->incRef();
}
......@@ -79,14 +83,18 @@ Object Object::doCopy(XRef *xref) const {
case objDict:
if (xref) {
obj.dict = dict->copy(xref, true);
if (!obj.dict) {
// Deep-copying the dict entries failed.
obj.type = objNone;
}
} else {
dict->incRef();
}
break;
case objStream:
if (xref) {
// TODO: How to copy a stream? Via BaseStream::copy? Or is it even necessary?
stream->incRef();
// Deep-copying of streams is not supported.
obj.type = objNone;
} else {
stream->incRef();
}
......
......@@ -205,8 +205,9 @@ public:
// Set object to null.
void setToNull() { free(); type = objNull; }
// Copy this to obj
// Shallow-copy this object
Object copy() const { return doCopy(nullptr); }
// Deep-copy this object and its child objects or return none if this is not possible
Object deepCopy(XRef *xref) const { return doCopy(xref); }
// If object is a Ref, fetch and return the referenced object.
......
......@@ -1132,7 +1132,12 @@ Object XRef::fetch(int num, int gen, int recursion) {
}
Object obj = parser.getObj(false, (encrypted && !e->getFlag(XRefEntry::Unencrypted)) ? fileKey : nullptr,
encAlgorithm, keyLength, num, gen, recursion);
objs.put(Ref{num, gen}, new Object{obj.deepCopy(this)});
auto cachedObj = obj.deepCopy(this);
if (!cachedObj.isNone()) {
objs.put(Ref{num, gen}, new Object{std::move(cachedObj)});
}
return obj;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment