Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_dictionary.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fpdfapi/parser/cpdf_dictionary.h"
8
9#include <set>
10#include <utility>
11
12#include "core/fpdfapi/parser/cpdf_array.h"
13#include "core/fpdfapi/parser/cpdf_boolean.h"
14#include "core/fpdfapi/parser/cpdf_crypto_handler.h"
15#include "core/fpdfapi/parser/cpdf_name.h"
16#include "core/fpdfapi/parser/cpdf_number.h"
17#include "core/fpdfapi/parser/cpdf_reference.h"
18#include "core/fpdfapi/parser/cpdf_stream.h"
19#include "core/fpdfapi/parser/cpdf_string.h"
20#include "core/fpdfapi/parser/fpdf_parser_utility.h"
21#include "core/fxcrt/fx_stream.h"
22#include "third_party/base/check.h"
23#include "third_party/base/containers/contains.h"
24
25CPDF_Dictionary::CPDF_Dictionary()
26 : CPDF_Dictionary(WeakPtr<ByteStringPool>()) {}
27
28CPDF_Dictionary::CPDF_Dictionary(const WeakPtr<ByteStringPool>& pPool)
29 : m_pPool(pPool) {}
30
31CPDF_Dictionary::~CPDF_Dictionary() {
32 // Mark the object as deleted so that it will not be deleted again,
33 // and break cyclic references.
35 for (auto& it : m_Map) {
36 if (it.second->GetObjNum() == kInvalidObjNum)
37 it.second.Leak();
38 }
39}
40
41CPDF_Object::Type CPDF_Dictionary::GetType() const {
42 return kDictionary;
43}
44
45CPDF_Dictionary* CPDF_Dictionary::AsMutableDictionary() {
46 return this;
47}
48
49RetainPtr<CPDF_Object> CPDF_Dictionary::Clone() const {
50 return CloneObjectNonCyclic(false);
51}
52
54 bool bDirect,
55 std::set<const CPDF_Object*>* pVisited) const {
56 pVisited->insert(this);
57 auto pCopy = pdfium::MakeRetain<CPDF_Dictionary>(m_pPool);
58 CPDF_DictionaryLocker locker(this);
59 for (const auto& it : locker) {
60 if (!pdfium::Contains(*pVisited, it.second.Get())) {
61 std::set<const CPDF_Object*> visited(*pVisited);
62 auto obj = it.second->CloneNonCyclic(bDirect, &visited);
63 if (obj)
64 pCopy->m_Map.insert(std::make_pair(it.first, std::move(obj)));
65 }
66 }
67 return pCopy;
68}
69
70const CPDF_Object* CPDF_Dictionary::GetObjectForInternal(
71 const ByteString& key) const {
72 auto it = m_Map.find(key);
73 return it != m_Map.end() ? it->second.Get() : nullptr;
74}
75
76RetainPtr<const CPDF_Object> CPDF_Dictionary::GetObjectFor(
77 const ByteString& key) const {
78 return pdfium::WrapRetain(GetObjectForInternal(key));
79}
80
82 const ByteString& key) {
83 return pdfium::WrapRetain(
84 const_cast<CPDF_Object*>(GetObjectForInternal(key)));
85}
86
87const CPDF_Object* CPDF_Dictionary::GetDirectObjectForInternal(
88 const ByteString& key) const {
89 const CPDF_Object* p = GetObjectForInternal(key);
90 return p ? p->GetDirectInternal() : nullptr;
91}
92
94 const ByteString& key) const {
95 return pdfium::WrapRetain(GetDirectObjectForInternal(key));
96}
97
99 const ByteString& key) {
100 return pdfium::WrapRetain(
101 const_cast<CPDF_Object*>(GetDirectObjectForInternal(key)));
102}
103
104ByteString CPDF_Dictionary::GetByteStringFor(const ByteString& key) const {
105 const CPDF_Object* p = GetObjectForInternal(key);
106 return p ? p->GetString() : ByteString();
107}
108
109ByteString CPDF_Dictionary::GetByteStringFor(const ByteString& key,
110 const ByteString& def) const {
111 const CPDF_Object* p = GetObjectForInternal(key);
112 return p ? p->GetString() : ByteString(def);
113}
114
115WideString CPDF_Dictionary::GetUnicodeTextFor(const ByteString& key) const {
116 const CPDF_Object* p = GetObjectForInternal(key);
117 if (const CPDF_Reference* pRef = ToReference(p))
118 p = pRef->GetDirectInternal();
119 return p ? p->GetUnicodeText() : WideString();
120}
121
122ByteString CPDF_Dictionary::GetNameFor(const ByteString& key) const {
123 const CPDF_Name* p = ToName(GetObjectForInternal(key));
124 return p ? p->GetString() : ByteString();
125}
126
127bool CPDF_Dictionary::GetBooleanFor(const ByteString& key,
128 bool bDefault) const {
129 const CPDF_Object* p = GetObjectForInternal(key);
130 return ToBoolean(p) ? p->GetInteger() != 0 : bDefault;
131}
132
133int CPDF_Dictionary::GetIntegerFor(const ByteString& key) const {
134 const CPDF_Object* p = GetObjectForInternal(key);
135 return p ? p->GetInteger() : 0;
136}
137
138int CPDF_Dictionary::GetIntegerFor(const ByteString& key, int def) const {
139 const CPDF_Object* p = GetObjectForInternal(key);
140 return p ? p->GetInteger() : def;
141}
142
143int CPDF_Dictionary::GetDirectIntegerFor(const ByteString& key) const {
144 const CPDF_Number* p = ToNumber(GetObjectForInternal(key));
145 return p ? p->GetInteger() : 0;
146}
147
148float CPDF_Dictionary::GetFloatFor(const ByteString& key) const {
149 const CPDF_Object* p = GetObjectForInternal(key);
150 return p ? p->GetNumber() : 0;
151}
152
153const CPDF_Dictionary* CPDF_Dictionary::GetDictInternal() const {
154 return this;
155}
156
157const CPDF_Dictionary* CPDF_Dictionary::GetDictForInternal(
158 const ByteString& key) const {
159 const CPDF_Object* p = GetDirectObjectForInternal(key);
160 return p ? p->GetDictInternal() : nullptr;
161}
162
163RetainPtr<const CPDF_Dictionary> CPDF_Dictionary::GetDictFor(
164 const ByteString& key) const {
165 return pdfium::WrapRetain(GetDictForInternal(key));
166}
167
168RetainPtr<CPDF_Dictionary> CPDF_Dictionary::GetMutableDictFor(
169 const ByteString& key) {
170 return pdfium::WrapRetain(
171 const_cast<CPDF_Dictionary*>(GetDictForInternal(key)));
172}
173
174RetainPtr<CPDF_Dictionary> CPDF_Dictionary::GetOrCreateDictFor(
175 const ByteString& key) {
176 RetainPtr<CPDF_Dictionary> result = GetMutableDictFor(key);
177 if (result)
178 return result;
179 return SetNewFor<CPDF_Dictionary>(key);
180}
181
182const CPDF_Array* CPDF_Dictionary::GetArrayForInternal(
183 const ByteString& key) const {
184 return ToArray(GetDirectObjectForInternal(key));
185}
186
187RetainPtr<const CPDF_Array> CPDF_Dictionary::GetArrayFor(
188 const ByteString& key) const {
189 return pdfium::WrapRetain(GetArrayForInternal(key));
190}
191
192RetainPtr<CPDF_Array> CPDF_Dictionary::GetMutableArrayFor(
193 const ByteString& key) {
194 return pdfium::WrapRetain(const_cast<CPDF_Array*>(GetArrayForInternal(key)));
195}
196
197RetainPtr<CPDF_Array> CPDF_Dictionary::GetOrCreateArrayFor(
198 const ByteString& key) {
199 RetainPtr<CPDF_Array> result = GetMutableArrayFor(key);
200 if (result)
201 return result;
202 return SetNewFor<CPDF_Array>(key);
203}
204
205const CPDF_Stream* CPDF_Dictionary::GetStreamForInternal(
206 const ByteString& key) const {
207 return ToStream(GetDirectObjectForInternal(key));
208}
209
210RetainPtr<const CPDF_Stream> CPDF_Dictionary::GetStreamFor(
211 const ByteString& key) const {
212 return pdfium::WrapRetain(GetStreamForInternal(key));
213}
214
215RetainPtr<CPDF_Stream> CPDF_Dictionary::GetMutableStreamFor(
216 const ByteString& key) {
217 return pdfium::WrapRetain(
218 const_cast<CPDF_Stream*>(GetStreamForInternal(key)));
219}
220
221const CPDF_Number* CPDF_Dictionary::GetNumberForInternal(
222 const ByteString& key) const {
223 return ToNumber(GetObjectForInternal(key));
224}
225
226RetainPtr<const CPDF_Number> CPDF_Dictionary::GetNumberFor(
227 const ByteString& key) const {
228 return pdfium::WrapRetain(GetNumberForInternal(key));
229}
230
231const CPDF_String* CPDF_Dictionary::GetStringForInternal(
232 const ByteString& key) const {
233 return ToString(GetObjectForInternal(key));
234}
235
236RetainPtr<const CPDF_String> CPDF_Dictionary::GetStringFor(
237 const ByteString& key) const {
238 return pdfium::WrapRetain(GetStringForInternal(key));
239}
240
241CFX_FloatRect CPDF_Dictionary::GetRectFor(const ByteString& key) const {
242 const CPDF_Array* pArray = GetArrayForInternal(key);
243 if (pArray)
244 return pArray->GetRect();
245 return CFX_FloatRect();
246}
247
248CFX_Matrix CPDF_Dictionary::GetMatrixFor(const ByteString& key) const {
249 const CPDF_Array* pArray = GetArrayForInternal(key);
250 if (pArray)
251 return pArray->GetMatrix();
252 return CFX_Matrix();
253}
254
255bool CPDF_Dictionary::KeyExist(const ByteString& key) const {
256 return pdfium::Contains(m_Map, key);
257}
258
259std::vector<ByteString> CPDF_Dictionary::GetKeys() const {
260 std::vector<ByteString> result;
261 CPDF_DictionaryLocker locker(this);
262 for (const auto& item : locker)
263 result.push_back(item.first);
264 return result;
265}
266
267void CPDF_Dictionary::SetFor(const ByteString& key,
268 RetainPtr<CPDF_Object> object) {
269 (void)SetForInternal(key, std::move(object));
270}
271
272CPDF_Object* CPDF_Dictionary::SetForInternal(const ByteString& key,
273 RetainPtr<CPDF_Object> pObj) {
275 if (!pObj) {
276 m_Map.erase(key);
277 return nullptr;
278 }
279 CHECK(pObj->IsInline());
280 CHECK(!pObj->IsStream());
281 CPDF_Object* pRet = pObj.Get();
282 m_Map[MaybeIntern(key)] = std::move(pObj);
283 return pRet;
284}
285
286void CPDF_Dictionary::ConvertToIndirectObjectFor(
287 const ByteString& key,
288 CPDF_IndirectObjectHolder* pHolder) {
290 auto it = m_Map.find(key);
291 if (it == m_Map.end() || it->second->IsReference())
292 return;
293
294 pHolder->AddIndirectObject(it->second);
295 it->second = it->second->MakeReference(pHolder);
296}
297
298RetainPtr<CPDF_Object> CPDF_Dictionary::RemoveFor(ByteStringView key) {
300 RetainPtr<CPDF_Object> result;
301 auto it = m_Map.find(key);
302 if (it != m_Map.end()) {
303 result = std::move(it->second);
304 m_Map.erase(it);
305 }
306 return result;
307}
308
309void CPDF_Dictionary::ReplaceKey(const ByteString& oldkey,
310 const ByteString& newkey) {
312 auto old_it = m_Map.find(oldkey);
313 if (old_it == m_Map.end())
314 return;
315
316 auto new_it = m_Map.find(newkey);
317 if (new_it == old_it)
318 return;
319
320 m_Map[MaybeIntern(newkey)] = std::move(old_it->second);
321 m_Map.erase(old_it);
322}
323
324void CPDF_Dictionary::SetRectFor(const ByteString& key,
325 const CFX_FloatRect& rect) {
326 auto pArray = SetNewFor<CPDF_Array>(key);
327 pArray->AppendNew<CPDF_Number>(rect.left);
328 pArray->AppendNew<CPDF_Number>(rect.bottom);
329 pArray->AppendNew<CPDF_Number>(rect.right);
330 pArray->AppendNew<CPDF_Number>(rect.top);
331}
332
333void CPDF_Dictionary::SetMatrixFor(const ByteString& key,
334 const CFX_Matrix& matrix) {
335 auto pArray = SetNewFor<CPDF_Array>(key);
336 pArray->AppendNew<CPDF_Number>(matrix.a);
337 pArray->AppendNew<CPDF_Number>(matrix.b);
338 pArray->AppendNew<CPDF_Number>(matrix.c);
339 pArray->AppendNew<CPDF_Number>(matrix.d);
340 pArray->AppendNew<CPDF_Number>(matrix.e);
341 pArray->AppendNew<CPDF_Number>(matrix.f);
342}
343
344ByteString CPDF_Dictionary::MaybeIntern(const ByteString& str) {
345 return m_pPool ? m_pPool->Intern(str) : str;
346}
347
348bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive,
349 const CPDF_Encryptor* encryptor) const {
350 if (!archive->WriteString("<<"))
351 return false;
352
353 const bool is_signature = CPDF_CryptoHandler::IsSignatureDictionary(this);
354
355 CPDF_DictionaryLocker locker(this);
356 for (const auto& it : locker) {
357 const ByteString& key = it.first;
358 const RetainPtr<CPDF_Object>& pValue = it.second;
359 if (!archive->WriteString("/") ||
360 !archive->WriteString(PDF_NameEncode(key).AsStringView())) {
361 return false;
362 }
363 if (!pValue->WriteTo(archive, !is_signature || key != "Contents"
364 ? encryptor
365 : nullptr)) {
366 return false;
367 }
368 }
369 return archive->WriteString(">>");
370}
371
372CPDF_DictionaryLocker::CPDF_DictionaryLocker(const CPDF_Dictionary* pDictionary)
374 m_pDictionary->m_LockCount++;
375}
376
378 RetainPtr<CPDF_Dictionary> pDictionary)
380 m_pDictionary->m_LockCount++;
381}
382
384 RetainPtr<const CPDF_Dictionary> pDictionary)
386 m_pDictionary->m_LockCount++;
387}
388
390 m_pDictionary->m_LockCount--;
391}
constexpr CFX_FloatRect()=default
CFX_Matrix()=default
CFX_Matrix GetMatrix() const
CFX_FloatRect GetRect() const
static bool IsSignatureDictionary(const CPDF_Dictionary *dictionary)
CPDF_DictionaryLocker(const CPDF_Dictionary *pDictionary)
CPDF_DictionaryLocker(RetainPtr< const CPDF_Dictionary > pDictionary)
CPDF_DictionaryLocker(RetainPtr< CPDF_Dictionary > pDictionary)
Type GetType() const override
bool KeyExist(const ByteString &key) const
int GetIntegerFor(const ByteString &key) const
RetainPtr< const CPDF_Stream > GetStreamFor(const ByteString &key) const
RetainPtr< const CPDF_Number > GetNumberFor(const ByteString &key) const
void SetFor(const ByteString &key, RetainPtr< CPDF_Object > object)
ByteString GetByteStringFor(const ByteString &key, const ByteString &default_str) const
RetainPtr< CPDF_Object > RemoveFor(ByteStringView key)
RetainPtr< CPDF_Array > GetOrCreateArrayFor(const ByteString &key)
void SetMatrixFor(const ByteString &key, const CFX_Matrix &matrix)
RetainPtr< CPDF_Stream > GetMutableStreamFor(const ByteString &key)
RetainPtr< CPDF_Object > GetMutableDirectObjectFor(const ByteString &key)
RetainPtr< const CPDF_Dictionary > GetDictFor(const ByteString &key) const
RetainPtr< CPDF_Array > GetMutableArrayFor(const ByteString &key)
float GetFloatFor(const ByteString &key) const
RetainPtr< CPDF_Dictionary > GetOrCreateDictFor(const ByteString &key)
void ConvertToIndirectObjectFor(const ByteString &key, CPDF_IndirectObjectHolder *pHolder)
WideString GetUnicodeTextFor(const ByteString &key) const
RetainPtr< CPDF_Object > Clone() const override
const CPDF_Dictionary * GetDictInternal() const override
RetainPtr< CPDF_Object > CloneNonCyclic(bool bDirect, std::set< const CPDF_Object * > *visited) const override
CPDF_Dictionary * AsMutableDictionary() override
std::vector< ByteString > GetKeys() const
bool GetBooleanFor(const ByteString &key, bool bDefault) const
ByteString GetByteStringFor(const ByteString &key) const
int GetDirectIntegerFor(const ByteString &key) const
RetainPtr< const CPDF_String > GetStringFor(const ByteString &key) const
void SetRectFor(const ByteString &key, const CFX_FloatRect &rect)
RetainPtr< CPDF_Dictionary > GetMutableDictFor(const ByteString &key)
RetainPtr< const CPDF_Object > GetDirectObjectFor(const ByteString &key) const
bool WriteTo(IFX_ArchiveStream *archive, const CPDF_Encryptor *encryptor) const override
RetainPtr< const CPDF_Array > GetArrayFor(const ByteString &key) const
RetainPtr< const CPDF_Object > GetObjectFor(const ByteString &key) const
int GetIntegerFor(const ByteString &key, int default_int) const
~CPDF_Dictionary() override
bool IsLocked() const
CFX_FloatRect GetRectFor(const ByteString &key) const
ByteString GetNameFor(const ByteString &key) const
CFX_Matrix GetMatrixFor(const ByteString &key) const
RetainPtr< CPDF_Object > GetMutableObjectFor(const ByteString &key)
void ReplaceKey(const ByteString &oldkey, const ByteString &newkey)
uint32_t AddIndirectObject(RetainPtr< CPDF_Object > pObj)
ByteString GetString() const override
Definition cpdf_name.cpp:29
int GetInteger() const override
virtual WideString GetUnicodeText() const
virtual ByteString GetString() const
virtual int GetInteger() const
virtual float GetNumber() const
uint32_t m_ObjNum
static constexpr uint32_t kInvalidObjNum
Definition cpdf_object.h:52
virtual const CPDF_Object * GetDirectInternal() const
RetainPtr< CPDF_Object > CloneObjectNonCyclic(bool bDirect) const
virtual const CPDF_Dictionary * GetDictInternal() const
const CPDF_Object * GetDirectInternal() const override
bool WriteString(ByteStringView str)
Definition fx_stream.cpp:47
ByteString(const ByteString &other)
const CPDF_Array * ToArray(const CPDF_Object *obj)
Definition cpdf_array.h:193
const CPDF_Boolean * ToBoolean(const CPDF_Object *obj)
const CPDF_Name * ToName(const CPDF_Object *obj)
Definition cpdf_name.h:40
const CPDF_Number * ToNumber(const CPDF_Object *obj)
Definition cpdf_number.h:46
const CPDF_Reference * ToReference(const CPDF_Object *obj)
const CPDF_Stream * ToStream(const CPDF_Object *obj)
const CPDF_String * ToString(const CPDF_Object *obj)
Definition cpdf_string.h:47
#define CHECK(cvref)