blob: 770c483dcaf0f129b881bc02f66bd03fadf3e0ac (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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));
}
}
|