mirror of https://github.com/qpdf/qpdf.git
Merge 3cd3c22df8
into 58c31fdd5e
This commit is contained in:
commit
ee4cb1da76
|
@ -772,12 +772,13 @@ class QPDF
|
|||
class Resolver
|
||||
{
|
||||
friend class QPDFObject;
|
||||
friend class QPDF_Unresolved;
|
||||
|
||||
private:
|
||||
static void
|
||||
resolve(QPDF* qpdf, QPDFObjGen const& og)
|
||||
static QPDFObject*
|
||||
resolved(QPDF* qpdf, QPDFObjGen og)
|
||||
{
|
||||
qpdf->resolve(og);
|
||||
return qpdf->resolve(og);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1028,7 +1029,7 @@ class QPDF
|
|||
QPDFObjGen exp_og,
|
||||
QPDFObjGen& og,
|
||||
bool skip_cache_if_in_xref);
|
||||
void resolve(QPDFObjGen og);
|
||||
QPDFObject* resolve(QPDFObjGen og);
|
||||
void resolveObjectsInStream(int obj_stream_number);
|
||||
void stopOnError(std::string const& message);
|
||||
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,245 @@
|
|||
// Copyright (c) 2005-2024 Jay Berkenbilt
|
||||
//
|
||||
// This file is part of qpdf.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Versions of qpdf prior to version 7 were released under the terms
|
||||
// of version 2.0 of the Artistic License. At your option, you may
|
||||
// continue to consider qpdf to be licensed under those terms. Please
|
||||
// see the manual for additional information.
|
||||
|
||||
#ifndef QPDFOBJECTHANDLE_INLINE_HH
|
||||
#define QPDFOBJECTHANDLE_INLINE_HH
|
||||
|
||||
class QPDFObjectHandle::QPDFDictItems
|
||||
{
|
||||
// This class allows C++-style iteration, including range-for iteration, around dictionaries.
|
||||
// You can write
|
||||
|
||||
// for (auto iter: QPDFDictItems(dictionary_obj))
|
||||
// {
|
||||
// // iter.first is a string
|
||||
// // iter.second is a QPDFObjectHandle
|
||||
// }
|
||||
|
||||
// See examples/pdf-name-number-tree.cc for a demonstration of using this API.
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFDictItems(QPDFObjectHandle const& oh);
|
||||
|
||||
class iterator
|
||||
{
|
||||
friend class QPDFDictItems;
|
||||
|
||||
public:
|
||||
typedef std::pair<std::string, QPDFObjectHandle> T;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = long;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
QPDF_DLL
|
||||
virtual ~iterator() = default;
|
||||
QPDF_DLL
|
||||
iterator& operator++();
|
||||
QPDF_DLL
|
||||
iterator
|
||||
operator++(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
++(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
iterator& operator--();
|
||||
QPDF_DLL
|
||||
iterator
|
||||
operator--(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
--(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
reference operator*();
|
||||
QPDF_DLL
|
||||
pointer operator->();
|
||||
QPDF_DLL
|
||||
bool operator==(iterator const& other) const;
|
||||
QPDF_DLL
|
||||
bool
|
||||
operator!=(iterator const& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
iterator(QPDFObjectHandle& oh, bool for_begin);
|
||||
void updateIValue();
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFDictItems::iterator;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members(QPDFObjectHandle& oh, bool for_begin);
|
||||
Members() = delete;
|
||||
Members(Members const&) = delete;
|
||||
|
||||
QPDFObjectHandle& oh;
|
||||
std::set<std::string> keys;
|
||||
std::set<std::string>::iterator iter;
|
||||
bool is_end;
|
||||
};
|
||||
std::shared_ptr<Members> m;
|
||||
value_type ivalue;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
iterator begin();
|
||||
QPDF_DLL
|
||||
iterator end();
|
||||
|
||||
private:
|
||||
QPDFObjectHandle oh;
|
||||
};
|
||||
|
||||
class QPDFObjectHandle::QPDFArrayItems
|
||||
{
|
||||
// This class allows C++-style iteration, including range-for iteration, around arrays. You can
|
||||
// write
|
||||
|
||||
// for (auto iter: QPDFArrayItems(array_obj))
|
||||
// {
|
||||
// // iter is a QPDFObjectHandle
|
||||
// }
|
||||
|
||||
// See examples/pdf-name-number-tree.cc for a demonstration of using this API.
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFArrayItems(QPDFObjectHandle const& oh);
|
||||
|
||||
class iterator
|
||||
{
|
||||
friend class QPDFArrayItems;
|
||||
|
||||
public:
|
||||
typedef QPDFObjectHandle T;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = long;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
QPDF_DLL
|
||||
virtual ~iterator() = default;
|
||||
QPDF_DLL
|
||||
iterator& operator++();
|
||||
QPDF_DLL
|
||||
iterator
|
||||
operator++(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
++(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
iterator& operator--();
|
||||
QPDF_DLL
|
||||
iterator
|
||||
operator--(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
--(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
reference operator*();
|
||||
QPDF_DLL
|
||||
pointer operator->();
|
||||
QPDF_DLL
|
||||
bool operator==(iterator const& other) const;
|
||||
QPDF_DLL
|
||||
bool
|
||||
operator!=(iterator const& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
iterator(QPDFObjectHandle& oh, bool for_begin);
|
||||
void updateIValue();
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFArrayItems::iterator;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members(QPDFObjectHandle& oh, bool for_begin);
|
||||
Members() = delete;
|
||||
Members(Members const&) = delete;
|
||||
|
||||
QPDFObjectHandle& oh;
|
||||
int item_number;
|
||||
bool is_end;
|
||||
};
|
||||
std::shared_ptr<Members> m;
|
||||
value_type ivalue;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
iterator begin();
|
||||
QPDF_DLL
|
||||
iterator end();
|
||||
|
||||
private:
|
||||
QPDFObjectHandle oh;
|
||||
};
|
||||
|
||||
inline int
|
||||
QPDFObjectHandle::getObjectID() const
|
||||
{
|
||||
return getObjGen().getObj();
|
||||
}
|
||||
|
||||
inline int
|
||||
QPDFObjectHandle::getGeneration() const
|
||||
{
|
||||
return getObjGen().getGen();
|
||||
}
|
||||
|
||||
inline bool
|
||||
QPDFObjectHandle::isIndirect() const
|
||||
{
|
||||
return (obj != nullptr) && (getObjectID() != 0);
|
||||
}
|
||||
|
||||
inline bool
|
||||
QPDFObjectHandle::isInitialized() const
|
||||
{
|
||||
return obj != nullptr;
|
||||
}
|
||||
|
||||
#endif // QPDFOBJECTHANDLE_INLINE_HH
|
|
@ -1696,11 +1696,11 @@ QPDF::readObjectAtOffset(
|
|||
return oh;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObject*
|
||||
QPDF::resolve(QPDFObjGen og)
|
||||
{
|
||||
if (!isUnresolved(og)) {
|
||||
return;
|
||||
return m->obj_cache[og].object.get();
|
||||
}
|
||||
|
||||
if (m->resolving.count(og)) {
|
||||
|
@ -1709,7 +1709,7 @@ QPDF::resolve(QPDFObjGen og)
|
|||
QTC::TC("qpdf", "QPDF recursion loop in resolve");
|
||||
warn(damagedPDF("", "loop detected resolving object " + og.unparse(' ')));
|
||||
updateCache(og, QPDF_Null::create(), -1, -1);
|
||||
return;
|
||||
return m->obj_cache[og].object.get();
|
||||
}
|
||||
ResolveRecorder rr(this, og);
|
||||
|
||||
|
@ -1750,6 +1750,7 @@ QPDF::resolve(QPDFObjGen og)
|
|||
|
||||
auto result(m->obj_cache[og].object);
|
||||
result->setDefaultDescription(this, og);
|
||||
return result.get();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -3,13 +3,6 @@
|
|||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDF_Destroyed.hh>
|
||||
|
||||
void
|
||||
QPDFObject::doResolve()
|
||||
{
|
||||
auto og = value->og;
|
||||
QPDF::Resolver::resolve(value->qpdf, og);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObject::destroy()
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -130,8 +130,7 @@ QPDF_Array::unparse()
|
|||
for (int j = next; j < key; ++j) {
|
||||
result += "null ";
|
||||
}
|
||||
item.second->resolve();
|
||||
auto og = item.second->getObjGen();
|
||||
auto og = item.second->resolved_object()->getObjGen();
|
||||
result += og.isIndirect() ? og.unparse(' ') + " R " : item.second->unparse() + " ";
|
||||
next = ++key;
|
||||
}
|
||||
|
@ -140,8 +139,7 @@ QPDF_Array::unparse()
|
|||
}
|
||||
} else {
|
||||
for (auto const& item: elements) {
|
||||
item->resolve();
|
||||
auto og = item->getObjGen();
|
||||
auto og = item->resolved_object()->getObjGen();
|
||||
result += og.isIndirect() ? og.unparse(' ') + " R " : item->unparse() + " ";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <qpdf/QPDF_Unresolved.hh>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFObject_private.hh>
|
||||
|
||||
QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og) :
|
||||
QPDFValue(::ot_unresolved, "unresolved", qpdf, og)
|
||||
|
@ -16,19 +17,23 @@ QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen const& og)
|
|||
std::shared_ptr<QPDFObject>
|
||||
QPDF_Unresolved::copy(bool shallow)
|
||||
{
|
||||
throw std::logic_error("attempted to shallow copy an unresolved QPDFObjectHandle");
|
||||
return nullptr;
|
||||
return QPDF::Resolver::resolved(qpdf, og)->copy(shallow);
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDF_Unresolved::unparse()
|
||||
{
|
||||
throw std::logic_error("attempted to unparse an unresolved QPDFObjectHandle");
|
||||
return "";
|
||||
return QPDF::Resolver::resolved(qpdf, og)->unparse();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Unresolved::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
throw std::logic_error("attempted to get JSON from an unresolved QPDFObjectHandle");
|
||||
QPDF::Resolver::resolved(qpdf, og)->writeJSON(json_version, p);
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDF_Unresolved::getStringValue() const
|
||||
{
|
||||
return QPDF::Resolver::resolved(qpdf, og)->getStringValue();
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
// include/qpdf/QPDFObject.hh. See comments there for an explanation.
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/JSON.hh>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFValue.hh>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
|
@ -43,18 +43,26 @@ class QPDFObject
|
|||
{
|
||||
return value->getStringValue();
|
||||
}
|
||||
// Return a unique type code for the resolved object
|
||||
qpdf_object_type_e
|
||||
getResolvedTypeCode() const
|
||||
{
|
||||
auto tc = value->type_code;
|
||||
return tc == ::ot_unresolved
|
||||
? QPDF::Resolver::resolved(value->qpdf, value->og)->value->type_code
|
||||
: tc;
|
||||
}
|
||||
// Return a unique type code for the object
|
||||
qpdf_object_type_e
|
||||
getTypeCode() const
|
||||
getTypeCode() const noexcept
|
||||
{
|
||||
return value->type_code;
|
||||
}
|
||||
|
||||
// Return a string literal that describes the type, useful for debugging and testing
|
||||
char const*
|
||||
getTypeName() const
|
||||
{
|
||||
return value->type_name;
|
||||
return resolved_object()->value->type_name;
|
||||
}
|
||||
|
||||
QPDF*
|
||||
|
@ -157,20 +165,23 @@ class QPDFObject
|
|||
{
|
||||
return value->type_code == ::ot_unresolved;
|
||||
}
|
||||
void
|
||||
resolve()
|
||||
const QPDFObject*
|
||||
resolved_object() const
|
||||
{
|
||||
if (isUnresolved()) {
|
||||
doResolve();
|
||||
}
|
||||
return isUnresolved() ? QPDF::Resolver::resolved(value->qpdf, value->og) : this;
|
||||
}
|
||||
void doResolve();
|
||||
|
||||
template <typename T>
|
||||
T*
|
||||
as()
|
||||
as() const
|
||||
{
|
||||
return dynamic_cast<T*>(value.get());
|
||||
if (auto result = dynamic_cast<T*>(value.get())) {
|
||||
return result;
|
||||
} else {
|
||||
return isUnresolved()
|
||||
? dynamic_cast<T*>(QPDF::Resolver::resolved(value->qpdf, value->og)->value.get())
|
||||
: nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -11,6 +11,7 @@ class QPDF_Unresolved: public QPDFValue
|
|||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
std::string getStringValue() const override;
|
||||
|
||||
private:
|
||||
QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og);
|
||||
|
|
Loading…
Reference in New Issue