| // 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 <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_LastObjNum(0), 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) { | |
| ASSERT(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); | |
| } |