| // Copyright 2016 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" |
| |
| #include <algorithm> |
| #include <memory> |
| #include <utility> |
| |
| #include "core/fpdfapi/parser/cpdf_object.h" |
| #include "core/fpdfapi/parser/cpdf_parser.h" |
| #include "third_party/base/check.h" |
| |
| namespace { |
| |
| CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) { |
| return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr; |
| } |
| |
| } // namespace |
| |
| CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder() |
| : m_pByteStringPool(std::make_unique<ByteStringPool>()) {} |
| |
| CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { |
| m_pByteStringPool.DeleteObject(); // Make weak. |
| } |
| |
| CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( |
| uint32_t objnum) const { |
| auto it = m_IndirectObjs.find(objnum); |
| return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.Get()) |
| : nullptr; |
| } |
| |
| CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObject( |
| uint32_t objnum) { |
| if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum) |
| return nullptr; |
| |
| // Add item anyway to prevent recursively parsing of same object. |
| auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr)); |
| if (!insert_result.second) |
| return FilterInvalidObjNum(insert_result.first->second.Get()); |
| |
| RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum); |
| if (!pNewObj) { |
| m_IndirectObjs.erase(insert_result.first); |
| return nullptr; |
| } |
| |
| pNewObj->SetObjNum(objnum); |
| m_LastObjNum = std::max(m_LastObjNum, objnum); |
| insert_result.first->second = std::move(pNewObj); |
| return insert_result.first->second.Get(); |
| } |
| |
| RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject( |
| uint32_t objnum) { |
| return nullptr; |
| } |
| |
| CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject( |
| RetainPtr<CPDF_Object> pObj) { |
| CHECK(!pObj->GetObjNum()); |
| pObj->SetObjNum(++m_LastObjNum); |
| |
| auto& obj_holder = m_IndirectObjs[m_LastObjNum]; |
| obj_holder = std::move(pObj); |
| return obj_holder.Get(); |
| } |
| |
| bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( |
| uint32_t objnum, |
| RetainPtr<CPDF_Object> pObj) { |
| DCHECK(objnum); |
| if (!pObj || objnum == CPDF_Object::kInvalidObjNum) |
| return false; |
| |
| auto& obj_holder = m_IndirectObjs[objnum]; |
| const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get()); |
| if (old_object && pObj->GetGenNum() <= old_object->GetGenNum()) |
| return false; |
| |
| pObj->SetObjNum(objnum); |
| obj_holder = std::move(pObj); |
| m_LastObjNum = std::max(m_LastObjNum, objnum); |
| return true; |
| } |
| |
| void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { |
| auto it = m_IndirectObjs.find(objnum); |
| if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get())) |
| return; |
| |
| m_IndirectObjs.erase(it); |
| } |