blob: 42e312ca64315c0c6499244c7faac7d546d9410e [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 <utility>
#include "core/fpdfapi/parser/cpdf_object.h"
#include "core/fpdfapi/parser/cpdf_parser.h"
#include "third_party/base/logging.h"
namespace {
CPDF_Object* FilterInvalidObjNum(CPDF_Object* obj) {
return obj && obj->GetObjNum() != CPDF_Object::kInvalidObjNum ? obj : nullptr;
}
} // namespace
CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder()
: m_LastObjNum(0),
m_pByteStringPool(pdfium::MakeUnique<ByteStringPool>()) {}
CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
m_pByteStringPool.DeleteObject(); // Make weak.
}
CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(
uint32_t objnum) const {
auto it = m_IndirectObjs.find(objnum);
return (it != m_IndirectObjs.end()) ? FilterInvalidObjNum(it->second.get())
: nullptr;
}
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.get());
std::unique_ptr<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 = std::move(pNewObj);
return insert_result.first->second.get();
}
std::unique_ptr<CPDF_Object> CPDF_IndirectObjectHolder::ParseIndirectObject(
uint32_t objnum) {
return nullptr;
}
CPDF_Object* CPDF_IndirectObjectHolder::AddIndirectObject(
std::unique_ptr<CPDF_Object> pObj) {
CHECK(!pObj->GetObjNum());
pObj->SetObjNum(++m_LastObjNum);
auto& obj_holder = m_IndirectObjs[m_LastObjNum];
if (obj_holder)
m_OrphanObjs.push_back(std::move(obj_holder));
obj_holder = std::move(pObj);
return obj_holder.get();
}
bool CPDF_IndirectObjectHolder::ReplaceIndirectObjectIfHigherGeneration(
uint32_t objnum,
std::unique_ptr<CPDF_Object> pObj) {
ASSERT(objnum);
if (!pObj || objnum == CPDF_Object::kInvalidObjNum)
return false;
auto& obj_holder = m_IndirectObjs[objnum];
const CPDF_Object* old_object = FilterInvalidObjNum(obj_holder.get());
if (old_object && pObj->GetGenNum() <= old_object->GetGenNum())
return false;
pObj->SetObjNum(objnum);
if (obj_holder)
m_OrphanObjs.push_back(std::move(obj_holder));
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.get()))
return;
m_IndirectObjs.erase(it);
}