diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index cfd19ea9..00bfb45c 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -1608,12 +1608,12 @@ class QPDFObjectHandle QPDF_DLL bool isImage(bool exclude_imagemask = true); - private: QPDFObjectHandle(std::shared_ptr const& obj) : obj(obj) { } + private: QPDF_Array* asArray(); QPDF_Bool* asBool(); QPDF_Dictionary* asDictionary(); diff --git a/libqpdf/QPDFParser.cc b/libqpdf/QPDFParser.cc index d190835d..6b3cdb4e 100644 --- a/libqpdf/QPDFParser.cc +++ b/libqpdf/QPDFParser.cc @@ -33,7 +33,7 @@ namespace { } - std::vector olist; + std::vector> olist; qpdf_offset_t offset; std::string contents_string; qpdf_offset_t contents_offset; @@ -67,7 +67,7 @@ QPDFParser::parse(bool& empty, bool content_stream) int good_count = 0; bool b_contents = false; bool is_null = false; - auto null_oh = QPDFObjectHandle::newNull(); + auto null_oh = QPDF_Null::create(); while (!done) { bool bad = false; @@ -191,11 +191,13 @@ QPDFParser::parse(bool& empty, bool content_stream) if (content_stream) { object = QPDF_Operator::create(value); } else if ( - (value == "R") && (state != st_top) && (size >= 2) && - (!olist.back().isIndirect()) && - (olist.back().isInteger()) && - (!olist.at(size - 2).isIndirect()) && - (olist.at(size - 2).isInteger())) { + value == "R" && state != st_top && size >= 2 && + olist.back() && + olist.back()->getTypeCode() == ::ot_integer && + !olist.back()->getObjGen().isIndirect() && + olist.at(size - 2) && + olist.at(size - 2)->getTypeCode() == ::ot_integer && + !olist.at(size - 2)->getObjGen().isIndirect()) { if (context == nullptr) { QTC::TC("qpdf", "QPDFParser indirect without context"); throw std::logic_error( @@ -203,8 +205,8 @@ QPDFParser::parse(bool& empty, bool content_stream) " on an object with indirect references"); } auto ref_og = QPDFObjGen( - olist.at(size - 2).getIntValueAsInt(), - olist.back().getIntValueAsInt()); + QPDFObjectHandle(olist.at(size - 2)).getIntValueAsInt(), + QPDFObjectHandle(olist.back()).getIntValueAsInt()); if (ref_og.isIndirect()) { // This action has the desirable side effect // of causing dangling references (references @@ -306,7 +308,7 @@ QPDFParser::parse(bool& empty, bool content_stream) setDescription(object, input->getLastOffset()); } set_offset = true; - olist.push_back(is_null ? null_oh : QPDFObjectHandle(object)); + olist.push_back(is_null ? null_oh : object); break; case st_top: @@ -325,7 +327,7 @@ 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(olist); + object = QPDF_Array::create(std::move(olist)); setDescription(object, offset - 1); // The `offset` points to the next of "[". Set the rewind // offset to point to the beginning of "[". This has been @@ -412,8 +414,7 @@ QPDFParser::parse(bool& empty, bool content_stream) if (state_stack.back() == st_top) { done = true; } else { - stack.back().olist.push_back( - is_null ? null_oh : QPDFObjectHandle(object)); + stack.back().olist.push_back(is_null ? null_oh : object); } } } diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 6e8db5e9..12e4b3e9 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -10,6 +11,12 @@ QPDF_Array::QPDF_Array(std::vector const& v) : setFromVector(v); } +QPDF_Array::QPDF_Array(std::vector>&& v) : + QPDFValue(::ot_array, "array") +{ + setFromVector(std::move(v)); +} + QPDF_Array::QPDF_Array(SparseOHArray const& items) : QPDFValue(::ot_array, "array"), elements(items) @@ -22,6 +29,12 @@ QPDF_Array::create(std::vector const& items) return do_create(new QPDF_Array(items)); } +std::shared_ptr +QPDF_Array::create(std::vector>&& items) +{ + return do_create(new QPDF_Array(std::move(items))); +} + std::shared_ptr QPDF_Array::create(SparseOHArray const& items) { @@ -106,6 +119,15 @@ QPDF_Array::setFromVector(std::vector const& v) } } +void +QPDF_Array::setFromVector(std::vector>&& v) +{ + this->elements = SparseOHArray(); + for (auto&& iter: v) { + this->elements.append(iter); + } +} + void QPDF_Array::insertItem(int at, QPDFObjectHandle const& item) { diff --git a/libqpdf/SparseOHArray.cc b/libqpdf/SparseOHArray.cc index 567f9d0b..5f64f50b 100644 --- a/libqpdf/SparseOHArray.cc +++ b/libqpdf/SparseOHArray.cc @@ -1,5 +1,8 @@ #include +#include +#include + #include SparseOHArray::SparseOHArray() : @@ -22,6 +25,15 @@ SparseOHArray::append(QPDFObjectHandle oh) ++this->n_elements; } +void +SparseOHArray::append(std::shared_ptr&& obj) +{ + if (obj->getTypeCode() != ::ot_null || !obj->getObjGen().isIndirect()) { + this->elements[this->n_elements] = std::move(obj); + } + ++this->n_elements; +} + QPDFObjectHandle SparseOHArray::at(size_t idx) const { diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 0bf3d436..56c0101f 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -13,6 +13,8 @@ class QPDF_Array: public QPDFValue virtual ~QPDF_Array() = default; static std::shared_ptr create(std::vector const& items); + static std::shared_ptr + create(std::vector>&& items); static std::shared_ptr create(SparseOHArray const& items); virtual std::shared_ptr copy(bool shallow = false); virtual std::string unparse(); @@ -25,6 +27,7 @@ class QPDF_Array: public QPDFValue void setItem(int, QPDFObjectHandle const&); void setFromVector(std::vector const& items); + void setFromVector(std::vector>&& items); void insertItem(int at, QPDFObjectHandle const& item); void appendItem(QPDFObjectHandle const& item); void eraseItem(int at); @@ -36,6 +39,7 @@ class QPDF_Array: public QPDFValue private: QPDF_Array(std::vector const& items); + QPDF_Array(std::vector>&& items); QPDF_Array(SparseOHArray const& items); SparseOHArray elements; }; diff --git a/libqpdf/qpdf/SparseOHArray.hh b/libqpdf/qpdf/SparseOHArray.hh index b6918cb5..b2b98313 100644 --- a/libqpdf/qpdf/SparseOHArray.hh +++ b/libqpdf/qpdf/SparseOHArray.hh @@ -10,6 +10,7 @@ class SparseOHArray SparseOHArray(); size_t size() const; void append(QPDFObjectHandle oh); + void append(std::shared_ptr&& obj); QPDFObjectHandle at(size_t idx) const; void remove_last(); void setAt(size_t idx, QPDFObjectHandle oh);