diff options
author | Artem Strygin <art-snake@yandex-team.ru> | 2018-06-27 17:52:40 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-06-27 17:52:40 +0000 |
commit | 9e12f14814722c0c0d46d4968f636b5e1a72a1e7 (patch) | |
tree | 540394b17d4f94227bec1064ebedbd475f88a26c /core/fpdfapi/parser/cpdf_cross_ref_table.cpp | |
parent | 2d7cb9267899902ce455165303e2373ac38c867d (diff) | |
download | pdfium-9e12f14814722c0c0d46d4968f636b5e1a72a1e7.tar.xz |
Implement CPDF_CrossRefTable
Change-Id: I5ac61ab323adb5eec2de8660064fff95ee877b5e
Reviewed-on: https://pdfium-review.googlesource.com/35432
Reviewed-by: dsinclair <dsinclair@chromium.org>
Commit-Queue: Art Snake <art-snake@yandex-team.ru>
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)); + } +} |