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_object_unittest.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#include "core/fpdfapi/parser/cpdf_object.h"
6
7#include <stdint.h>
8
9#include <memory>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "constants/stream_dict_common.h"
15#include "core/fpdfapi/parser/cpdf_array.h"
16#include "core/fpdfapi/parser/cpdf_boolean.h"
17#include "core/fpdfapi/parser/cpdf_dictionary.h"
18#include "core/fpdfapi/parser/cpdf_indirect_object_holder.h"
19#include "core/fpdfapi/parser/cpdf_name.h"
20#include "core/fpdfapi/parser/cpdf_null.h"
21#include "core/fpdfapi/parser/cpdf_number.h"
22#include "core/fpdfapi/parser/cpdf_reference.h"
23#include "core/fpdfapi/parser/cpdf_stream.h"
24#include "core/fpdfapi/parser/cpdf_stream_acc.h"
25#include "core/fpdfapi/parser/cpdf_string.h"
26#include "core/fxcrt/compiler_specific.h"
27#include "core/fxcrt/data_vector.h"
28#include "core/fxcrt/stl_util.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31namespace {
32
33void TestArrayAccessors(const CPDF_Array* arr,
34 size_t index,
35 const char* str_val,
36 const char* const_str_val,
37 int int_val,
38 float float_val,
39 CPDF_Array* arr_val,
40 CPDF_Dictionary* dict_val,
41 CPDF_Stream* stream_val) {
42 EXPECT_EQ(str_val, arr->GetByteStringAt(index));
43 EXPECT_EQ(int_val, arr->GetIntegerAt(index));
44 EXPECT_EQ(float_val, arr->GetFloatAt(index));
45 EXPECT_EQ(arr_val, arr->GetArrayAt(index));
46 EXPECT_EQ(dict_val, arr->GetDictAt(index));
47 EXPECT_EQ(stream_val, arr->GetStreamAt(index));
48}
49
50} // namespace
51
52class PDFObjectsTest : public testing::Test {
53 public:
54 void SetUp() override {
55 // Initialize different kinds of objects.
56 // Boolean objects.
57 auto boolean_false_obj = pdfium::MakeRetain<CPDF_Boolean>(false);
58 auto boolean_true_obj = pdfium::MakeRetain<CPDF_Boolean>(true);
59 // Number objects.
60 auto number_int_obj = pdfium::MakeRetain<CPDF_Number>(1245);
61 auto number_float_obj = pdfium::MakeRetain<CPDF_Number>(9.00345f);
62 // String objects.
63 auto str_reg_obj =
64 pdfium::MakeRetain<CPDF_String>(nullptr, L"A simple test");
65 auto str_spec_obj = pdfium::MakeRetain<CPDF_String>(nullptr, L"\t\n");
66 // Name object.
67 auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "space");
68 // Array object.
69 m_ArrayObj = pdfium::MakeRetain<CPDF_Array>();
70 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902);
71 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address");
72 // Dictionary object.
73 m_DictObj = pdfium::MakeRetain<CPDF_Dictionary>();
74 m_DictObj->SetNewFor<CPDF_Boolean>("bool", false);
75 m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f);
76 // Stream object.
77 static constexpr char kContents[] = "abcdefghijklmnopqrstuvwxyz";
78 auto pNewDict = pdfium::MakeRetain<CPDF_Dictionary>();
79 m_StreamDictObj = pNewDict;
80 m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict");
81 m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1);
82 auto stream_obj = pdfium::MakeRetain<CPDF_Stream>(
83 DataVector<uint8_t>(std::begin(kContents),
84 UNSAFE_TODO(std::end(kContents) - 1)),
85 std::move(pNewDict));
86 // Null Object.
87 auto null_obj = pdfium::MakeRetain<CPDF_Null>();
88 // All direct objects.
89 CPDF_Object* objs[] = {
90 boolean_false_obj.Get(), boolean_true_obj.Get(), number_int_obj.Get(),
91 number_float_obj.Get(), str_reg_obj.Get(), str_spec_obj.Get(),
92 name_obj.Get(), m_ArrayObj.Get(), m_DictObj.Get(),
93 stream_obj.Get(), null_obj.Get()};
94 m_DirectObjTypes = {
95 CPDF_Object::kBoolean, CPDF_Object::kBoolean, CPDF_Object::kNumber,
96 CPDF_Object::kNumber, CPDF_Object::kString, CPDF_Object::kString,
97 CPDF_Object::kName, CPDF_Object::kArray, CPDF_Object::kDictionary,
98 CPDF_Object::kStream, CPDF_Object::kNullobj};
99 for (auto* obj : objs) {
100 m_DirectObjs.emplace_back(obj);
101 }
102 // Indirect references to indirect objects.
103 m_ObjHolder = std::make_unique<CPDF_IndirectObjectHolder>();
104 m_IndirectObjNums = {
105 m_ObjHolder->AddIndirectObject(boolean_true_obj->Clone()),
106 m_ObjHolder->AddIndirectObject(number_int_obj->Clone()),
107 m_ObjHolder->AddIndirectObject(str_spec_obj->Clone()),
108 m_ObjHolder->AddIndirectObject(name_obj->Clone()),
109 m_ObjHolder->AddIndirectObject(m_ArrayObj->Clone()),
110 m_ObjHolder->AddIndirectObject(m_DictObj->Clone()),
111 m_ObjHolder->AddIndirectObject(stream_obj->Clone())};
112 for (uint32_t objnum : m_IndirectObjNums) {
113 m_RefObjs.emplace_back(
114 pdfium::MakeRetain<CPDF_Reference>(m_ObjHolder.get(), objnum));
115 }
116 }
117
118 bool Equal(const CPDF_Object* obj1, const CPDF_Object* obj2) {
119 if (obj1 == obj2)
120 return true;
121 if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType())
122 return false;
123 switch (obj1->GetType()) {
125 return obj1->GetInteger() == obj2->GetInteger();
131 return obj1->GetString() == obj2->GetString();
132 case CPDF_Object::kArray: {
133 const CPDF_Array* array1 = obj1->AsArray();
134 const CPDF_Array* array2 = obj2->AsArray();
135 if (array1->size() != array2->size())
136 return false;
137 for (size_t i = 0; i < array1->size(); ++i) {
138 if (!Equal(array1->GetObjectAt(i).Get(),
139 array2->GetObjectAt(i).Get())) {
140 return false;
141 }
142 }
143 return true;
144 }
146 const CPDF_Dictionary* dict1 = obj1->AsDictionary();
147 const CPDF_Dictionary* dict2 = obj2->AsDictionary();
148 if (dict1->size() != dict2->size())
149 return false;
150 CPDF_DictionaryLocker locker1(dict1);
151 for (const auto& item : locker1) {
152 if (!Equal(item.second.Get(), dict2->GetObjectFor(item.first).Get()))
153 return false;
154 }
155 return true;
156 }
158 return true;
160 RetainPtr<const CPDF_Stream> stream1(obj1->AsStream());
161 RetainPtr<const CPDF_Stream> stream2(obj2->AsStream());
162 // Compare dictionaries.
163 if (!Equal(stream1->GetDict().Get(), stream2->GetDict().Get()))
164 return false;
165
166 auto streamAcc1 =
167 pdfium::MakeRetain<CPDF_StreamAcc>(std::move(stream1));
168 streamAcc1->LoadAllDataRaw();
169 auto streamAcc2 =
170 pdfium::MakeRetain<CPDF_StreamAcc>(std::move(stream2));
171 streamAcc2->LoadAllDataRaw();
172 pdfium::span<const uint8_t> span1 = streamAcc1->GetSpan();
173 pdfium::span<const uint8_t> span2 = streamAcc2->GetSpan();
174
175 // Compare sizes.
176 if (span1.size() != span2.size())
177 return false;
178
179 return memcmp(span1.data(), span2.data(), span2.size()) == 0;
180 }
184 }
185 return false;
186 }
187
188 protected:
189 // m_ObjHolder needs to be declared first and destructed last since it also
190 // refers to some objects in m_DirectObjs.
199};
200
202 constexpr auto direct_obj_results = fxcrt::ToArray<const char*>(
203 {"false", "true", "1245", "9.0034504", "A simple test", "\t\n", "space",
204 "", "", "", ""});
205 // Check for direct objects.
206 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
207 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetString());
208 }
209
210 // Check indirect references.
211 constexpr auto indirect_obj_results = fxcrt::ToArray<const char*>(
212 {"true", "1245", "\t\n", "space", "", "", ""});
213 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
214 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetString());
215 }
216}
217
219 constexpr auto direct_obj_results = fxcrt::ToArray<const wchar_t*>(
220 {L"", L"", L"", L"", L"A simple test", L"\t\n", L"space", L"", L"",
221 L"abcdefghijklmnopqrstuvwxyz", L""});
222 // Check for direct objects.
223 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
224 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetUnicodeText());
225 }
226
227 // Check indirect references.
228 for (const auto& it : m_RefObjs) {
229 EXPECT_EQ(L"", it->GetUnicodeText());
230 }
231}
232
234 constexpr auto direct_obj_results =
235 fxcrt::ToArray<const float>({0, 0, 1245, 9.00345f, 0, 0, 0, 0, 0, 0, 0});
236 // Check for direct objects.
237 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
238 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetNumber());
239 }
240
241 // Check indirect references.
242 constexpr auto indirect_obj_results =
243 fxcrt::ToArray<const float>({0, 1245, 0, 0, 0, 0, 0});
244 for (size_t i = 0; i < m_RefObjs.size(); ++i)
245 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetNumber());
246}
247
249 constexpr auto direct_obj_results =
250 fxcrt::ToArray<const int>({0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0});
251 // Check for direct objects.
252 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
253 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetInteger());
254 }
255
256 // Check indirect references.
257 constexpr auto indirect_obj_results =
258 fxcrt::ToArray<const int>({1, 1245, 0, 0, 0, 0, 0});
259 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
260 EXPECT_EQ(indirect_obj_results[i], m_RefObjs[i]->GetInteger());
261 }
262}
263
265 const auto direct_obj_results = fxcrt::ToArray<const CPDF_Dictionary*>(
266 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
267 m_DictObj.Get(), m_StreamDictObj.Get(), nullptr});
268 // Check for direct objects.
269 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
270 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->GetDict());
271 }
272
273 const auto indirect_obj_results = fxcrt::ToArray<const CPDF_Dictionary*>(
274 {nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj.Get(),
275 m_StreamDictObj.Get()});
276 // Check indirect references.
277 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
278 EXPECT_TRUE(Equal(indirect_obj_results[i], m_RefObjs[i]->GetDict().Get()));
279 }
280}
281
283 m_DictObj->SetNewFor<CPDF_String>("string", "ium");
284 m_DictObj->SetNewFor<CPDF_Name>("name", "Pdf");
285
286 EXPECT_EQ("", m_DictObj->GetNameFor("invalid"));
287 EXPECT_EQ("", m_DictObj->GetNameFor("bool"));
288 EXPECT_EQ("", m_DictObj->GetNameFor("num"));
289 EXPECT_EQ("", m_DictObj->GetNameFor("string"));
290 EXPECT_EQ("Pdf", m_DictObj->GetNameFor("name"));
291
292 EXPECT_EQ("", m_DictObj->GetByteStringFor("invalid"));
293 EXPECT_EQ("false", m_DictObj->GetByteStringFor("bool"));
294 EXPECT_EQ(".23", m_DictObj->GetByteStringFor("num"));
295 EXPECT_EQ("ium", m_DictObj->GetByteStringFor("string"));
296 EXPECT_EQ("Pdf", m_DictObj->GetByteStringFor("name"));
297}
298
300 const auto direct_obj_results = fxcrt::ToArray<const CPDF_Array*>(
301 {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
302 m_ArrayObj.Get(), nullptr, nullptr, nullptr});
303 // Check for direct objects.
304 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
305 EXPECT_EQ(direct_obj_results[i], m_DirectObjs[i]->AsArray());
306 }
307
308 // Check indirect references.
309 for (const auto& it : m_RefObjs) {
310 EXPECT_FALSE(it->AsArray());
311 }
312}
313
315 // Check for direct objects.
316 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
317 RetainPtr<CPDF_Object> obj = m_DirectObjs[i]->Clone();
318 EXPECT_TRUE(Equal(m_DirectObjs[i].Get(), obj.Get()));
319 }
320
321 // Check indirect references.
322 for (const auto& it : m_RefObjs) {
323 RetainPtr<CPDF_Object> obj = it->Clone();
324 EXPECT_TRUE(Equal(it.Get(), obj.Get()));
325 }
326}
327
329 // Check for direct objects.
330 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
331 EXPECT_EQ(m_DirectObjTypes[i], m_DirectObjs[i]->GetType());
332
333 // Check indirect references.
334 for (const auto& it : m_RefObjs)
335 EXPECT_EQ(CPDF_Object::kReference, it->GetType());
336}
337
339 // Check for direct objects.
340 for (size_t i = 0; i < m_DirectObjs.size(); ++i)
341 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->GetDirect());
342
343 // Check indirect references.
344 for (size_t i = 0; i < m_RefObjs.size(); ++i)
345 EXPECT_EQ(m_IndirectObjNums[i], m_RefObjs[i]->GetDirect()->GetObjNum());
346}
347
349 // Check for direct objects.
350 constexpr auto set_values = fxcrt::ToArray<const char*>(
351 {"true", "fake", "3.125f", "097", "changed", "", "NewName"});
352 constexpr auto expected = fxcrt::ToArray<const char*>(
353 {"true", "false", "3.125", "97", "changed", "", "NewName"});
354 for (size_t i = 0; i < std::size(set_values); ++i) {
355 m_DirectObjs[i]->SetString(set_values[i]);
356 EXPECT_EQ(expected[i], m_DirectObjs[i]->GetString());
357 }
358}
359
361 // Check for direct objects.
362 for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
363 if (m_DirectObjTypes[i] == CPDF_Object::kArray) {
364 EXPECT_TRUE(m_DirectObjs[i]->IsArray());
365 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsArray());
366 } else {
367 EXPECT_FALSE(m_DirectObjs[i]->IsArray());
368 EXPECT_FALSE(m_DirectObjs[i]->AsArray());
369 }
370
371 if (m_DirectObjTypes[i] == CPDF_Object::kBoolean) {
372 EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
373 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsBoolean());
374 } else {
375 EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
376 EXPECT_FALSE(m_DirectObjs[i]->AsBoolean());
377 }
378
379 if (m_DirectObjTypes[i] == CPDF_Object::kName) {
380 EXPECT_TRUE(m_DirectObjs[i]->IsName());
381 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsName());
382 } else {
383 EXPECT_FALSE(m_DirectObjs[i]->IsName());
384 EXPECT_FALSE(m_DirectObjs[i]->AsName());
385 }
386
387 if (m_DirectObjTypes[i] == CPDF_Object::kNumber) {
388 EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
389 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsNumber());
390 } else {
391 EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
392 EXPECT_FALSE(m_DirectObjs[i]->AsNumber());
393 }
394
395 if (m_DirectObjTypes[i] == CPDF_Object::kString) {
396 EXPECT_TRUE(m_DirectObjs[i]->IsString());
397 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsString());
398 } else {
399 EXPECT_FALSE(m_DirectObjs[i]->IsString());
400 EXPECT_FALSE(m_DirectObjs[i]->AsString());
401 }
402
403 if (m_DirectObjTypes[i] == CPDF_Object::kDictionary) {
404 EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
405 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsDictionary());
406 } else {
407 EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
408 EXPECT_FALSE(m_DirectObjs[i]->AsDictionary());
409 }
410
411 if (m_DirectObjTypes[i] == CPDF_Object::kStream) {
412 EXPECT_TRUE(m_DirectObjs[i]->IsStream());
413 EXPECT_EQ(m_DirectObjs[i].Get(), m_DirectObjs[i]->AsStream());
414 } else {
415 EXPECT_FALSE(m_DirectObjs[i]->IsStream());
416 EXPECT_FALSE(m_DirectObjs[i]->AsStream());
417 }
418
419 EXPECT_FALSE(m_DirectObjs[i]->IsReference());
420 EXPECT_FALSE(m_DirectObjs[i]->AsReference());
421 }
422 // Check indirect references.
423 for (size_t i = 0; i < m_RefObjs.size(); ++i) {
424 EXPECT_TRUE(m_RefObjs[i]->IsReference());
425 EXPECT_EQ(m_RefObjs[i].Get(), m_RefObjs[i]->AsReference());
426 }
427}
428
430 auto original_obj = pdfium::MakeRetain<CPDF_Null>();
431 original_obj->SetObjNum(42);
432 ASSERT_FALSE(original_obj->IsInline());
433
434 auto ref_obj = original_obj->MakeReference(m_ObjHolder.get());
435
436 ASSERT_TRUE(ref_obj->IsReference());
437 EXPECT_EQ(original_obj->GetObjNum(),
438 ToReference(ref_obj.Get())->GetRefObjNum());
439}
440
442 std::set<uint64_t> key_set;
443
444 // Check all direct objects inserted without collision.
445 for (const auto& direct : m_DirectObjs) {
446 EXPECT_TRUE(key_set.insert(direct->KeyForCache()).second);
447 }
448 // Check indirect objects inserted without collision.
449 for (const auto& pair : *m_ObjHolder) {
450 EXPECT_TRUE(key_set.insert(pair.second->KeyForCache()).second);
451 }
452
453 // Check all expected objects counted.
454 EXPECT_EQ(18u, key_set.size());
455}
456
458 using Row = std::array<float, 6>;
459 constexpr auto elems = fxcrt::ToArray<const Row>({
460 {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}},
461 {{1, 2, 3, 4, 5, 6}},
462 {{2.3f, 4.05f, 3, -2, -3, 0.0f}},
463 {{0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}},
464 });
465 for (const auto& elem : elems) {
466 auto arr = pdfium::MakeRetain<CPDF_Array>();
467 for (float f : elem) {
468 arr->AppendNew<CPDF_Number>(f);
469 }
470 CFX_Matrix matrix(elem[0], elem[1], elem[2], elem[3], elem[4], elem[5]);
471 CFX_Matrix arr_matrix = arr->GetMatrix();
472 EXPECT_EQ(matrix, arr_matrix);
473 }
474}
475
477 using Row = std::array<float, 4>;
478 constexpr auto elems = fxcrt::ToArray<const Row>({
479 {{0.0f, 0.0f, 0.0f, 0.0f}},
480 {{1, 2, 5, 6}},
481 {{2.3f, 4.05f, -3, 0.0f}},
482 {{0.05f, 0.1f, 1.34f, 99.9f}},
483 });
484 for (const auto& elem : elems) {
485 auto arr = pdfium::MakeRetain<CPDF_Array>();
486 for (float f : elem) {
487 arr->AppendNew<CPDF_Number>(f);
488 }
489 CFX_FloatRect rect(elem[0], elem[1], elem[2], elem[3]);
490 CFX_FloatRect arr_rect = arr->GetRect();
491 EXPECT_EQ(rect, arr_rect);
492 }
493}
494
496 {
497 // Boolean array.
498 constexpr auto vals =
499 fxcrt::ToArray<const bool>({true, false, false, true, true});
500 auto arr = pdfium::MakeRetain<CPDF_Array>();
501 for (size_t i = 0; i < vals.size(); ++i) {
502 arr->InsertNewAt<CPDF_Boolean>(i, vals[i]);
503 }
504 for (size_t i = 0; i < vals.size(); ++i) {
505 TestArrayAccessors(arr.Get(), i, // Array and index.
506 vals[i] ? "true" : "false", // String value.
507 nullptr, // Const string value.
508 vals[i] ? 1 : 0, // Integer value.
509 0, // Float value.
510 nullptr, // Array value.
511 nullptr, // Dictionary value.
512 nullptr); // Stream value.
513 }
514 }
515 {
516 // Integer array.
517 constexpr auto vals = fxcrt::ToArray<const int>(
518 {10, 0, -345, 2089345456, -1000000000, 567, 93658767});
519 auto arr = pdfium::MakeRetain<CPDF_Array>();
520 for (size_t i = 0; i < vals.size(); ++i) {
521 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
522 }
523 for (size_t i = 0; i < vals.size(); ++i) {
524 char buf[33];
525 TestArrayAccessors(arr.Get(), i, // Array and index.
526 FXSYS_itoa(vals[i], buf, 10), // String value.
527 nullptr, // Const string value.
528 vals[i], // Integer value.
529 vals[i], // Float value.
530 nullptr, // Array value.
531 nullptr, // Dictionary value.
532 nullptr); // Stream value.
533 }
534 }
535 {
536 // Float array.
537 constexpr auto vals = fxcrt::ToArray<const float>(
538 {0.0f, 0, 10, 10.0f, 0.0345f, 897.34f, -2.5f, -1.0f, -345.0f, -0.0f});
539 auto arr = pdfium::MakeRetain<CPDF_Array>();
540 for (size_t i = 0; i < vals.size(); ++i) {
541 arr->InsertNewAt<CPDF_Number>(i, vals[i]);
542 }
543 constexpr auto expected_str =
544 fxcrt::ToArray<const char*>({"0", "0", "10", "10", ".034499999",
545 "897.34003", "-2.5", "-1", "-345", "0"});
546 for (size_t i = 0; i < vals.size(); ++i) {
547 TestArrayAccessors(arr.Get(), i, // Array and index.
548 expected_str[i], // String value.
549 nullptr, // Const string value.
550 vals[i], // Integer value.
551 vals[i], // Float value.
552 nullptr, // Array value.
553 nullptr, // Dictionary value.
554 nullptr); // Stream value.
555 }
556 }
557 {
558 // String and name array
559 constexpr auto vals = fxcrt::ToArray<const char*>(
560 {"this", "adsde$%^", "\r\t", "\"012", ".", "EYREW", "It is a joke :)"});
561 auto string_array = pdfium::MakeRetain<CPDF_Array>();
562 auto name_array = pdfium::MakeRetain<CPDF_Array>();
563 for (size_t i = 0; i < vals.size(); ++i) {
564 string_array->InsertNewAt<CPDF_String>(i, vals[i]);
565 name_array->InsertNewAt<CPDF_Name>(i, vals[i]);
566 }
567 for (size_t i = 0; i < std::size(vals); ++i) {
568 TestArrayAccessors(string_array.Get(), i, // Array and index.
569 vals[i], // String value.
570 vals[i], // Const string value.
571 0, // Integer value.
572 0, // Float value.
573 nullptr, // Array value.
574 nullptr, // Dictionary value.
575 nullptr); // Stream value.
576 TestArrayAccessors(name_array.Get(), i, // Array and index.
577 vals[i], // String value.
578 vals[i], // Const string value.
579 0, // Integer value.
580 0, // Float value.
581 nullptr, // Array value.
582 nullptr, // Dictionary value.
583 nullptr); // Stream value.
584 }
585 }
586 {
587 // Null element array.
588 auto arr = pdfium::MakeRetain<CPDF_Array>();
589 for (size_t i = 0; i < 3; ++i)
590 arr->InsertNewAt<CPDF_Null>(i);
591 for (size_t i = 0; i < 3; ++i) {
592 TestArrayAccessors(arr.Get(), i, // Array and index.
593 "", // String value.
594 nullptr, // Const string value.
595 0, // Integer value.
596 0, // Float value.
597 nullptr, // Array value.
598 nullptr, // Dictionary value.
599 nullptr); // Stream value.
600 }
601 }
602 {
603 // Array of array.
604 std::array<RetainPtr<CPDF_Array>, 3> vals;
605 auto arr = pdfium::MakeRetain<CPDF_Array>();
606 for (size_t i = 0; i < 3; ++i) {
607 vals[i] = arr->AppendNew<CPDF_Array>();
608 for (size_t j = 0; j < 3; ++j) {
609 int value = j + 100;
610 vals[i]->InsertNewAt<CPDF_Number>(j, value);
611 }
612 }
613 for (size_t i = 0; i < 3; ++i) {
614 TestArrayAccessors(arr.Get(), i, // Array and index.
615 "", // String value.
616 nullptr, // Const string value.
617 0, // Integer value.
618 0, // Float value.
619 vals[i].Get(), // Array value.
620 nullptr, // Dictionary value.
621 nullptr); // Stream value.
622 }
623 }
624 {
625 // Dictionary array.
626 std::array<RetainPtr<CPDF_Dictionary>, 3> vals;
627 auto arr = pdfium::MakeRetain<CPDF_Array>();
628 for (size_t i = 0; i < 3; ++i) {
629 vals[i] = arr->AppendNew<CPDF_Dictionary>();
630 for (size_t j = 0; j < 3; ++j) {
631 std::string key("key");
632 char buf[33];
633 key.append(FXSYS_itoa(j, buf, 10));
634 int value = j + 200;
635 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
636 }
637 }
638 for (size_t i = 0; i < 3; ++i) {
639 TestArrayAccessors(arr.Get(), i, // Array and index.
640 "", // String value.
641 nullptr, // Const string value.
642 0, // Integer value.
643 0, // Float value.
644 nullptr, // Array value.
645 vals[i].Get(), // Dictionary value.
646 nullptr); // Stream value.
647 }
648 }
649 {
650 // Stream array.
651 CPDF_IndirectObjectHolder object_holder;
652
653 std::array<RetainPtr<CPDF_Dictionary>, 3> vals;
654 std::array<RetainPtr<CPDF_Stream>, 3> stream_vals;
655 auto arr = pdfium::MakeRetain<CPDF_Array>();
656 for (size_t i = 0; i < 3; ++i) {
657 vals[i] = pdfium::MakeRetain<CPDF_Dictionary>();
658 for (size_t j = 0; j < 3; ++j) {
659 std::string key("key");
660 char buf[33];
661 key.append(FXSYS_itoa(j, buf, 10));
662 int value = j + 200;
663 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value);
664 }
665 static constexpr uint8_t kContents[] = "content: this is a stream";
666 stream_vals[i] = object_holder.NewIndirect<CPDF_Stream>(
667 DataVector<uint8_t>(std::begin(kContents), std::end(kContents)),
668 vals[i]);
669 arr->AppendNew<CPDF_Reference>(&object_holder,
670 stream_vals[i]->GetObjNum());
671 }
672 for (size_t i = 0; i < 3; ++i) {
673 TestArrayAccessors(arr.Get(), i, // Array and index.
674 "", // String value.
675 nullptr, // Const string value.
676 0, // Integer value.
677 0, // Float value.
678 nullptr, // Array value.
679 vals[i].Get(), // Dictionary value.
680 stream_vals[i].Get()); // Stream value.
681 }
682 }
683 {
684 // Mixed array.
685
686 CPDF_IndirectObjectHolder object_holder;
687 auto arr = pdfium::MakeRetain<CPDF_Array>();
688 arr->InsertNewAt<CPDF_Boolean>(0, true);
689 arr->InsertNewAt<CPDF_Boolean>(1, false);
690 arr->InsertNewAt<CPDF_Number>(2, 0);
691 arr->InsertNewAt<CPDF_Number>(3, -1234);
692 arr->InsertNewAt<CPDF_Number>(4, 2345.0f);
693 arr->InsertNewAt<CPDF_Number>(5, 0.05f);
694 arr->InsertNewAt<CPDF_String>(6, "");
695 arr->InsertNewAt<CPDF_String>(7, "It is a test!");
696 arr->InsertNewAt<CPDF_Name>(8, "NAME");
697 arr->InsertNewAt<CPDF_Name>(9, "test");
698 arr->InsertNewAt<CPDF_Null>(10);
699
700 auto arr_val = arr->InsertNewAt<CPDF_Array>(11);
701 arr_val->AppendNew<CPDF_Number>(1);
702 arr_val->AppendNew<CPDF_Number>(2);
703
704 auto dict_val = arr->InsertNewAt<CPDF_Dictionary>(12);
705 dict_val->SetNewFor<CPDF_String>("key1", "Linda");
706 dict_val->SetNewFor<CPDF_String>("key2", "Zoe");
707
708 auto stream_dict = pdfium::MakeRetain<CPDF_Dictionary>();
709 stream_dict->SetNewFor<CPDF_String>("key1", "John");
710 stream_dict->SetNewFor<CPDF_String>("key2", "King");
711 static constexpr uint8_t kData[] = "A stream for test";
712 // The data buffer will be owned by stream object, so it needs to be
713 // dynamically allocated.
714 auto stream_val = object_holder.NewIndirect<CPDF_Stream>(
715 DataVector<uint8_t>(std::begin(kData), std::end(kData)), stream_dict);
716 arr->InsertNewAt<CPDF_Reference>(13, &object_holder,
717 stream_val->GetObjNum());
718 constexpr auto expected_str = fxcrt::ToArray<const char*>(
719 {"true", "false", "0", "-1234", "2345", ".050000001", "",
720 "It is a test!", "NAME", "test", "", "", "", ""});
721 constexpr auto expected_int = fxcrt::ToArray<const int>(
722 {1, 0, 0, -1234, 2345, 0, 0, 0, 0, 0, 0, 0, 0, 0});
723 constexpr auto expected_float = fxcrt::ToArray<const float>(
724 {0, 0, 0, -1234, 2345, 0.05f, 0, 0, 0, 0, 0, 0, 0, 0});
725 for (size_t i = 0; i < arr->size(); ++i) {
726 EXPECT_EQ(expected_str[i], arr->GetByteStringAt(i));
727 EXPECT_EQ(expected_int[i], arr->GetIntegerAt(i));
728 EXPECT_EQ(expected_float[i], arr->GetFloatAt(i));
729 if (i == 11) {
730 EXPECT_EQ(arr_val, arr->GetArrayAt(i));
731 } else {
732 EXPECT_FALSE(arr->GetArrayAt(i));
733 }
734 if (i == 13) {
735 EXPECT_EQ(stream_dict, arr->GetDictAt(i));
736 EXPECT_EQ(stream_val, arr->GetStreamAt(i));
737 } else {
738 EXPECT_FALSE(arr->GetStreamAt(i));
739 if (i == 12)
740 EXPECT_EQ(dict_val, arr->GetDictAt(i));
741 else
742 EXPECT_FALSE(arr->GetDictAt(i));
743 }
744 }
745 }
746}
747
749 constexpr auto vals = fxcrt::ToArray<const float>(
750 {1.0f, -1.0f, 0, 0.456734f, 12345.54321f, 0.5f, 1000, 0.000045f});
751 auto arr = pdfium::MakeRetain<CPDF_Array>();
752 for (size_t i = 0; i < vals.size(); ++i) {
753 arr->AppendNew<CPDF_Number>(vals[i]);
754 }
755 for (size_t i = 0; i < vals.size(); ++i) {
756 EXPECT_EQ(CPDF_Object::kNumber, arr->GetObjectAt(i)->GetType());
757 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
758 }
759}
760
762 constexpr auto vals = fxcrt::ToArray<const int>(
763 {0, 1, 934435456, 876, 10000, -1, -24354656, -100});
764 auto arr = pdfium::MakeRetain<CPDF_Array>();
765 for (size_t i = 0; i < vals.size(); ++i) {
766 arr->AppendNew<CPDF_Number>(vals[i]);
767 }
768 for (size_t i = 0; i < vals.size(); ++i) {
769 EXPECT_EQ(CPDF_Object::kNumber, arr->GetObjectAt(i)->GetType());
770 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber());
771 }
772}
773
775 static constexpr auto kVals =
776 fxcrt::ToArray<const char*>({"", "a", "ehjhRIOYTTFdfcdnv", "122323",
777 "$#%^&**", " ", "This is a test.\r\n"});
778 auto string_array = pdfium::MakeRetain<CPDF_Array>();
779 auto name_array = pdfium::MakeRetain<CPDF_Array>();
780 for (const char* val : kVals) {
781 string_array->AppendNew<CPDF_String>(val);
782 name_array->AppendNew<CPDF_Name>(val);
783 }
784 for (size_t i = 0; i < std::size(kVals); ++i) {
785 EXPECT_EQ(CPDF_Object::kString, string_array->GetObjectAt(i)->GetType());
786 EXPECT_EQ(kVals[i], string_array->GetObjectAt(i)->GetString());
787 EXPECT_EQ(CPDF_Object::kName, name_array->GetObjectAt(i)->GetType());
788 EXPECT_EQ(kVals[i], name_array->GetObjectAt(i)->GetString());
789 }
790}
791
793 auto holder = std::make_unique<CPDF_IndirectObjectHolder>();
794 auto boolean_obj = pdfium::MakeRetain<CPDF_Boolean>(true);
795 auto int_obj = pdfium::MakeRetain<CPDF_Number>(-1234);
796 auto float_obj = pdfium::MakeRetain<CPDF_Number>(2345.089f);
797 auto str_obj =
798 pdfium::MakeRetain<CPDF_String>(nullptr, "Adsfdsf 343434 %&&*\n");
799 auto name_obj = pdfium::MakeRetain<CPDF_Name>(nullptr, "Title:");
800 auto null_obj = pdfium::MakeRetain<CPDF_Null>();
801 auto indirect_objs = fxcrt::ToArray<RetainPtr<CPDF_Object>>(
802 {boolean_obj, int_obj, float_obj, str_obj, name_obj, null_obj});
803 auto obj_nums = fxcrt::ToArray<int>({2, 4, 7, 2345, 799887, 1});
804 auto arr = pdfium::MakeRetain<CPDF_Array>();
805 auto arr1 = pdfium::MakeRetain<CPDF_Array>();
806 // Create two arrays of references by different AddReference() APIs.
807 for (size_t i = 0; i < std::size(indirect_objs); ++i) {
808 holder->ReplaceIndirectObjectIfHigherGeneration(obj_nums[i],
809 indirect_objs[i]);
810 arr->AppendNew<CPDF_Reference>(holder.get(), obj_nums[i]);
811 arr1->AppendNew<CPDF_Reference>(holder.get(),
812 indirect_objs[i]->GetObjNum());
813 }
814 // Check indirect objects.
815 for (size_t i = 0; i < std::size(obj_nums); ++i)
816 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i]));
817 // Check arrays.
818 EXPECT_EQ(arr->size(), arr1->size());
819 for (size_t i = 0; i < arr->size(); ++i) {
820 EXPECT_EQ(CPDF_Object::kReference, arr->GetObjectAt(i)->GetType());
821 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect());
822 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i));
823 EXPECT_EQ(CPDF_Object::kReference, arr1->GetObjectAt(i)->GetType());
824 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect());
825 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i));
826 }
827}
828
830 CPDF_IndirectObjectHolder objects_holder;
831 auto array = pdfium::MakeRetain<CPDF_Array>();
832 array->AppendNew<CPDF_Reference>(&objects_holder, 1234);
833 ASSERT_EQ(1U, array->size());
834 RetainPtr<const CPDF_Object> obj = array->GetObjectAt(0);
835 ASSERT_TRUE(obj);
836 EXPECT_TRUE(obj->IsReference());
837
838 RetainPtr<CPDF_Object> cloned_array_object = array->CloneDirectObject();
839 ASSERT_TRUE(cloned_array_object);
840 ASSERT_TRUE(cloned_array_object->IsArray());
841
842 RetainPtr<CPDF_Array> cloned_array = ToArray(std::move(cloned_array_object));
843 ASSERT_EQ(0U, cloned_array->size());
844 RetainPtr<const CPDF_Object> cloned_obj = cloned_array->GetObjectAt(0);
845 EXPECT_FALSE(cloned_obj);
846}
847
849 CPDF_IndirectObjectHolder objects_holder;
850 auto array = pdfium::MakeRetain<CPDF_Array>();
851 auto pObj = array->AppendNew<CPDF_Number>(42);
852 array->ConvertToIndirectObjectAt(0, &objects_holder);
853 RetainPtr<const CPDF_Object> pRef = array->GetObjectAt(0);
854 RetainPtr<const CPDF_Object> pNum = array->GetDirectObjectAt(0);
855 EXPECT_TRUE(pRef->IsReference());
856 EXPECT_TRUE(pNum->IsNumber());
857 EXPECT_NE(pObj, pRef);
858 EXPECT_EQ(pObj, pNum);
859 EXPECT_EQ(42, array->GetIntegerAt(0));
860}
861
863 DataVector<uint8_t> data(100);
864 auto stream = pdfium::MakeRetain<CPDF_Stream>(
865 data, pdfium::MakeRetain<CPDF_Dictionary>());
866 EXPECT_EQ(static_cast<int>(data.size()),
867 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
868
869 stream->GetMutableDict()->SetNewFor<CPDF_String>(pdfium::stream::kFilter,
870 L"SomeFilter");
871 stream->GetMutableDict()->SetNewFor<CPDF_String>(pdfium::stream::kDecodeParms,
872 L"SomeParams");
873
874 DataVector<uint8_t> new_data(data.size() * 2);
875 stream->SetData(new_data);
876
877 // The "Length" field should be updated for new data size.
878 EXPECT_EQ(static_cast<int>(new_data.size()),
879 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
880
881 // The "Filter" and "DecodeParms" fields should not be changed.
882 EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor(pdfium::stream::kFilter),
883 L"SomeFilter");
884 EXPECT_EQ(stream->GetDict()->GetUnicodeTextFor(pdfium::stream::kDecodeParms),
885 L"SomeParams");
886}
887
889 DataVector<uint8_t> data(100);
890 auto stream = pdfium::MakeRetain<CPDF_Stream>(
891 data, pdfium::MakeRetain<CPDF_Dictionary>());
892 EXPECT_EQ(static_cast<int>(data.size()),
893 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
894
895 stream->GetMutableDict()->SetNewFor<CPDF_String>(pdfium::stream::kFilter,
896 L"SomeFilter");
897 stream->GetMutableDict()->SetNewFor<CPDF_String>(pdfium::stream::kDecodeParms,
898 L"SomeParams");
899
900 DataVector<uint8_t> new_data(data.size() * 2);
901 stream->SetDataAndRemoveFilter(new_data);
902 // The "Length" field should be updated for new data size.
903 EXPECT_EQ(static_cast<int>(new_data.size()),
904 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
905
906 // The "Filter" and "DecodeParms" should be removed.
907 EXPECT_FALSE(stream->GetDict()->KeyExist(pdfium::stream::kFilter));
908 EXPECT_FALSE(stream->GetDict()->KeyExist(pdfium::stream::kDecodeParms));
909}
910
912 static constexpr uint32_t kBufSize = 100;
913 // The length field should be created on stream create.
914 {
915 auto stream = pdfium::MakeRetain<CPDF_Stream>(
916 DataVector<uint8_t>(kBufSize), pdfium::MakeRetain<CPDF_Dictionary>());
917 EXPECT_EQ(static_cast<int>(kBufSize),
918 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
919 }
920 // The length field should be corrected on stream create.
921 {
922 auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
923 dict->SetNewFor<CPDF_Number>(pdfium::stream::kLength, 30000);
924 auto stream = pdfium::MakeRetain<CPDF_Stream>(DataVector<uint8_t>(kBufSize),
925 std::move(dict));
926 EXPECT_EQ(static_cast<int>(kBufSize),
927 stream->GetDict()->GetIntegerFor(pdfium::stream::kLength));
928 }
929}
930
932 CPDF_IndirectObjectHolder objects_holder;
933 auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
934 dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234);
935 ASSERT_EQ(1U, dict->size());
936 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor("foo");
937 ASSERT_TRUE(obj);
938 EXPECT_TRUE(obj->IsReference());
939
940 RetainPtr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject();
941 ASSERT_TRUE(cloned_dict_object);
942 ASSERT_TRUE(cloned_dict_object->IsDictionary());
943
944 RetainPtr<CPDF_Dictionary> cloned_dict =
945 ToDictionary(std::move(cloned_dict_object));
946 ASSERT_EQ(0U, cloned_dict->size());
947 RetainPtr<const CPDF_Object> cloned_obj = cloned_dict->GetObjectFor("foo");
948 EXPECT_FALSE(cloned_obj);
949}
950
952 {
953 // Create a dictionary/array pair with a reference loop.
954 auto arr_obj = pdfium::MakeRetain<CPDF_Array>();
955 auto dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0);
956 dict_obj->SetFor("arr", arr_obj);
957 // Clone this object to see whether stack overflow will be triggered.
958 RetainPtr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone());
959 // Cloned object should be the same as the original.
960 ASSERT_TRUE(cloned_array);
961 EXPECT_EQ(1u, cloned_array->size());
962 RetainPtr<const CPDF_Object> cloned_dict = cloned_array->GetObjectAt(0);
963 ASSERT_TRUE(cloned_dict);
964 ASSERT_TRUE(cloned_dict->IsDictionary());
965 // Recursively referenced object is not cloned.
966 EXPECT_FALSE(cloned_dict->AsDictionary()->GetObjectFor("arr"));
967 dict_obj->RemoveFor("arr"); // Break deliberate cycle for cleanup.
968 }
969 {
970 CPDF_IndirectObjectHolder objects_holder;
971 // Create an object with a reference loop.
972 auto dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>();
973 auto arr_obj = pdfium::MakeRetain<CPDF_Array>();
974 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder,
975 dict_obj->GetObjNum());
976 RetainPtr<const CPDF_Object> elem0 = arr_obj->GetObjectAt(0);
977 dict_obj->SetFor("arr", std::move(arr_obj));
978 EXPECT_EQ(1u, dict_obj->GetObjNum());
979 ASSERT_TRUE(elem0);
980 ASSERT_TRUE(elem0->IsReference());
981 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum());
982 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect());
983
984 // Clone this object to see whether stack overflow will be triggered.
985 RetainPtr<CPDF_Dictionary> cloned_dict =
986 ToDictionary(dict_obj->CloneDirectObject());
987 // Cloned object should be the same as the original.
988 ASSERT_TRUE(cloned_dict);
989 RetainPtr<const CPDF_Object> cloned_arr = cloned_dict->GetObjectFor("arr");
990 ASSERT_TRUE(cloned_arr);
991 ASSERT_TRUE(cloned_arr->IsArray());
992 EXPECT_EQ(0U, cloned_arr->AsArray()->size());
993 // Recursively referenced object is not cloned.
994 EXPECT_FALSE(cloned_arr->AsArray()->GetObjectAt(0));
995 dict_obj->RemoveFor("arr"); // Break deliberate cycle for cleanup.
996 }
997}
998
1000 CPDF_IndirectObjectHolder objects_holder;
1001 auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
1002 auto pObj = dict->SetNewFor<CPDF_Number>("clams", 42);
1003 dict->ConvertToIndirectObjectFor("clams", &objects_holder);
1004 RetainPtr<const CPDF_Object> pRef = dict->GetObjectFor("clams");
1005 RetainPtr<const CPDF_Object> pNum = dict->GetDirectObjectFor("clams");
1006 EXPECT_TRUE(pRef->IsReference());
1007 EXPECT_TRUE(pNum->IsNumber());
1008 EXPECT_NE(pObj, pRef);
1009 EXPECT_EQ(pObj, pNum);
1010 EXPECT_EQ(42, dict->GetIntegerFor("clams"));
1011}
1012
1014 auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
1015 auto pObj = dict->SetNewFor<CPDF_Number>("child", 42);
1016 auto extracted_object = dict->RemoveFor("child");
1017 EXPECT_EQ(pObj, extracted_object.Get());
1018
1019 extracted_object = dict->RemoveFor("non_exists_object");
1020 EXPECT_FALSE(extracted_object);
1021}
1022
1024 auto obj_holder = std::make_unique<CPDF_IndirectObjectHolder>();
1025 auto original_ref = pdfium::MakeRetain<CPDF_Reference>(obj_holder.get(), 42);
1026 original_ref->SetObjNum(1952);
1027 ASSERT_FALSE(original_ref->IsInline());
1028
1029 auto ref_obj = original_ref->MakeReference(obj_holder.get());
1030
1031 ASSERT_TRUE(ref_obj->IsReference());
1032 // We do not allow reference to reference.
1033 // New reference should have same RefObjNum.
1034 EXPECT_EQ(original_ref->GetRefObjNum(),
1035 ToReference(ref_obj.Get())->GetRefObjNum());
1036}
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
Definition cpdf_array.h:29
CPDF_DictionaryLocker(const CPDF_Dictionary *pDictionary)
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
bool IsInteger() const
Definition cpdf_number.h:30
virtual Type GetType() const =0
virtual ByteString GetString() const
const CPDF_Array * AsArray() const
virtual int GetInteger() const
const CPDF_Dictionary * AsDictionary() const
const CPDF_Reference * AsReference() const
const CPDF_Number * AsNumber() const
uint32_t GetRefObjNum() const
RetainPtr< CPDF_Array > m_ArrayObj
RetainPtr< CPDF_Dictionary > m_DictObj
std::vector< RetainPtr< CPDF_Object > > m_RefObjs
std::unique_ptr< CPDF_IndirectObjectHolder > m_ObjHolder
bool Equal(const CPDF_Object *obj1, const CPDF_Object *obj2)
std::vector< uint32_t > m_IndirectObjNums
std::vector< int > m_DirectObjTypes
std::vector< RetainPtr< CPDF_Object > > m_DirectObjs
void SetUp() override
RetainPtr< CPDF_Dictionary > m_StreamDictObj
bool operator==(const ByteString &other) const
#define UNSAFE_TODO(...)
TEST_F(PDFObjectsTest, GetString)
TEST(FXCRYPT, MD5GenerateEmtpyData)
const char kDecodeParms[]