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 16 namespace { 17 FilterInvalidObjNum(CPDF_Object * obj)18CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) { 19 return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr; 20 } 21 22 } // namespace 23 CPDF_IndirectObjectHolder()24CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder() 25 : m_LastObjNum(0), 26 m_pByteStringPool(pdfium::MakeUnique<ByteStringPool>()) {} 27 ~CPDF_IndirectObjectHolder()28CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { 29 m_pByteStringPool.DeleteObject(); // Make weak. 30 } 31 GetIndirectObject(uint32_t objnum) const32CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject( 33 uint32_t objnum) const { 34 auto it = m_IndirectObjs.find(objnum); 35 return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.get()) 36 : nullptr; 37 } 38 GetOrParseIndirectObject(uint32_t objnum)39CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObject( 40 uint32_t objnum) { 41 if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum) 42 return nullptr; 43 44 // Add item anyway to prevent recursively parsing of same object. 45 auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr)); 46 if (!insert_result.second) 47 return FilterInvalidObjNum(insert_result.first->second.get()); 48 49 std::unique_ptr<CPDF_Object> pNewObj = ParseIndirectObject(objnum); 50 if (!pNewObj) { 51 m_IndirectObjs.erase(insert_result.first); 52 return nullptr; 53 } 54 55 pNewObj->SetObjNum(objnum); 56 m_LastObjNum = std::max(m_LastObjNum, objnum); 57 insert_result.first->second = std::move(pNewObj); 58 return insert_result.first->second.get(); 59 } 60 ParseIndirectObject(uint32_t objnum)61std::unique_ptr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject( 62 uint32_t objnum) { 63 return nullptr; 64 } 65 AddIndirectObject(std::unique_ptr<CPDF_Object> pObj)66CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject( 67 std::unique_ptr<CPDF_Object> pObj) { 68 CHECK(!pObj->GetObjNum()); 69 pObj->SetObjNum(++m_LastObjNum); 70 71 auto& obj_holder = m_IndirectObjs[m_LastObjNum]; 72 if (obj_holder) 73 m_OrphanObjs.push_back(std::move(obj_holder)); 74 75 obj_holder = std::move(pObj); 76 return obj_holder.get(); 77 } 78 ReplaceIndirectObjectIfHigherGeneration(uint32_t objnum,std::unique_ptr<CPDF_Object> pObj)79bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( 80 uint32_t objnum, 81 std::unique_ptr<CPDF_Object> pObj) { 82 ASSERT(objnum); 83 if (!pObj || objnum == CPDF_Object::kInvalidObjNum) 84 return false; 85 86 auto& obj_holder = m_IndirectObjs[objnum]; 87 const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.get()); 88 if (old_object && pObj->GetGenNum() <= old_object->GetGenNum()) 89 return false; 90 91 pObj->SetObjNum(objnum); 92 if (obj_holder) 93 m_OrphanObjs.push_back(std::move(obj_holder)); 94 95 obj_holder = std::move(pObj); 96 m_LastObjNum = std::max(m_LastObjNum, objnum); 97 return true; 98 } 99 DeleteIndirectObject(uint32_t objnum)100void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { 101 auto it = m_IndirectObjs.find(objnum); 102 if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.get())) 103 return; 104 105 m_IndirectObjs.erase(it); 106 } 107