blob: 539aae5aa0378b58240cdcf91daa6bfb36139994 [file] [log] [blame]
// Copyright 2016 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "third_party/base/check.h"
namespace {
RetainPtr<CPDF_Object> FilterInvalidObjNum(RetainPtr<CPDF_Object> obj) {
return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
}
} // namespace
CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
: m_pByteStringPool(std::make_unique<ByteStringPool>()) {}
CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
m_pByteStringPool.DeleteObject(); // Make weak.
}
RetainPtr<const CPDF_Object> CPDF_IndirectObjectHolder::GetIndirectObject(
uint32_t objnum) const {
return const_cast<CPDF_IndirectObjectHolder*>(this)->GetMutableIndirectObject(
objnum);
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetMutableIndirectObject(
uint32_t objnum) {
auto it = m_IndirectObjs.find(objnum);
if (it == m_IndirectObjs.end())
return nullptr;
return FilterInvalidObjNum(it->second);
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::GetOrParseIndirectObject(
uint32_t objnum) {
if (objnum == 0 || objnum == CPDF_Object::kInvalidObjNum)
return nullptr;
// Add item anyway to prevent recursively parsing of same object.
auto insert_result = m_IndirectObjs.insert(std::make_pair(objnum, nullptr));
if (!insert_result.second)
return FilterInvalidObjNum(insert_result.first->second);
RetainPtr<CPDF_Object> pNewObj = ParseIndirectObject(objnum);
if (!pNewObj) {
m_IndirectObjs.erase(insert_result.first);
return nullptr;
}
pNewObj->SetObjNum(objnum);
m_LastObjNum = std::max(m_LastObjNum, objnum);
insert_result.first->second = pNewObj;
return pNewObj;
}
RetainPtr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
uint32_t objnum) {
return nullptr;
}
CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject(
RetainPtr<CPDF_Object> pObj) {
CHECK(!pObj->GetObjNum());
pObj->SetObjNum(++m_LastObjNum);
auto& obj_holder = m_IndirectObjs[m_LastObjNum];
obj_holder = std::move(pObj);
return obj_holder.Get();
}
bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration(
uint32_t objnum,
RetainPtr<CPDF_Object> pObj) {
DCHECK(objnum);
if (!pObj || objnum == CPDF_Object::kInvalidObjNum)
return false;
auto& obj_holder = m_IndirectObjs[objnum];
RetainPtr<const CPDF_Object> old_object = FilterInvalidObjNum(obj_holder);
if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
return false;
pObj->SetObjNum(objnum);
obj_holder = std::move(pObj);
m_LastObjNum = std::max(m_LastObjNum, objnum);
return true;
}
void CPDF_IndirectObjectHolder::DeleteIndirectObject(uint32_t objnum) {
auto it = m_IndirectObjs.find(objnum);
if (it == m_IndirectObjs.end() || !FilterInvalidObjNum(it->second))
return;
m_IndirectObjs.erase(it);
}