• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)19 CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) {
20   return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
21 }
22 
23 }  // namespace
24 
CPDF_IndirectObjectHolder()25 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
26     : m_LastObjNum(0),
27       m_pByteStringPool(pdfium::MakeUnique<ByteStringPool>()) {}
28 
~CPDF_IndirectObjectHolder()29 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
30   m_pByteStringPool.DeleteObject();  // Make weak.
31 }
32 
GetIndirectObject(uint32_t objnum) const33 CPDF_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)40 CPDF_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)62 RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
63     uint32_t objnum) {
64   return nullptr;
65 }
66 
AddIndirectObject(RetainPtr<CPDF_Object> pObj)67 CPDF_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)77 bool 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)95 void 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