mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-31 02:48:31 +00:00
Optimize QPDFParser for non-sparse QPDF_Arrays
Stop using nullptr to represent null objects. Count null array elements and trigger creation of sparse arrays if null count is greater than 100.
This commit is contained in:
parent
18c1ffe0df
commit
8fdc3f0964
@ -27,16 +27,15 @@ namespace
|
||||
struct StackFrame
|
||||
{
|
||||
StackFrame(std::shared_ptr<InputSource> input) :
|
||||
offset(input->tell()),
|
||||
contents_string(""),
|
||||
contents_offset(-1)
|
||||
offset(input->tell())
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<QPDFObject>> olist;
|
||||
qpdf_offset_t offset;
|
||||
std::string contents_string;
|
||||
qpdf_offset_t contents_offset;
|
||||
std::string contents_string{""};
|
||||
qpdf_offset_t contents_offset{-1};
|
||||
int null_count{0};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -50,6 +49,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
// this, it will cause a logic error to be thrown from
|
||||
// QPDF::inParse().
|
||||
|
||||
const static std::shared_ptr<QPDFObject> null_oh = QPDF_Null::create();
|
||||
QPDF::ParseGuard pg(context);
|
||||
|
||||
empty = false;
|
||||
@ -67,7 +67,6 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
int good_count = 0;
|
||||
bool b_contents = false;
|
||||
bool is_null = false;
|
||||
auto null_oh = QPDF_Null::create();
|
||||
|
||||
while (!done) {
|
||||
bool bad = false;
|
||||
@ -156,6 +155,8 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
|
||||
case QPDFTokenizer::tt_null:
|
||||
is_null = true;
|
||||
++frame.null_count;
|
||||
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_integer:
|
||||
@ -301,9 +302,11 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
|
||||
case st_dictionary:
|
||||
case st_array:
|
||||
if (!indirect_ref && !is_null) {
|
||||
// No need to set description for direct nulls - they will
|
||||
// become implicit.
|
||||
if (is_null) {
|
||||
object = null_oh;
|
||||
// No need to set description for direct nulls - they probably
|
||||
// will become implicit.
|
||||
} else if (!indirect_ref) {
|
||||
setDescription(object, input->getLastOffset());
|
||||
}
|
||||
set_offset = true;
|
||||
@ -326,7 +329,8 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
parser_state_e old_state = state_stack.back();
|
||||
state_stack.pop_back();
|
||||
if (old_state == st_array) {
|
||||
object = QPDF_Array::create(std::move(olist));
|
||||
object = QPDF_Array::create(
|
||||
std::move(olist), frame.null_count > 100);
|
||||
setDescription(object, offset - 1);
|
||||
// The `offset` points to the next of "[". Set the rewind
|
||||
// offset to point to the beginning of "[". This has been
|
||||
@ -381,7 +385,7 @@ QPDFParser::parse(bool& empty, bool content_stream)
|
||||
// Calculate value.
|
||||
std::shared_ptr<QPDFObject> val;
|
||||
if (iter != olist.end()) {
|
||||
val = *iter ? *iter : QPDF_Null::create();
|
||||
val = *iter;
|
||||
++iter;
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDFParser no val for last key");
|
||||
|
@ -11,15 +11,19 @@ QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) :
|
||||
setFromVector(v);
|
||||
}
|
||||
|
||||
QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v) :
|
||||
QPDFValue(::ot_array, "array")
|
||||
QPDF_Array::QPDF_Array(
|
||||
std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse) :
|
||||
QPDFValue(::ot_array, "array"),
|
||||
sparse(sparse)
|
||||
{
|
||||
setFromVector(std::move(v));
|
||||
}
|
||||
|
||||
QPDF_Array::QPDF_Array(SparseOHArray const& items) :
|
||||
QPDFValue(::ot_array, "array"),
|
||||
sparse(true),
|
||||
sp_elements(items)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@ -37,9 +41,10 @@ QPDF_Array::create(std::vector<QPDFObjectHandle> const& items)
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
QPDF_Array::create(std::vector<std::shared_ptr<QPDFObject>>&& items)
|
||||
QPDF_Array::create(
|
||||
std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse)
|
||||
{
|
||||
return do_create(new QPDF_Array(std::move(items)));
|
||||
return do_create(new QPDF_Array(std::move(items), sparse));
|
||||
}
|
||||
|
||||
std::shared_ptr<QPDFObject>
|
||||
@ -196,8 +201,9 @@ QPDF_Array::setFromVector(std::vector<std::shared_ptr<QPDFObject>>&& v)
|
||||
if (sparse) {
|
||||
sp_elements = SparseOHArray();
|
||||
for (auto&& item: v) {
|
||||
if (item) {
|
||||
sp_elements.append(item);
|
||||
if (item->getTypeCode() != ::ot_null ||
|
||||
item->getObjGen().isIndirect()) {
|
||||
sp_elements.append(std::move(item));
|
||||
} else {
|
||||
++sp_elements.n_elements;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ class QPDF_Array: public QPDFValue
|
||||
static std::shared_ptr<QPDFObject>
|
||||
create(std::vector<QPDFObjectHandle> const& items);
|
||||
static std::shared_ptr<QPDFObject>
|
||||
create(std::vector<std::shared_ptr<QPDFObject>>&& items);
|
||||
create(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse);
|
||||
static std::shared_ptr<QPDFObject> create(SparseOHArray const& items);
|
||||
static std::shared_ptr<QPDFObject> create(OHArray const& items);
|
||||
virtual std::shared_ptr<QPDFObject> copy(bool shallow = false);
|
||||
@ -36,7 +36,7 @@ class QPDF_Array: public QPDFValue
|
||||
|
||||
private:
|
||||
QPDF_Array(std::vector<QPDFObjectHandle> const& items);
|
||||
QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& items);
|
||||
QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse);
|
||||
QPDF_Array(SparseOHArray const& items);
|
||||
QPDF_Array(OHArray const& items);
|
||||
bool sparse{false};
|
||||
|
Loading…
x
Reference in New Issue
Block a user