mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
Split QPDFObjectHandle::shallowCopyInternal and copyObject
Have separate versions for unsafeShallowCopy, shallowCopy and makeDirect.
This commit is contained in:
parent
dbc5f07b90
commit
63d1dcb414
@ -1628,12 +1628,23 @@ class QPDFObjectHandle
|
|||||||
void objectWarning(std::string const& warning);
|
void objectWarning(std::string const& warning);
|
||||||
void assertType(char const* type_name, bool istype);
|
void assertType(char const* type_name, bool istype);
|
||||||
bool dereference();
|
bool dereference();
|
||||||
|
void copyObject1(
|
||||||
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect,
|
||||||
|
bool first_level_only,
|
||||||
|
bool stop_at_streams);
|
||||||
|
void shallowCopyInternal1(QPDFObjectHandle& oh, bool first_level_only);
|
||||||
|
void copyObject2(
|
||||||
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect,
|
||||||
|
bool first_level_only,
|
||||||
|
bool stop_at_streams);
|
||||||
|
void shallowCopyInternal2(QPDFObjectHandle& oh, bool first_level_only);
|
||||||
void copyObject(
|
void copyObject(
|
||||||
std::set<QPDFObjGen>& visited,
|
std::set<QPDFObjGen>& visited,
|
||||||
bool cross_indirect,
|
bool cross_indirect,
|
||||||
bool first_level_only,
|
bool first_level_only,
|
||||||
bool stop_at_streams);
|
bool stop_at_streams);
|
||||||
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
|
|
||||||
void disconnect();
|
void disconnect();
|
||||||
void setParsedOffset(qpdf_offset_t offset);
|
void setParsedOffset(qpdf_offset_t offset);
|
||||||
void parseContentStream_internal(
|
void parseContentStream_internal(
|
||||||
|
@ -2201,20 +2201,12 @@ QPDFObjectHandle
|
|||||||
QPDFObjectHandle::shallowCopy()
|
QPDFObjectHandle::shallowCopy()
|
||||||
{
|
{
|
||||||
QPDFObjectHandle result;
|
QPDFObjectHandle result;
|
||||||
shallowCopyInternal(result, false);
|
shallowCopyInternal1(result, false);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPDFObjectHandle
|
|
||||||
QPDFObjectHandle::unsafeShallowCopy()
|
|
||||||
{
|
|
||||||
QPDFObjectHandle result;
|
|
||||||
shallowCopyInternal(result, true);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFObjectHandle::shallowCopyInternal(
|
QPDFObjectHandle::shallowCopyInternal1(
|
||||||
QPDFObjectHandle& new_obj, bool first_level_only)
|
QPDFObjectHandle& new_obj, bool first_level_only)
|
||||||
{
|
{
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
@ -2226,7 +2218,178 @@ QPDFObjectHandle::shallowCopyInternal(
|
|||||||
new_obj = QPDFObjectHandle(obj->copy(true));
|
new_obj = QPDFObjectHandle(obj->copy(true));
|
||||||
|
|
||||||
std::set<QPDFObjGen> visited;
|
std::set<QPDFObjGen> visited;
|
||||||
new_obj.copyObject(visited, false, first_level_only, false);
|
new_obj.copyObject1(visited, false, first_level_only, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFObjectHandle::copyObject1(
|
||||||
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect,
|
||||||
|
bool first_level_only,
|
||||||
|
bool stop_at_streams)
|
||||||
|
{
|
||||||
|
assertInitialized();
|
||||||
|
|
||||||
|
if (isStream()) {
|
||||||
|
if (stop_at_streams) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(
|
||||||
|
"attempt to make a stream into a direct object");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cur_og = getObjGen();
|
||||||
|
if (cur_og.getObj() != 0) {
|
||||||
|
if (visited.count(cur_og)) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"loop detected while converting object from "
|
||||||
|
"indirect to direct");
|
||||||
|
}
|
||||||
|
visited.insert(cur_og);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReserved()) {
|
||||||
|
throw std::logic_error("QPDFObjectHandle: attempting to make a"
|
||||||
|
" reserved object handle direct");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFObject> new_obj;
|
||||||
|
|
||||||
|
if (isBool() || isInteger() || isName() || isNull() || isReal() ||
|
||||||
|
isString()) {
|
||||||
|
new_obj = obj->copy(true);
|
||||||
|
} 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 ((!first_level_only) &&
|
||||||
|
(cross_indirect || (!items.back().isIndirect()))) {
|
||||||
|
items.back().copyObject1(
|
||||||
|
visited, cross_indirect, first_level_only, stop_at_streams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_obj = QPDF_Array::create(items);
|
||||||
|
} else if (isDictionary()) {
|
||||||
|
std::map<std::string, QPDFObjectHandle> items;
|
||||||
|
auto dict = asDictionary();
|
||||||
|
for (auto const& key: getKeys()) {
|
||||||
|
items[key] = dict->getKey(key);
|
||||||
|
if ((!first_level_only) &&
|
||||||
|
(cross_indirect || (!items[key].isIndirect()))) {
|
||||||
|
items[key].copyObject1(
|
||||||
|
visited, cross_indirect, first_level_only, stop_at_streams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_obj = QPDF_Dictionary::create(items);
|
||||||
|
} else {
|
||||||
|
throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
|
||||||
|
"unknown object type");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->obj = new_obj;
|
||||||
|
|
||||||
|
if (cur_og.getObj()) {
|
||||||
|
visited.erase(cur_og);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPDFObjectHandle
|
||||||
|
QPDFObjectHandle::unsafeShallowCopy()
|
||||||
|
{
|
||||||
|
QPDFObjectHandle result;
|
||||||
|
shallowCopyInternal2(result, true);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFObjectHandle::shallowCopyInternal2(
|
||||||
|
QPDFObjectHandle& new_obj, bool first_level_only)
|
||||||
|
{
|
||||||
|
assertInitialized();
|
||||||
|
|
||||||
|
if (isStream()) {
|
||||||
|
throw std::runtime_error("attempt to make a shallow copy of a stream");
|
||||||
|
}
|
||||||
|
new_obj = QPDFObjectHandle(obj->copy(true));
|
||||||
|
|
||||||
|
std::set<QPDFObjGen> visited;
|
||||||
|
new_obj.copyObject2(visited, false, first_level_only, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFObjectHandle::copyObject2(
|
||||||
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect,
|
||||||
|
bool first_level_only,
|
||||||
|
bool stop_at_streams)
|
||||||
|
{
|
||||||
|
assertInitialized();
|
||||||
|
|
||||||
|
if (isStream()) {
|
||||||
|
if (stop_at_streams) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(
|
||||||
|
"attempt to make a stream into a direct object");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cur_og = getObjGen();
|
||||||
|
if (cur_og.getObj() != 0) {
|
||||||
|
if (visited.count(cur_og)) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"loop detected while converting object from "
|
||||||
|
"indirect to direct");
|
||||||
|
}
|
||||||
|
visited.insert(cur_og);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReserved()) {
|
||||||
|
throw std::logic_error("QPDFObjectHandle: attempting to make a"
|
||||||
|
" reserved object handle direct");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFObject> new_obj;
|
||||||
|
|
||||||
|
if (isBool() || isInteger() || isName() || isNull() || isReal() ||
|
||||||
|
isString()) {
|
||||||
|
new_obj = obj->copy(true);
|
||||||
|
} 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 ((!first_level_only) &&
|
||||||
|
(cross_indirect || (!items.back().isIndirect()))) {
|
||||||
|
items.back().copyObject2(
|
||||||
|
visited, cross_indirect, first_level_only, stop_at_streams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_obj = QPDF_Array::create(items);
|
||||||
|
} else if (isDictionary()) {
|
||||||
|
std::map<std::string, QPDFObjectHandle> items;
|
||||||
|
auto dict = asDictionary();
|
||||||
|
for (auto const& key: getKeys()) {
|
||||||
|
items[key] = dict->getKey(key);
|
||||||
|
if ((!first_level_only) &&
|
||||||
|
(cross_indirect || (!items[key].isIndirect()))) {
|
||||||
|
items[key].copyObject2(
|
||||||
|
visited, cross_indirect, first_level_only, stop_at_streams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_obj = QPDF_Dictionary::create(items);
|
||||||
|
} else {
|
||||||
|
throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
|
||||||
|
"unknown object type");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->obj = new_obj;
|
||||||
|
|
||||||
|
if (cur_og.getObj()) {
|
||||||
|
visited.erase(cur_og);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user