1 // Copyright 2016 The PDFium Authors 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 <memory> 11 #include <utility> 12 13 #include "core/fpdfapi/parser/cpdf_object.h" 14 #include "core/fpdfapi/parser/cpdf_parser.h" 15 #include "third_party/base/check.h" 16 17 namespace { 18 FilterInvalidObjNum(const CPDF_Object * obj)19const CPDF_Object* FilterInvalidObjNum(const 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_pByteStringPool(std::make_unique<ByteStringPool>()) {} 27 ~CPDF_IndirectObjectHolder()28CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() { 29 m_pByteStringPool.DeleteObject(); // Make weak. 30 } 31 GetIndirectObject(uint32_t objnum) const32RetainPtr<const CPDF_Object> CPDF_IndirectObjectHolder::GetIndirectObject( 33 uint32_t objnum) const { 34 return pdfium::WrapRetain(GetIndirectObjectInternal(objnum)); 35 } 36 GetMutableIndirectObject(uint32_t objnum)37RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetMutableIndirectObject( 38 uint32_t objnum) { 39 return pdfium::WrapRetain( 40 const_cast<CPDF_Object*>(GetIndirectObjectInternal(objnum))); 41 } 42 GetIndirectObjectInternal(uint32_t objnum) const43const CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObjectInternal( 44 uint32_t objnum) const { 45 auto it = m_IndirectObjs.find(objnum); 46 if (it == m_IndirectObjs.end()) 47 return nullptr; 48 49 return FilterInvalidObjNum(it->second.Get()); 50 } 51 GetOrParseIndirectObject(uint32_t objnum)52RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetOrParseIndirectObject( 53 uint32_t objnum) { 54 return pdfium::WrapRetain(GetOrParseIndirectObjectInternal(objnum)); 55 } 56 GetOrParseIndirectObjectInternal(uint32_t objnum)57CPDF_Object* CPDF_IndirectObjectHolder::GetOrParseIndirectObjectInternal( 58 uint32_t objnum) { 59 if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum) 60 return nullptr; 61 62 // Add item anyway to prevent recursively parsing of same object. 63 auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr)); 64 if (!insert_result.second) { 65 return const_cast<CPDF_Object*>( 66 FilterInvalidObjNum(insert_result.first->second.Get())); 67 } 68 RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum); 69 if (!pNewObj) { 70 m_IndirectObjs.erase(insert_result.first); 71 return nullptr; 72 } 73 74 pNewObj->SetObjNum(objnum); 75 m_LastObjNum = std::max(m_LastObjNum, objnum); 76 77 CPDF_Object* result = pNewObj.Get(); 78 insert_result.first->second = std::move(pNewObj); 79 return result; 80 } 81 ParseIndirectObject(uint32_t objnum)82RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject( 83 uint32_t objnum) { 84 return nullptr; 85 } 86 AddIndirectObject(RetainPtr<CPDF_Object> pObj)87uint32_t CPDF_IndirectObjectHolder::AddIndirectObject( 88 RetainPtr<CPDF_Object> pObj) { 89 CHECK(!pObj->GetObjNum()); 90 pObj->SetObjNum(++m_LastObjNum); 91 m_IndirectObjs[m_LastObjNum] = std::move(pObj); 92 return m_LastObjNum; 93 } 94 ReplaceIndirectObjectIfHigherGeneration(uint32_t objnum,RetainPtr<CPDF_Object> pObj)95bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration( 96 uint32_t objnum, 97 RetainPtr<CPDF_Object> pObj) { 98 DCHECK(objnum); 99 if (!pObj || objnum == CPDF_Object::kInvalidObjNum) 100 return false; 101 102 auto& obj_holder = m_IndirectObjs[objnum]; 103 const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.Get()); 104 if (old_object && pObj->GetGenNum() <= old_object->GetGenNum()) 105 return false; 106 107 pObj->SetObjNum(objnum); 108 obj_holder = std::move(pObj); 109 m_LastObjNum = std::max(m_LastObjNum, objnum); 110 return true; 111 } 112 DeleteIndirectObject(uint32_t objnum)113void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) { 114 auto it = m_IndirectObjs.find(objnum); 115 if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second.Get())) 116 return; 117 118 m_IndirectObjs.erase(it); 119 } 120