OLD | NEW |
1 // Copyright 2016 PDFium Authors. All rights reserved. | 1 // Copyright 2016 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/fpdfapi/parser/cpdf_array.h" | 5 #include "core/fpdfapi/parser/cpdf_array.h" |
6 #include "core/fpdfapi/parser/cpdf_boolean.h" | 6 #include "core/fpdfapi/parser/cpdf_boolean.h" |
7 #include "core/fpdfapi/parser/cpdf_dictionary.h" | 7 #include "core/fpdfapi/parser/cpdf_dictionary.h" |
8 #include "core/fpdfapi/parser/cpdf_name.h" | 8 #include "core/fpdfapi/parser/cpdf_name.h" |
9 #include "core/fpdfapi/parser/cpdf_null.h" | 9 #include "core/fpdfapi/parser/cpdf_null.h" |
10 #include "core/fpdfapi/parser/cpdf_number.h" | 10 #include "core/fpdfapi/parser/cpdf_number.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 public: | 46 public: |
47 void SetUp() override { | 47 void SetUp() override { |
48 // Initialize different kinds of objects. | 48 // Initialize different kinds of objects. |
49 // Boolean objects. | 49 // Boolean objects. |
50 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false); | 50 CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false); |
51 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true); | 51 CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true); |
52 // Number objects. | 52 // Number objects. |
53 CPDF_Number* number_int_obj = new CPDF_Number(1245); | 53 CPDF_Number* number_int_obj = new CPDF_Number(1245); |
54 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f); | 54 CPDF_Number* number_float_obj = new CPDF_Number(9.00345f); |
55 // String objects. | 55 // String objects. |
56 CPDF_String* str_reg_obj = new CPDF_String(L"A simple test"); | 56 CPDF_String* str_reg_obj = new CPDF_String(nullptr, L"A simple test"); |
57 CPDF_String* str_spec_obj = new CPDF_String(L"\t\n"); | 57 CPDF_String* str_spec_obj = new CPDF_String(nullptr, L"\t\n"); |
58 // Name object. | 58 // Name object. |
59 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space"); | 59 CPDF_Name* name_obj = new CPDF_Name(nullptr, "space"); |
60 // Array object. | 60 // Array object. |
61 m_ArrayObj = new CPDF_Array; | 61 m_ArrayObj = new CPDF_Array; |
62 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902); | 62 m_ArrayObj->InsertNewAt<CPDF_Number>(0, 8902); |
63 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address"); | 63 m_ArrayObj->InsertNewAt<CPDF_Name>(1, "address"); |
64 // Dictionary object. | 64 // Dictionary object. |
65 m_DictObj = new CPDF_Dictionary(); | 65 m_DictObj = new CPDF_Dictionary(); |
66 m_DictObj->SetFor("bool", new CPDF_Boolean(false)); | 66 m_DictObj->SetNewFor<CPDF_Boolean>("bool", false); |
67 m_DictObj->SetFor("num", new CPDF_Number(0.23f)); | 67 m_DictObj->SetNewFor<CPDF_Number>("num", 0.23f); |
68 // Stream object. | 68 // Stream object. |
69 const char content[] = "abcdefghijklmnopqrstuvwxyz"; | 69 const char content[] = "abcdefghijklmnopqrstuvwxyz"; |
70 size_t buf_len = FX_ArraySize(content); | 70 size_t buf_len = FX_ArraySize(content); |
71 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len)); | 71 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len)); |
72 memcpy(buf, content, buf_len); | 72 memcpy(buf, content, buf_len); |
73 m_StreamDictObj = new CPDF_Dictionary(); | 73 m_StreamDictObj = new CPDF_Dictionary(); |
74 m_StreamDictObj->SetFor("key1", new CPDF_String(L" test dict")); | 74 m_StreamDictObj->SetNewFor<CPDF_String>("key1", L" test dict"); |
75 m_StreamDictObj->SetFor("key2", new CPDF_Number(-1)); | 75 m_StreamDictObj->SetNewFor<CPDF_Number>("key2", -1); |
76 CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj); | 76 CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj); |
77 // Null Object. | 77 // Null Object. |
78 CPDF_Null* null_obj = new CPDF_Null; | 78 CPDF_Null* null_obj = new CPDF_Null; |
79 // All direct objects. | 79 // All direct objects. |
80 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, | 80 CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj, |
81 number_float_obj, str_reg_obj, str_spec_obj, | 81 number_float_obj, str_reg_obj, str_spec_obj, |
82 name_obj, m_ArrayObj, m_DictObj, | 82 name_obj, m_ArrayObj, m_DictObj, |
83 stream_obj, null_obj}; | 83 stream_obj, null_obj}; |
84 m_DirectObjTypes = { | 84 m_DirectObjTypes = { |
85 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, | 85 CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 129 } |
130 return true; | 130 return true; |
131 } | 131 } |
132 case CPDF_Object::DICTIONARY: { | 132 case CPDF_Object::DICTIONARY: { |
133 const CPDF_Dictionary* dict1 = obj1->AsDictionary(); | 133 const CPDF_Dictionary* dict1 = obj1->AsDictionary(); |
134 const CPDF_Dictionary* dict2 = obj2->AsDictionary(); | 134 const CPDF_Dictionary* dict2 = obj2->AsDictionary(); |
135 if (dict1->GetCount() != dict2->GetCount()) | 135 if (dict1->GetCount() != dict2->GetCount()) |
136 return false; | 136 return false; |
137 for (CPDF_Dictionary::const_iterator it = dict1->begin(); | 137 for (CPDF_Dictionary::const_iterator it = dict1->begin(); |
138 it != dict1->end(); ++it) { | 138 it != dict1->end(); ++it) { |
139 if (!Equal(it->second, dict2->GetObjectFor(it->first))) | 139 if (!Equal(it->second.get(), dict2->GetObjectFor(it->first))) |
140 return false; | 140 return false; |
141 } | 141 } |
142 return true; | 142 return true; |
143 } | 143 } |
144 case CPDF_Object::NULLOBJ: | 144 case CPDF_Object::NULLOBJ: |
145 return true; | 145 return true; |
146 case CPDF_Object::STREAM: { | 146 case CPDF_Object::STREAM: { |
147 const CPDF_Stream* stream1 = obj1->AsStream(); | 147 const CPDF_Stream* stream1 = obj1->AsStream(); |
148 const CPDF_Stream* stream2 = obj2->AsStream(); | 148 const CPDF_Stream* stream2 = obj2->AsStream(); |
149 if (!stream1->GetDict() && !stream2->GetDict()) | 149 if (!stream1->GetDict() && !stream2->GetDict()) |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 // Dictionary array. | 548 // Dictionary array. |
549 CPDF_Dictionary* vals[3]; | 549 CPDF_Dictionary* vals[3]; |
550 auto arr = pdfium::MakeUnique<CPDF_Array>(); | 550 auto arr = pdfium::MakeUnique<CPDF_Array>(); |
551 for (size_t i = 0; i < 3; ++i) { | 551 for (size_t i = 0; i < 3; ++i) { |
552 vals[i] = arr->AddNew<CPDF_Dictionary>(); | 552 vals[i] = arr->AddNew<CPDF_Dictionary>(); |
553 for (size_t j = 0; j < 3; ++j) { | 553 for (size_t j = 0; j < 3; ++j) { |
554 std::string key("key"); | 554 std::string key("key"); |
555 char buf[33]; | 555 char buf[33]; |
556 key.append(FXSYS_itoa(j, buf, 10)); | 556 key.append(FXSYS_itoa(j, buf, 10)); |
557 int value = j + 200; | 557 int value = j + 200; |
558 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 558 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value); |
559 } | 559 } |
560 } | 560 } |
561 for (size_t i = 0; i < 3; ++i) { | 561 for (size_t i = 0; i < 3; ++i) { |
562 TestArrayAccessors(arr.get(), i, // Array and index. | 562 TestArrayAccessors(arr.get(), i, // Array and index. |
563 "", // String value. | 563 "", // String value. |
564 nullptr, // Const string value. | 564 nullptr, // Const string value. |
565 0, // Integer value. | 565 0, // Integer value. |
566 0, // Float value. | 566 0, // Float value. |
567 nullptr, // Array value. | 567 nullptr, // Array value. |
568 vals[i], // Dictionary value. | 568 vals[i], // Dictionary value. |
569 nullptr); // Stream value. | 569 nullptr); // Stream value. |
570 } | 570 } |
571 } | 571 } |
572 { | 572 { |
573 // Stream array. | 573 // Stream array. |
574 CPDF_Dictionary* vals[3]; | 574 CPDF_Dictionary* vals[3]; |
575 CPDF_Stream* stream_vals[3]; | 575 CPDF_Stream* stream_vals[3]; |
576 auto arr = pdfium::MakeUnique<CPDF_Array>(); | 576 auto arr = pdfium::MakeUnique<CPDF_Array>(); |
577 for (size_t i = 0; i < 3; ++i) { | 577 for (size_t i = 0; i < 3; ++i) { |
578 vals[i] = new CPDF_Dictionary(); | 578 vals[i] = new CPDF_Dictionary(); |
579 for (size_t j = 0; j < 3; ++j) { | 579 for (size_t j = 0; j < 3; ++j) { |
580 std::string key("key"); | 580 std::string key("key"); |
581 char buf[33]; | 581 char buf[33]; |
582 key.append(FXSYS_itoa(j, buf, 10)); | 582 key.append(FXSYS_itoa(j, buf, 10)); |
583 int value = j + 200; | 583 int value = j + 200; |
584 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 584 vals[i]->SetNewFor<CPDF_Number>(key.c_str(), value); |
585 } | 585 } |
586 uint8_t content[] = "content: this is a stream"; | 586 uint8_t content[] = "content: this is a stream"; |
587 size_t data_size = FX_ArraySize(content); | 587 size_t data_size = FX_ArraySize(content); |
588 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); | 588 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); |
589 memcpy(data, content, data_size); | 589 memcpy(data, content, data_size); |
590 stream_vals[i] = arr->AddNew<CPDF_Stream>(data, data_size, vals[i]); | 590 stream_vals[i] = arr->AddNew<CPDF_Stream>(data, data_size, vals[i]); |
591 } | 591 } |
592 for (size_t i = 0; i < 3; ++i) { | 592 for (size_t i = 0; i < 3; ++i) { |
593 TestArrayAccessors(arr.get(), i, // Array and index. | 593 TestArrayAccessors(arr.get(), i, // Array and index. |
594 "", // String value. | 594 "", // String value. |
(...skipping 18 matching lines...) Expand all Loading... |
613 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false); | 613 arr->InsertNewAt<CPDF_String>(7, "It is a test!", false); |
614 arr->InsertNewAt<CPDF_Name>(8, "NAME"); | 614 arr->InsertNewAt<CPDF_Name>(8, "NAME"); |
615 arr->InsertNewAt<CPDF_Name>(9, "test"); | 615 arr->InsertNewAt<CPDF_Name>(9, "test"); |
616 arr->InsertNewAt<CPDF_Null>(10); | 616 arr->InsertNewAt<CPDF_Null>(10); |
617 | 617 |
618 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11); | 618 CPDF_Array* arr_val = arr->InsertNewAt<CPDF_Array>(11); |
619 arr_val->AddNew<CPDF_Number>(1); | 619 arr_val->AddNew<CPDF_Number>(1); |
620 arr_val->AddNew<CPDF_Number>(2); | 620 arr_val->AddNew<CPDF_Number>(2); |
621 | 621 |
622 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12); | 622 CPDF_Dictionary* dict_val = arr->InsertNewAt<CPDF_Dictionary>(12); |
623 dict_val->SetFor("key1", new CPDF_String(nullptr, "Linda", false)); | 623 dict_val->SetNewFor<CPDF_String>("key1", "Linda", false); |
624 dict_val->SetFor("key2", new CPDF_String(nullptr, "Zoe", false)); | 624 dict_val->SetNewFor<CPDF_String>("key2", "Zoe", false); |
625 | 625 |
626 CPDF_Dictionary* stream_dict = new CPDF_Dictionary(); | 626 CPDF_Dictionary* stream_dict = new CPDF_Dictionary(); |
627 stream_dict->SetFor("key1", new CPDF_String(nullptr, "John", false)); | 627 stream_dict->SetNewFor<CPDF_String>("key1", "John", false); |
628 stream_dict->SetFor("key2", new CPDF_String(nullptr, "King", false)); | 628 stream_dict->SetNewFor<CPDF_String>("key2", "King", false); |
629 uint8_t data[] = "A stream for test"; | 629 uint8_t data[] = "A stream for test"; |
630 // The data buffer will be owned by stream object, so it needs to be | 630 // The data buffer will be owned by stream object, so it needs to be |
631 // dynamically allocated. | 631 // dynamically allocated. |
632 size_t buf_size = sizeof(data); | 632 size_t buf_size = sizeof(data); |
633 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_size)); | 633 uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_size)); |
634 memcpy(buf, data, buf_size); | 634 memcpy(buf, data, buf_size); |
635 CPDF_Stream* stream_val = | 635 CPDF_Stream* stream_val = |
636 arr->InsertNewAt<CPDF_Stream>(13, buf, buf_size, stream_dict); | 636 arr->InsertNewAt<CPDF_Stream>(13, buf, buf_size, stream_dict); |
637 const char* const expected_str[] = { | 637 const char* const expected_str[] = { |
638 "true", "false", "0", "-1234", "2345", "0.05", "", | 638 "true", "false", "0", "-1234", "2345", "0.05", "", |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 EXPECT_TRUE(pRef->IsReference()); | 771 EXPECT_TRUE(pRef->IsReference()); |
772 EXPECT_TRUE(pNum->IsNumber()); | 772 EXPECT_TRUE(pNum->IsNumber()); |
773 EXPECT_NE(pObj, pRef); | 773 EXPECT_NE(pObj, pRef); |
774 EXPECT_EQ(pObj, pNum); | 774 EXPECT_EQ(pObj, pNum); |
775 EXPECT_EQ(42, array->GetIntegerAt(0)); | 775 EXPECT_EQ(42, array->GetIntegerAt(0)); |
776 } | 776 } |
777 | 777 |
778 TEST(PDFDictionaryTest, CloneDirectObject) { | 778 TEST(PDFDictionaryTest, CloneDirectObject) { |
779 CPDF_IndirectObjectHolder objects_holder; | 779 CPDF_IndirectObjectHolder objects_holder; |
780 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); | 780 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); |
781 dict->SetReferenceFor("foo", &objects_holder, 1234); | 781 dict->SetNewFor<CPDF_Reference>("foo", &objects_holder, 1234); |
782 ASSERT_EQ(1U, dict->GetCount()); | 782 ASSERT_EQ(1U, dict->GetCount()); |
783 CPDF_Object* obj = dict->GetObjectFor("foo"); | 783 CPDF_Object* obj = dict->GetObjectFor("foo"); |
784 ASSERT_TRUE(obj); | 784 ASSERT_TRUE(obj); |
785 EXPECT_TRUE(obj->IsReference()); | 785 EXPECT_TRUE(obj->IsReference()); |
786 | 786 |
787 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject(); | 787 std::unique_ptr<CPDF_Object> cloned_dict_object = dict->CloneDirectObject(); |
788 ASSERT_TRUE(cloned_dict_object); | 788 ASSERT_TRUE(cloned_dict_object); |
789 ASSERT_TRUE(cloned_dict_object->IsDictionary()); | 789 ASSERT_TRUE(cloned_dict_object->IsDictionary()); |
790 | 790 |
791 std::unique_ptr<CPDF_Dictionary> cloned_dict = | 791 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
792 ToDictionary(std::move(cloned_dict_object)); | 792 ToDictionary(std::move(cloned_dict_object)); |
793 ASSERT_EQ(1U, cloned_dict->GetCount()); | 793 ASSERT_EQ(1U, cloned_dict->GetCount()); |
794 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); | 794 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); |
795 EXPECT_FALSE(cloned_obj); | 795 EXPECT_FALSE(cloned_obj); |
796 } | 796 } |
797 | 797 |
798 TEST(PDFObjectTest, CloneCheckLoop) { | 798 TEST(PDFObjectTest, CloneCheckLoop) { |
799 { | 799 { |
800 // Create a dictionary/array pair with a reference loop. | 800 // Create a dictionary/array pair with a reference loop. It takes |
| 801 // some work to do this nowadays, in particular we need the |
| 802 // anti-pattern pdfium::WrapUnique(arr.get()). |
801 auto arr_obj = pdfium::MakeUnique<CPDF_Array>(); | 803 auto arr_obj = pdfium::MakeUnique<CPDF_Array>(); |
802 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0); | 804 CPDF_Dictionary* dict_obj = arr_obj->InsertNewAt<CPDF_Dictionary>(0); |
803 dict_obj->SetFor("arr", arr_obj.get()); | 805 dict_obj->SetFor("arr", pdfium::WrapUnique(arr_obj.get())); |
804 // Clone this object to see whether stack overflow will be triggered. | 806 // Clone this object to see whether stack overflow will be triggered. |
805 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone()); | 807 std::unique_ptr<CPDF_Array> cloned_array = ToArray(arr_obj->Clone()); |
806 // Cloned object should be the same as the original. | 808 // Cloned object should be the same as the original. |
807 ASSERT_TRUE(cloned_array); | 809 ASSERT_TRUE(cloned_array); |
808 EXPECT_EQ(1u, cloned_array->GetCount()); | 810 EXPECT_EQ(1u, cloned_array->GetCount()); |
809 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); | 811 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); |
810 ASSERT_TRUE(cloned_dict); | 812 ASSERT_TRUE(cloned_dict); |
811 ASSERT_TRUE(cloned_dict->IsDictionary()); | 813 ASSERT_TRUE(cloned_dict->IsDictionary()); |
812 // Recursively referenced object is not cloned. | 814 // Recursively referenced object is not cloned. |
813 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); | 815 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); |
814 } | 816 } |
815 { | 817 { |
816 // Create a dictionary/stream pair with a reference loop. | 818 // Create a dictionary/stream pair with a reference loop. |
817 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 819 auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>(); |
818 std::unique_ptr<CPDF_Stream> stream_obj( | 820 CPDF_Stream* stream_obj = |
819 new CPDF_Stream(nullptr, 0, dict_obj)); | 821 dict_obj->SetNewFor<CPDF_Stream>("stream", nullptr, 0, dict_obj.get()); |
820 dict_obj->SetFor("stream", stream_obj.get()); | |
821 | |
822 // Clone this object to see whether stack overflow will be triggered. | 822 // Clone this object to see whether stack overflow will be triggered. |
823 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone()); | 823 std::unique_ptr<CPDF_Stream> cloned_stream = ToStream(stream_obj->Clone()); |
824 // Cloned object should be the same as the original. | 824 // Cloned object should be the same as the original. |
825 ASSERT_TRUE(cloned_stream); | 825 ASSERT_TRUE(cloned_stream); |
826 CPDF_Object* cloned_dict = cloned_stream->GetDict(); | 826 CPDF_Object* cloned_dict = cloned_stream->GetDict(); |
827 ASSERT_TRUE(cloned_dict); | 827 ASSERT_TRUE(cloned_dict); |
828 ASSERT_TRUE(cloned_dict->IsDictionary()); | 828 ASSERT_TRUE(cloned_dict->IsDictionary()); |
829 // Recursively referenced object is not cloned. | 829 // Recursively referenced object is not cloned. |
830 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); | 830 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); |
831 } | 831 } |
832 { | 832 { |
833 CPDF_IndirectObjectHolder objects_holder; | 833 CPDF_IndirectObjectHolder objects_holder; |
834 // Create an object with a reference loop. | 834 // Create an object with a reference loop. |
835 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>(); | 835 CPDF_Dictionary* dict_obj = objects_holder.NewIndirect<CPDF_Dictionary>(); |
836 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>(); | 836 std::unique_ptr<CPDF_Array> arr_obj = pdfium::MakeUnique<CPDF_Array>(); |
837 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder, | 837 arr_obj->InsertNewAt<CPDF_Reference>(0, &objects_holder, |
838 dict_obj->GetObjNum()); | 838 dict_obj->GetObjNum()); |
839 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); | 839 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); |
840 dict_obj->SetFor("arr", arr_obj.release()); | 840 dict_obj->SetFor("arr", std::move(arr_obj)); |
841 EXPECT_EQ(1u, dict_obj->GetObjNum()); | 841 EXPECT_EQ(1u, dict_obj->GetObjNum()); |
842 ASSERT_TRUE(elem0); | 842 ASSERT_TRUE(elem0); |
843 ASSERT_TRUE(elem0->IsReference()); | 843 ASSERT_TRUE(elem0->IsReference()); |
844 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); | 844 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); |
845 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); | 845 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); |
846 | 846 |
847 // Clone this object to see whether stack overflow will be triggered. | 847 // Clone this object to see whether stack overflow will be triggered. |
848 std::unique_ptr<CPDF_Dictionary> cloned_dict = | 848 std::unique_ptr<CPDF_Dictionary> cloned_dict = |
849 ToDictionary(dict_obj->CloneDirectObject()); | 849 ToDictionary(dict_obj->CloneDirectObject()); |
850 // Cloned object should be the same as the original. | 850 // Cloned object should be the same as the original. |
851 ASSERT_TRUE(cloned_dict); | 851 ASSERT_TRUE(cloned_dict); |
852 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); | 852 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); |
853 ASSERT_TRUE(cloned_arr); | 853 ASSERT_TRUE(cloned_arr); |
854 ASSERT_TRUE(cloned_arr->IsArray()); | 854 ASSERT_TRUE(cloned_arr->IsArray()); |
855 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); | 855 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); |
856 // Recursively referenced object is not cloned. | 856 // Recursively referenced object is not cloned. |
857 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); | 857 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); |
858 } | 858 } |
859 } | 859 } |
860 | 860 |
861 TEST(PDFDictionaryTest, ConvertIndirect) { | 861 TEST(PDFDictionaryTest, ConvertIndirect) { |
862 CPDF_IndirectObjectHolder objects_holder; | 862 CPDF_IndirectObjectHolder objects_holder; |
863 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); | 863 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary); |
864 CPDF_Object* pObj = new CPDF_Number(42); | 864 CPDF_Object* pObj = dict->SetNewFor<CPDF_Number>("clams", 42); |
865 dict->SetFor("clams", pObj); | |
866 dict->ConvertToIndirectObjectFor("clams", &objects_holder); | 865 dict->ConvertToIndirectObjectFor("clams", &objects_holder); |
867 CPDF_Object* pRef = dict->GetObjectFor("clams"); | 866 CPDF_Object* pRef = dict->GetObjectFor("clams"); |
868 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); | 867 CPDF_Object* pNum = dict->GetDirectObjectFor("clams"); |
869 EXPECT_TRUE(pRef->IsReference()); | 868 EXPECT_TRUE(pRef->IsReference()); |
870 EXPECT_TRUE(pNum->IsNumber()); | 869 EXPECT_TRUE(pNum->IsNumber()); |
871 EXPECT_NE(pObj, pRef); | 870 EXPECT_NE(pObj, pRef); |
872 EXPECT_EQ(pObj, pNum); | 871 EXPECT_EQ(pObj, pNum); |
873 EXPECT_EQ(42, dict->GetIntegerFor("clams")); | 872 EXPECT_EQ(42, dict->GetIntegerFor("clams")); |
874 } | 873 } |
OLD | NEW |