1 // Copyright 2016 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfapi/parser/cpdf_indirect_object_holder.h" 8 9 #include <algorithm> 10 #include <utility> 11 12 #include "core/fpdfapi/parser/cpdf_object.h" 13 #include "core/fpdfapi/parser/cpdf_parser.h" 14 #include "third_party/base/logging.h" 15 #include "third_party/base/ptr_util.h" 16 17 namespace { 18 FilterInvalidObjNum(CPDF_Object * obj)19CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) { 20 return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr; 21 } 22 23 } // namespace 24 CPDF_IndirectObjectHolder()25CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder() 26 : m_LastObjNum(0), 27 m_pByteStringPool(pdfium::MakeUnique<ByteStringPool>()) {} 28 ~CPDF_IndirectObjectHolder()29CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { 30 m_pByteStringPool.DeleteObject(); // Make weak. 31 } 32 GetIndirectObject(uint32_t objnum) const33CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( 34 uint32_t objnum) const { 35 auto it = m_IndirectObjs.find(objnum); 36 return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.Get()) 37 : nullptr; 38 } 39 GetOrParseIndirectObject(uint32_t objnum)40CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObject( 41 uint32_t objnum) { 42 if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum) 43 return nullptr; 44 45 // Add item anyway to prevent recursively parsing of same object. 46 auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr)); 47 if (!insert_result.second) 48 return FilterInvalidObjNum(insert_result.first->second.Get()); 49 50 RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum); 51 if (!pNewObj) { 52 m_IndirectObjs.erase(insert_result.first); 53 return nullptr; 54 } 55 56 pNewObj->SetObjNum(objnum); 57 m_LastObjNum = std::max(m_LastObjNum, objnum); 58 insert_result.first->second = std::move(pNewObj); 59 return insert_result.first->second.Get(); 60 } 61 ParseIndirectObject(uint32_t objnum)62RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject( 63 uint32_t objnum) { 64 return nullptr; 65 } 66 AddIndirectObject(RetainPtr<CPDF_Object> pObj)67CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject( 68 RetainPtr<CPDF_Object> pObj) { 69 CHECK(!pObj->GetObjNum()); 70 pObj->SetObjNum(++m_LastObjNum); 71 72 auto& obj_holder = m_IndirectObjs[m_LastObjNum]; 73 obj_holder = std::move(pObj); 74 return obj_holder.Get(); 75 } 76 ReplaceIndirectObjectIfHigherGeneration(uint32_t objnum,RetainPtr<CPDF_Object> pObj)77bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( 78 uint32_t objnum, 79 RetainPtr<CPDF_Object> pObj) { 80 ASSERT(objnum); 81 if (!pObj || objnum == CPDF_Object::kInvalidObjNum) 82 return false; 83 84 auto& obj_holder = m_IndirectObjs[objnum]; 85 const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get()); 86 if (old_object && pObj->GetGenNum() <= old_object->GetGenNum()) 87 return false; 88 89 pObj->SetObjNum(objnum); 90 obj_holder = std::move(pObj); 91 m_LastObjNum = std::max(m_LastObjNum, objnum); 92 return true; 93 } 94 DeleteIndirectObject(uint32_t objnum)95void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { 96 auto it = m_IndirectObjs.find(objnum); 97 if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get())) 98 return; 99 100 m_IndirectObjs.erase(it); 101 } 102