Home | History | Annotate | Download | only in parser
      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 
     18 CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) {
     19   return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
     20 }
     21 
     22 }  // namespace
     23 
     24 CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
     25     : m_LastObjNum(0),
     26       m_pByteStringPool(pdfium::MakeUnique<ByteStringPool>()) {}
     27 
     28 CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
     29   m_pByteStringPool.DeleteObject();  // Make weak.
     30 }
     31 
     32 CPDF_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 
     39 CPDF_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 
     61 std::unique_ptr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
     62     uint32_t objnum) {
     63   return nullptr;
     64 }
     65 
     66 CPDF_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 
     79 bool 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 
    100 void 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