diff options
Diffstat (limited to 'core/fpdfapi/parser/cpdf_cross_ref_table.cpp')
-rw-r--r-- | core/fpdfapi/parser/cpdf_cross_ref_table.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp new file mode 100644 index 0000000000..770c483dca --- /dev/null +++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp @@ -0,0 +1,129 @@ +// Copyright 2018 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. + +#include "core/fpdfapi/parser/cpdf_cross_ref_table.h" + +#include <utility> + +#include "core/fpdfapi/parser/cpdf_dictionary.h" + +CPDF_CrossRefTable::CPDF_CrossRefTable() = default; + +CPDF_CrossRefTable::CPDF_CrossRefTable(std::unique_ptr<CPDF_Dictionary> trailer) + : trailer_(std::move(trailer)) {} + +CPDF_CrossRefTable::~CPDF_CrossRefTable() = default; + +void CPDF_CrossRefTable::AddCompressed(uint32_t obj_num, + uint32_t archive_obj_num) { + auto& info = objects_info_[obj_num]; + if (info.gennum > 0) + return; + + if (info.type == ObjectType::kObjStream) + return; + + info.type = ObjectType::kCompressed; + info.archive_obj_num = archive_obj_num; + info.gennum = 0; + + objects_info_[archive_obj_num].type = ObjectType::kObjStream; +} + +void CPDF_CrossRefTable::AddNormal(uint32_t obj_num, + uint16_t gen_num, + FX_FILESIZE pos) { + auto& info = objects_info_[obj_num]; + if (info.gennum > gen_num) + return; + + if (info.type == ObjectType::kCompressed && gen_num == 0) + return; + + if (info.type != ObjectType::kObjStream) + info.type = ObjectType::kNormal; + + info.gennum = gen_num; + info.pos = pos; +} + +void CPDF_CrossRefTable::SetFree(uint32_t obj_num) { + auto& info = objects_info_[obj_num]; + info.type = ObjectType::kFree; + info.gennum = 0xFFFF; + info.pos = 0; +} + +void CPDF_CrossRefTable::SetTrailer(std::unique_ptr<CPDF_Dictionary> trailer) { + trailer_ = std::move(trailer); +} + +const CPDF_CrossRefTable::ObjectInfo* CPDF_CrossRefTable::GetObjectInfo( + uint32_t obj_num) const { + const auto it = objects_info_.find(obj_num); + return it != objects_info_.end() ? &it->second : nullptr; +} + +void CPDF_CrossRefTable::Update( + std::unique_ptr<CPDF_CrossRefTable> new_cross_ref) { + UpdateInfo(std::move(new_cross_ref->objects_info_)); + UpdateTrailer(std::move(new_cross_ref->trailer_)); +} + +void CPDF_CrossRefTable::ShrinkObjectMap(uint32_t objnum) { + if (objnum == 0) { + objects_info_.clear(); + return; + } + + objects_info_.erase(objects_info_.lower_bound(objnum), objects_info_.end()); + + if (!pdfium::ContainsKey(objects_info_, objnum - 1)) + objects_info_[objnum - 1].pos = 0; +} + +void CPDF_CrossRefTable::UpdateInfo( + std::map<uint32_t, ObjectInfo>&& new_objects_info) { + auto cur_it = objects_info_.begin(); + auto new_it = new_objects_info.begin(); + while (cur_it != objects_info_.end() && new_it != new_objects_info.end()) { + if (cur_it->first == new_it->first) { + if (cur_it->second.type == ObjectType::kObjStream && + new_it->second.type == ObjectType::kNormal) { + new_it->second.type = ObjectType::kObjStream; + } + ++cur_it; + ++new_it; + } else if (cur_it->first < new_it->first) { + new_objects_info.insert(new_it, *cur_it); + ++cur_it; + } else { + new_it = new_objects_info.lower_bound(cur_it->first); + } + } + for (; cur_it != objects_info_.end(); ++cur_it) { + new_objects_info.insert(new_objects_info.end(), *cur_it); + } + objects_info_ = std::move(new_objects_info); +} + +void CPDF_CrossRefTable::UpdateTrailer( + std::unique_ptr<CPDF_Dictionary> new_trailer) { + if (!new_trailer) + return; + + if (!trailer_) { + trailer_ = std::move(new_trailer); + return; + } + + new_trailer->SetFor("XRefStm", trailer_->RemoveFor("XRefStm")); + new_trailer->SetFor("Prev", trailer_->RemoveFor("Prev")); + + for (auto it = new_trailer->begin(); it != new_trailer->end();) { + const ByteString key = it->first; + ++it; + trailer_->SetFor(key, new_trailer->RemoveFor(key)); + } +} |