| 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/fpdf_parser/cpdf_array.h" | 5 #include "core/fpdfapi/fpdf_parser/cpdf_array.h" |
| 6 #include "core/fpdfapi/fpdf_parser/cpdf_boolean.h" | 6 #include "core/fpdfapi/fpdf_parser/cpdf_boolean.h" |
| 7 #include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h" | 7 #include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h" |
| 8 #include "core/fpdfapi/fpdf_parser/cpdf_name.h" | 8 #include "core/fpdfapi/fpdf_parser/cpdf_name.h" |
| 9 #include "core/fpdfapi/fpdf_parser/cpdf_null.h" | 9 #include "core/fpdfapi/fpdf_parser/cpdf_null.h" |
| 10 #include "core/fpdfapi/fpdf_parser/cpdf_number.h" | 10 #include "core/fpdfapi/fpdf_parser/cpdf_number.h" |
| 11 #include "core/fpdfapi/fpdf_parser/cpdf_reference.h" | 11 #include "core/fpdfapi/fpdf_parser/cpdf_reference.h" |
| 12 #include "core/fpdfapi/fpdf_parser/cpdf_stream.h" | 12 #include "core/fpdfapi/fpdf_parser/cpdf_stream.h" |
| 13 #include "core/fpdfapi/fpdf_parser/cpdf_string.h" | 13 #include "core/fpdfapi/fpdf_parser/cpdf_string.h" |
| 14 | 14 |
| 15 #include <memory> | 15 #include <memory> |
| 16 #include <string> | 16 #include <string> |
| 17 #include <vector> | 17 #include <vector> |
| 18 | 18 |
| 19 #include "core/fpdfapi/fpdf_parser/cpdf_indirect_object_holder.h" | 19 #include "core/fpdfapi/fpdf_parser/cpdf_indirect_object_holder.h" |
| 20 #include "core/fxcrt/fx_basic.h" | 20 #include "core/fxcrt/fx_basic.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 using ScopedArray = std::unique_ptr<CPDF_Array, ReleaseDeleter<CPDF_Array>>; | |
| 26 using ScopedDict = | |
| 27 std::unique_ptr<CPDF_Dictionary, ReleaseDeleter<CPDF_Dictionary>>; | |
| 28 using ScopedStream = std::unique_ptr<CPDF_Stream, ReleaseDeleter<CPDF_Stream>>; | |
| 29 | |
| 30 void TestArrayAccessors(const CPDF_Array* arr, | 25 void TestArrayAccessors(const CPDF_Array* arr, |
| 31 size_t index, | 26 size_t index, |
| 32 const char* str_val, | 27 const char* str_val, |
| 33 const char* const_str_val, | 28 const char* const_str_val, |
| 34 int int_val, | 29 int int_val, |
| 35 float float_val, | 30 float float_val, |
| 36 CPDF_Array* arr_val, | 31 CPDF_Array* arr_val, |
| 37 CPDF_Dictionary* dict_val, | 32 CPDF_Dictionary* dict_val, |
| 38 CPDF_Stream* stream_val) { | 33 CPDF_Stream* stream_val) { |
| 39 EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str()); | 34 EXPECT_STREQ(str_val, arr->GetStringAt(index).c_str()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 stream1->GetRawSize()) == 0; | 161 stream1->GetRawSize()) == 0; |
| 167 } | 162 } |
| 168 case CPDF_Object::REFERENCE: | 163 case CPDF_Object::REFERENCE: |
| 169 return obj1->AsReference()->GetRefObjNum() == | 164 return obj1->AsReference()->GetRefObjNum() == |
| 170 obj2->AsReference()->GetRefObjNum(); | 165 obj2->AsReference()->GetRefObjNum(); |
| 171 } | 166 } |
| 172 return false; | 167 return false; |
| 173 } | 168 } |
| 174 | 169 |
| 175 protected: | 170 protected: |
| 176 using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>; | 171 using ScopedObj = std::unique_ptr<CPDF_Object>; |
| 177 | 172 |
| 178 // m_ObjHolder needs to be declared first and destructed last since it also | 173 // m_ObjHolder needs to be declared first and destructed last since it also |
| 179 // refers to some objects in m_DirectObjs. | 174 // refers to some objects in m_DirectObjs. |
| 180 std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder; | 175 std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder; |
| 181 std::vector<ScopedObj> m_DirectObjs; | 176 std::vector<ScopedObj> m_DirectObjs; |
| 182 std::vector<int> m_DirectObjTypes; | 177 std::vector<int> m_DirectObjTypes; |
| 183 std::vector<ScopedObj> m_RefObjs; | 178 std::vector<ScopedObj> m_RefObjs; |
| 184 CPDF_Dictionary* m_DictObj; | 179 CPDF_Dictionary* m_DictObj; |
| 185 CPDF_Dictionary* m_StreamDictObj; | 180 CPDF_Dictionary* m_StreamDictObj; |
| 186 CPDF_Array* m_ArrayObj; | 181 CPDF_Array* m_ArrayObj; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference()); | 381 EXPECT_EQ(m_RefObjs[i].get(), m_RefObjs[i]->AsReference()); |
| 387 } | 382 } |
| 388 } | 383 } |
| 389 | 384 |
| 390 TEST(PDFArrayTest, GetMatrix) { | 385 TEST(PDFArrayTest, GetMatrix) { |
| 391 float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, | 386 float elems[][6] = {{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, |
| 392 {1, 2, 3, 4, 5, 6}, | 387 {1, 2, 3, 4, 5, 6}, |
| 393 {2.3f, 4.05f, 3, -2, -3, 0.0f}, | 388 {2.3f, 4.05f, 3, -2, -3, 0.0f}, |
| 394 {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}}; | 389 {0.05f, 0.1f, 0.56f, 0.67f, 1.34f, 99.9f}}; |
| 395 for (size_t i = 0; i < FX_ArraySize(elems); ++i) { | 390 for (size_t i = 0; i < FX_ArraySize(elems); ++i) { |
| 396 ScopedArray arr(new CPDF_Array); | 391 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 397 CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3], | 392 CFX_Matrix matrix(elems[i][0], elems[i][1], elems[i][2], elems[i][3], |
| 398 elems[i][4], elems[i][5]); | 393 elems[i][4], elems[i][5]); |
| 399 for (size_t j = 0; j < 6; ++j) | 394 for (size_t j = 0; j < 6; ++j) |
| 400 arr->AddNumber(elems[i][j]); | 395 arr->AddNumber(elems[i][j]); |
| 401 CFX_Matrix arr_matrix = arr->GetMatrix(); | 396 CFX_Matrix arr_matrix = arr->GetMatrix(); |
| 402 EXPECT_EQ(matrix.GetA(), arr_matrix.GetA()); | 397 EXPECT_EQ(matrix.GetA(), arr_matrix.GetA()); |
| 403 EXPECT_EQ(matrix.GetB(), arr_matrix.GetB()); | 398 EXPECT_EQ(matrix.GetB(), arr_matrix.GetB()); |
| 404 EXPECT_EQ(matrix.GetC(), arr_matrix.GetC()); | 399 EXPECT_EQ(matrix.GetC(), arr_matrix.GetC()); |
| 405 EXPECT_EQ(matrix.GetD(), arr_matrix.GetD()); | 400 EXPECT_EQ(matrix.GetD(), arr_matrix.GetD()); |
| 406 EXPECT_EQ(matrix.GetE(), arr_matrix.GetE()); | 401 EXPECT_EQ(matrix.GetE(), arr_matrix.GetE()); |
| 407 EXPECT_EQ(matrix.GetF(), arr_matrix.GetF()); | 402 EXPECT_EQ(matrix.GetF(), arr_matrix.GetF()); |
| 408 } | 403 } |
| 409 } | 404 } |
| 410 | 405 |
| 411 TEST(PDFArrayTest, GetRect) { | 406 TEST(PDFArrayTest, GetRect) { |
| 412 float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, | 407 float elems[][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, |
| 413 {1, 2, 5, 6}, | 408 {1, 2, 5, 6}, |
| 414 {2.3f, 4.05f, -3, 0.0f}, | 409 {2.3f, 4.05f, -3, 0.0f}, |
| 415 {0.05f, 0.1f, 1.34f, 99.9f}}; | 410 {0.05f, 0.1f, 1.34f, 99.9f}}; |
| 416 for (size_t i = 0; i < FX_ArraySize(elems); ++i) { | 411 for (size_t i = 0; i < FX_ArraySize(elems); ++i) { |
| 417 ScopedArray arr(new CPDF_Array); | 412 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 418 CFX_FloatRect rect(elems[i]); | 413 CFX_FloatRect rect(elems[i]); |
| 419 for (size_t j = 0; j < 4; ++j) | 414 for (size_t j = 0; j < 4; ++j) |
| 420 arr->AddNumber(elems[i][j]); | 415 arr->AddNumber(elems[i][j]); |
| 421 CFX_FloatRect arr_rect = arr->GetRect(); | 416 CFX_FloatRect arr_rect = arr->GetRect(); |
| 422 EXPECT_EQ(rect.left, arr_rect.left); | 417 EXPECT_EQ(rect.left, arr_rect.left); |
| 423 EXPECT_EQ(rect.right, arr_rect.right); | 418 EXPECT_EQ(rect.right, arr_rect.right); |
| 424 EXPECT_EQ(rect.bottom, arr_rect.bottom); | 419 EXPECT_EQ(rect.bottom, arr_rect.bottom); |
| 425 EXPECT_EQ(rect.top, arr_rect.top); | 420 EXPECT_EQ(rect.top, arr_rect.top); |
| 426 } | 421 } |
| 427 } | 422 } |
| 428 | 423 |
| 429 TEST(PDFArrayTest, GetTypeAt) { | 424 TEST(PDFArrayTest, GetTypeAt) { |
| 430 { | 425 { |
| 431 // Boolean array. | 426 // Boolean array. |
| 432 const bool vals[] = {true, false, false, true, true}; | 427 const bool vals[] = {true, false, false, true, true}; |
| 433 ScopedArray arr(new CPDF_Array); | 428 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 434 for (size_t i = 0; i < FX_ArraySize(vals); ++i) | 429 for (size_t i = 0; i < FX_ArraySize(vals); ++i) |
| 435 arr->InsertAt(i, new CPDF_Boolean(vals[i])); | 430 arr->InsertAt(i, new CPDF_Boolean(vals[i])); |
| 436 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 431 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 437 TestArrayAccessors(arr.get(), i, // Array and index. | 432 TestArrayAccessors(arr.get(), i, // Array and index. |
| 438 vals[i] ? "true" : "false", // String value. | 433 vals[i] ? "true" : "false", // String value. |
| 439 nullptr, // Const string value. | 434 nullptr, // Const string value. |
| 440 vals[i] ? 1 : 0, // Integer value. | 435 vals[i] ? 1 : 0, // Integer value. |
| 441 0, // Float value. | 436 0, // Float value. |
| 442 nullptr, // Array value. | 437 nullptr, // Array value. |
| 443 nullptr, // Dictionary value. | 438 nullptr, // Dictionary value. |
| 444 nullptr); // Stream value. | 439 nullptr); // Stream value. |
| 445 } | 440 } |
| 446 } | 441 } |
| 447 { | 442 { |
| 448 // Integer array. | 443 // Integer array. |
| 449 const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767}; | 444 const int vals[] = {10, 0, -345, 2089345456, -1000000000, 567, 93658767}; |
| 450 ScopedArray arr(new CPDF_Array); | 445 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 451 for (size_t i = 0; i < FX_ArraySize(vals); ++i) | 446 for (size_t i = 0; i < FX_ArraySize(vals); ++i) |
| 452 arr->InsertAt(i, new CPDF_Number(vals[i])); | 447 arr->InsertAt(i, new CPDF_Number(vals[i])); |
| 453 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 448 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 454 char buf[33]; | 449 char buf[33]; |
| 455 TestArrayAccessors(arr.get(), i, // Array and index. | 450 TestArrayAccessors(arr.get(), i, // Array and index. |
| 456 FXSYS_itoa(vals[i], buf, 10), // String value. | 451 FXSYS_itoa(vals[i], buf, 10), // String value. |
| 457 nullptr, // Const string value. | 452 nullptr, // Const string value. |
| 458 vals[i], // Integer value. | 453 vals[i], // Integer value. |
| 459 vals[i], // Float value. | 454 vals[i], // Float value. |
| 460 nullptr, // Array value. | 455 nullptr, // Array value. |
| 461 nullptr, // Dictionary value. | 456 nullptr, // Dictionary value. |
| 462 nullptr); // Stream value. | 457 nullptr); // Stream value. |
| 463 } | 458 } |
| 464 } | 459 } |
| 465 { | 460 { |
| 466 // Float array. | 461 // Float array. |
| 467 const float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f, | 462 const float vals[] = {0.0f, 0, 10, 10.0f, 0.0345f, |
| 468 897.34f, -2.5f, -1.0f, -345.0f, -0.0f}; | 463 897.34f, -2.5f, -1.0f, -345.0f, -0.0f}; |
| 469 const char* const expected_str[] = { | 464 const char* const expected_str[] = { |
| 470 "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"}; | 465 "0", "0", "10", "10", "0.0345", "897.34", "-2.5", "-1", "-345", "0"}; |
| 471 ScopedArray arr(new CPDF_Array); | 466 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 472 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 467 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 473 arr->InsertAt(i, new CPDF_Number(vals[i])); | 468 arr->InsertAt(i, new CPDF_Number(vals[i])); |
| 474 } | 469 } |
| 475 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 470 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 476 TestArrayAccessors(arr.get(), i, // Array and index. | 471 TestArrayAccessors(arr.get(), i, // Array and index. |
| 477 expected_str[i], // String value. | 472 expected_str[i], // String value. |
| 478 nullptr, // Const string value. | 473 nullptr, // Const string value. |
| 479 vals[i], // Integer value. | 474 vals[i], // Integer value. |
| 480 vals[i], // Float value. | 475 vals[i], // Float value. |
| 481 nullptr, // Array value. | 476 nullptr, // Array value. |
| 482 nullptr, // Dictionary value. | 477 nullptr, // Dictionary value. |
| 483 nullptr); // Stream value. | 478 nullptr); // Stream value. |
| 484 } | 479 } |
| 485 } | 480 } |
| 486 { | 481 { |
| 487 // String and name array | 482 // String and name array |
| 488 const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012", | 483 const char* const vals[] = {"this", "adsde$%^", "\r\t", "\"012", |
| 489 ".", "EYREW", "It is a joke :)"}; | 484 ".", "EYREW", "It is a joke :)"}; |
| 490 ScopedArray string_array(new CPDF_Array); | 485 std::unique_ptr<CPDF_Array> string_array(new CPDF_Array); |
| 491 ScopedArray name_array(new CPDF_Array); | 486 std::unique_ptr<CPDF_Array> name_array(new CPDF_Array); |
| 492 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 487 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 493 string_array->InsertAt(i, new CPDF_String(vals[i], false)); | 488 string_array->InsertAt(i, new CPDF_String(vals[i], false)); |
| 494 name_array->InsertAt(i, new CPDF_Name(vals[i])); | 489 name_array->InsertAt(i, new CPDF_Name(vals[i])); |
| 495 } | 490 } |
| 496 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 491 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 497 TestArrayAccessors(string_array.get(), i, // Array and index. | 492 TestArrayAccessors(string_array.get(), i, // Array and index. |
| 498 vals[i], // String value. | 493 vals[i], // String value. |
| 499 vals[i], // Const string value. | 494 vals[i], // Const string value. |
| 500 0, // Integer value. | 495 0, // Integer value. |
| 501 0, // Float value. | 496 0, // Float value. |
| 502 nullptr, // Array value. | 497 nullptr, // Array value. |
| 503 nullptr, // Dictionary value. | 498 nullptr, // Dictionary value. |
| 504 nullptr); // Stream value. | 499 nullptr); // Stream value. |
| 505 TestArrayAccessors(name_array.get(), i, // Array and index. | 500 TestArrayAccessors(name_array.get(), i, // Array and index. |
| 506 vals[i], // String value. | 501 vals[i], // String value. |
| 507 vals[i], // Const string value. | 502 vals[i], // Const string value. |
| 508 0, // Integer value. | 503 0, // Integer value. |
| 509 0, // Float value. | 504 0, // Float value. |
| 510 nullptr, // Array value. | 505 nullptr, // Array value. |
| 511 nullptr, // Dictionary value. | 506 nullptr, // Dictionary value. |
| 512 nullptr); // Stream value. | 507 nullptr); // Stream value. |
| 513 } | 508 } |
| 514 } | 509 } |
| 515 { | 510 { |
| 516 // Null element array. | 511 // Null element array. |
| 517 ScopedArray arr(new CPDF_Array); | 512 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 518 for (size_t i = 0; i < 3; ++i) | 513 for (size_t i = 0; i < 3; ++i) |
| 519 arr->InsertAt(i, new CPDF_Null); | 514 arr->InsertAt(i, new CPDF_Null); |
| 520 for (size_t i = 0; i < 3; ++i) { | 515 for (size_t i = 0; i < 3; ++i) { |
| 521 TestArrayAccessors(arr.get(), i, // Array and index. | 516 TestArrayAccessors(arr.get(), i, // Array and index. |
| 522 "", // String value. | 517 "", // String value. |
| 523 nullptr, // Const string value. | 518 nullptr, // Const string value. |
| 524 0, // Integer value. | 519 0, // Integer value. |
| 525 0, // Float value. | 520 0, // Float value. |
| 526 nullptr, // Array value. | 521 nullptr, // Array value. |
| 527 nullptr, // Dictionary value. | 522 nullptr, // Dictionary value. |
| 528 nullptr); // Stream value. | 523 nullptr); // Stream value. |
| 529 } | 524 } |
| 530 } | 525 } |
| 531 { | 526 { |
| 532 // Array of array. | 527 // Array of array. |
| 533 CPDF_Array* vals[3]; | 528 CPDF_Array* vals[3]; |
| 534 ScopedArray arr(new CPDF_Array); | 529 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 535 for (size_t i = 0; i < 3; ++i) { | 530 for (size_t i = 0; i < 3; ++i) { |
| 536 vals[i] = new CPDF_Array; | 531 vals[i] = new CPDF_Array; |
| 537 for (size_t j = 0; j < 3; ++j) { | 532 for (size_t j = 0; j < 3; ++j) { |
| 538 int value = j + 100; | 533 int value = j + 100; |
| 539 vals[i]->InsertAt(i, new CPDF_Number(value)); | 534 vals[i]->InsertAt(i, new CPDF_Number(value)); |
| 540 } | 535 } |
| 541 arr->InsertAt(i, vals[i]); | 536 arr->InsertAt(i, vals[i]); |
| 542 } | 537 } |
| 543 for (size_t i = 0; i < 3; ++i) { | 538 for (size_t i = 0; i < 3; ++i) { |
| 544 TestArrayAccessors(arr.get(), i, // Array and index. | 539 TestArrayAccessors(arr.get(), i, // Array and index. |
| 545 "", // String value. | 540 "", // String value. |
| 546 nullptr, // Const string value. | 541 nullptr, // Const string value. |
| 547 0, // Integer value. | 542 0, // Integer value. |
| 548 0, // Float value. | 543 0, // Float value. |
| 549 vals[i], // Array value. | 544 vals[i], // Array value. |
| 550 nullptr, // Dictionary value. | 545 nullptr, // Dictionary value. |
| 551 nullptr); // Stream value. | 546 nullptr); // Stream value. |
| 552 } | 547 } |
| 553 } | 548 } |
| 554 { | 549 { |
| 555 // Dictionary array. | 550 // Dictionary array. |
| 556 CPDF_Dictionary* vals[3]; | 551 CPDF_Dictionary* vals[3]; |
| 557 ScopedArray arr(new CPDF_Array); | 552 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 558 for (size_t i = 0; i < 3; ++i) { | 553 for (size_t i = 0; i < 3; ++i) { |
| 559 vals[i] = new CPDF_Dictionary(); | 554 vals[i] = new CPDF_Dictionary(); |
| 560 for (size_t j = 0; j < 3; ++j) { | 555 for (size_t j = 0; j < 3; ++j) { |
| 561 std::string key("key"); | 556 std::string key("key"); |
| 562 char buf[33]; | 557 char buf[33]; |
| 563 key.append(FXSYS_itoa(j, buf, 10)); | 558 key.append(FXSYS_itoa(j, buf, 10)); |
| 564 int value = j + 200; | 559 int value = j + 200; |
| 565 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 560 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); |
| 566 } | 561 } |
| 567 arr->InsertAt(i, vals[i]); | 562 arr->InsertAt(i, vals[i]); |
| 568 } | 563 } |
| 569 for (size_t i = 0; i < 3; ++i) { | 564 for (size_t i = 0; i < 3; ++i) { |
| 570 TestArrayAccessors(arr.get(), i, // Array and index. | 565 TestArrayAccessors(arr.get(), i, // Array and index. |
| 571 "", // String value. | 566 "", // String value. |
| 572 nullptr, // Const string value. | 567 nullptr, // Const string value. |
| 573 0, // Integer value. | 568 0, // Integer value. |
| 574 0, // Float value. | 569 0, // Float value. |
| 575 nullptr, // Array value. | 570 nullptr, // Array value. |
| 576 vals[i], // Dictionary value. | 571 vals[i], // Dictionary value. |
| 577 nullptr); // Stream value. | 572 nullptr); // Stream value. |
| 578 } | 573 } |
| 579 } | 574 } |
| 580 { | 575 { |
| 581 // Stream array. | 576 // Stream array. |
| 582 CPDF_Dictionary* vals[3]; | 577 CPDF_Dictionary* vals[3]; |
| 583 CPDF_Stream* stream_vals[3]; | 578 CPDF_Stream* stream_vals[3]; |
| 584 ScopedArray arr(new CPDF_Array); | 579 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 585 for (size_t i = 0; i < 3; ++i) { | 580 for (size_t i = 0; i < 3; ++i) { |
| 586 vals[i] = new CPDF_Dictionary(); | 581 vals[i] = new CPDF_Dictionary(); |
| 587 for (size_t j = 0; j < 3; ++j) { | 582 for (size_t j = 0; j < 3; ++j) { |
| 588 std::string key("key"); | 583 std::string key("key"); |
| 589 char buf[33]; | 584 char buf[33]; |
| 590 key.append(FXSYS_itoa(j, buf, 10)); | 585 key.append(FXSYS_itoa(j, buf, 10)); |
| 591 int value = j + 200; | 586 int value = j + 200; |
| 592 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); | 587 vals[i]->SetFor(key.c_str(), new CPDF_Number(value)); |
| 593 } | 588 } |
| 594 uint8_t content[] = "content: this is a stream"; | 589 uint8_t content[] = "content: this is a stream"; |
| 595 size_t data_size = FX_ArraySize(content); | 590 size_t data_size = FX_ArraySize(content); |
| 596 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); | 591 uint8_t* data = reinterpret_cast<uint8_t*>(malloc(data_size)); |
| 597 memcpy(data, content, data_size); | 592 memcpy(data, content, data_size); |
| 598 stream_vals[i] = new CPDF_Stream(data, data_size, vals[i]); | 593 stream_vals[i] = new CPDF_Stream(data, data_size, vals[i]); |
| 599 arr->InsertAt(i, stream_vals[i]); | 594 arr->InsertAt(i, stream_vals[i]); |
| 600 } | 595 } |
| 601 for (size_t i = 0; i < 3; ++i) { | 596 for (size_t i = 0; i < 3; ++i) { |
| 602 TestArrayAccessors(arr.get(), i, // Array and index. | 597 TestArrayAccessors(arr.get(), i, // Array and index. |
| 603 "", // String value. | 598 "", // String value. |
| 604 nullptr, // Const string value. | 599 nullptr, // Const string value. |
| 605 0, // Integer value. | 600 0, // Integer value. |
| 606 0, // Float value. | 601 0, // Float value. |
| 607 nullptr, // Array value. | 602 nullptr, // Array value. |
| 608 vals[i], // Dictionary value. | 603 vals[i], // Dictionary value. |
| 609 stream_vals[i]); // Stream value. | 604 stream_vals[i]); // Stream value. |
| 610 } | 605 } |
| 611 } | 606 } |
| 612 { | 607 { |
| 613 // Mixed array. | 608 // Mixed array. |
| 614 ScopedArray arr(new CPDF_Array); | 609 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 615 // Array arr will take ownership of all the objects inserted. | 610 // Array arr will take ownership of all the objects inserted. |
| 616 arr->InsertAt(0, new CPDF_Boolean(true)); | 611 arr->InsertAt(0, new CPDF_Boolean(true)); |
| 617 arr->InsertAt(1, new CPDF_Boolean(false)); | 612 arr->InsertAt(1, new CPDF_Boolean(false)); |
| 618 arr->InsertAt(2, new CPDF_Number(0)); | 613 arr->InsertAt(2, new CPDF_Number(0)); |
| 619 arr->InsertAt(3, new CPDF_Number(-1234)); | 614 arr->InsertAt(3, new CPDF_Number(-1234)); |
| 620 arr->InsertAt(4, new CPDF_Number(2345.0f)); | 615 arr->InsertAt(4, new CPDF_Number(2345.0f)); |
| 621 arr->InsertAt(5, new CPDF_Number(0.05f)); | 616 arr->InsertAt(5, new CPDF_Number(0.05f)); |
| 622 arr->InsertAt(6, new CPDF_String("", false)); | 617 arr->InsertAt(6, new CPDF_String("", false)); |
| 623 arr->InsertAt(7, new CPDF_String("It is a test!", false)); | 618 arr->InsertAt(7, new CPDF_String("It is a test!", false)); |
| 624 arr->InsertAt(8, new CPDF_Name("NAME")); | 619 arr->InsertAt(8, new CPDF_Name("NAME")); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 else | 664 else |
| 670 EXPECT_EQ(nullptr, arr->GetDictAt(i)); | 665 EXPECT_EQ(nullptr, arr->GetDictAt(i)); |
| 671 } | 666 } |
| 672 } | 667 } |
| 673 } | 668 } |
| 674 } | 669 } |
| 675 | 670 |
| 676 TEST(PDFArrayTest, AddNumber) { | 671 TEST(PDFArrayTest, AddNumber) { |
| 677 float vals[] = {1.0f, -1.0f, 0, 0.456734f, | 672 float vals[] = {1.0f, -1.0f, 0, 0.456734f, |
| 678 12345.54321f, 0.5f, 1000, 0.000045f}; | 673 12345.54321f, 0.5f, 1000, 0.000045f}; |
| 679 ScopedArray arr(new CPDF_Array); | 674 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 680 for (size_t i = 0; i < FX_ArraySize(vals); ++i) | 675 for (size_t i = 0; i < FX_ArraySize(vals); ++i) |
| 681 arr->AddNumber(vals[i]); | 676 arr->AddNumber(vals[i]); |
| 682 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 677 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 683 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType()); | 678 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType()); |
| 684 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber()); | 679 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber()); |
| 685 } | 680 } |
| 686 } | 681 } |
| 687 | 682 |
| 688 TEST(PDFArrayTest, AddInteger) { | 683 TEST(PDFArrayTest, AddInteger) { |
| 689 int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100}; | 684 int vals[] = {0, 1, 934435456, 876, 10000, -1, -24354656, -100}; |
| 690 ScopedArray arr(new CPDF_Array); | 685 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 691 for (size_t i = 0; i < FX_ArraySize(vals); ++i) | 686 for (size_t i = 0; i < FX_ArraySize(vals); ++i) |
| 692 arr->AddInteger(vals[i]); | 687 arr->AddInteger(vals[i]); |
| 693 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 688 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 694 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType()); | 689 EXPECT_EQ(CPDF_Object::NUMBER, arr->GetObjectAt(i)->GetType()); |
| 695 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber()); | 690 EXPECT_EQ(vals[i], arr->GetObjectAt(i)->GetNumber()); |
| 696 } | 691 } |
| 697 } | 692 } |
| 698 | 693 |
| 699 TEST(PDFArrayTest, AddStringAndName) { | 694 TEST(PDFArrayTest, AddStringAndName) { |
| 700 const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323", | 695 const char* vals[] = {"", "a", "ehjhRIOYTTFdfcdnv", "122323", |
| 701 "$#%^&**", " ", "This is a test.\r\n"}; | 696 "$#%^&**", " ", "This is a test.\r\n"}; |
| 702 ScopedArray string_array(new CPDF_Array); | 697 std::unique_ptr<CPDF_Array> string_array(new CPDF_Array); |
| 703 ScopedArray name_array(new CPDF_Array); | 698 std::unique_ptr<CPDF_Array> name_array(new CPDF_Array); |
| 704 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 699 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 705 string_array->AddString(vals[i]); | 700 string_array->AddString(vals[i]); |
| 706 name_array->AddName(vals[i]); | 701 name_array->AddName(vals[i]); |
| 707 } | 702 } |
| 708 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { | 703 for (size_t i = 0; i < FX_ArraySize(vals); ++i) { |
| 709 EXPECT_EQ(CPDF_Object::STRING, string_array->GetObjectAt(i)->GetType()); | 704 EXPECT_EQ(CPDF_Object::STRING, string_array->GetObjectAt(i)->GetType()); |
| 710 EXPECT_STREQ(vals[i], string_array->GetObjectAt(i)->GetString().c_str()); | 705 EXPECT_STREQ(vals[i], string_array->GetObjectAt(i)->GetString().c_str()); |
| 711 EXPECT_EQ(CPDF_Object::NAME, name_array->GetObjectAt(i)->GetType()); | 706 EXPECT_EQ(CPDF_Object::NAME, name_array->GetObjectAt(i)->GetType()); |
| 712 EXPECT_STREQ(vals[i], name_array->GetObjectAt(i)->GetString().c_str()); | 707 EXPECT_STREQ(vals[i], name_array->GetObjectAt(i)->GetString().c_str()); |
| 713 } | 708 } |
| 714 } | 709 } |
| 715 | 710 |
| 716 TEST(PDFArrayTest, AddReferenceAndGetObjectAt) { | 711 TEST(PDFArrayTest, AddReferenceAndGetObjectAt) { |
| 717 std::unique_ptr<CPDF_IndirectObjectHolder> holder( | 712 std::unique_ptr<CPDF_IndirectObjectHolder> holder( |
| 718 new CPDF_IndirectObjectHolder()); | 713 new CPDF_IndirectObjectHolder()); |
| 719 CPDF_Boolean* boolean_obj = new CPDF_Boolean(true); | 714 CPDF_Boolean* boolean_obj = new CPDF_Boolean(true); |
| 720 CPDF_Number* int_obj = new CPDF_Number(-1234); | 715 CPDF_Number* int_obj = new CPDF_Number(-1234); |
| 721 CPDF_Number* float_obj = new CPDF_Number(2345.089f); | 716 CPDF_Number* float_obj = new CPDF_Number(2345.089f); |
| 722 CPDF_String* str_obj = new CPDF_String("Adsfdsf 343434 %&&*\n", false); | 717 CPDF_String* str_obj = new CPDF_String("Adsfdsf 343434 %&&*\n", false); |
| 723 CPDF_Name* name_obj = new CPDF_Name("Title:"); | 718 CPDF_Name* name_obj = new CPDF_Name("Title:"); |
| 724 CPDF_Null* null_obj = new CPDF_Null(); | 719 CPDF_Null* null_obj = new CPDF_Null(); |
| 725 CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj, | 720 CPDF_Object* indirect_objs[] = {boolean_obj, int_obj, float_obj, |
| 726 str_obj, name_obj, null_obj}; | 721 str_obj, name_obj, null_obj}; |
| 727 unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1}; | 722 unsigned int obj_nums[] = {2, 4, 7, 2345, 799887, 1}; |
| 728 ScopedArray arr(new CPDF_Array); | 723 std::unique_ptr<CPDF_Array> arr(new CPDF_Array); |
| 729 ScopedArray arr1(new CPDF_Array); | 724 std::unique_ptr<CPDF_Array> arr1(new CPDF_Array); |
| 730 // Create two arrays of references by different AddReference() APIs. | 725 // Create two arrays of references by different AddReference() APIs. |
| 731 for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) { | 726 for (size_t i = 0; i < FX_ArraySize(indirect_objs); ++i) { |
| 732 // All the indirect objects inserted will be owned by holder. | 727 // All the indirect objects inserted will be owned by holder. |
| 733 holder->ReplaceIndirectObjectIfHigherGeneration(obj_nums[i], | 728 holder->ReplaceIndirectObjectIfHigherGeneration(obj_nums[i], |
| 734 indirect_objs[i]); | 729 indirect_objs[i]); |
| 735 arr->AddReference(holder.get(), obj_nums[i]); | 730 arr->AddReference(holder.get(), obj_nums[i]); |
| 736 arr1->AddReference(holder.get(), indirect_objs[i]->GetObjNum()); | 731 arr1->AddReference(holder.get(), indirect_objs[i]->GetObjNum()); |
| 737 } | 732 } |
| 738 // Check indirect objects. | 733 // Check indirect objects. |
| 739 for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i) | 734 for (size_t i = 0; i < FX_ArraySize(obj_nums); ++i) |
| 740 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i])); | 735 EXPECT_EQ(indirect_objs[i], holder->GetOrParseIndirectObject(obj_nums[i])); |
| 741 // Check arrays. | 736 // Check arrays. |
| 742 EXPECT_EQ(arr->GetCount(), arr1->GetCount()); | 737 EXPECT_EQ(arr->GetCount(), arr1->GetCount()); |
| 743 for (size_t i = 0; i < arr->GetCount(); ++i) { | 738 for (size_t i = 0; i < arr->GetCount(); ++i) { |
| 744 EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetObjectAt(i)->GetType()); | 739 EXPECT_EQ(CPDF_Object::REFERENCE, arr->GetObjectAt(i)->GetType()); |
| 745 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect()); | 740 EXPECT_EQ(indirect_objs[i], arr->GetObjectAt(i)->GetDirect()); |
| 746 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i)); | 741 EXPECT_EQ(indirect_objs[i], arr->GetDirectObjectAt(i)); |
| 747 EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetObjectAt(i)->GetType()); | 742 EXPECT_EQ(CPDF_Object::REFERENCE, arr1->GetObjectAt(i)->GetType()); |
| 748 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect()); | 743 EXPECT_EQ(indirect_objs[i], arr1->GetObjectAt(i)->GetDirect()); |
| 749 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i)); | 744 EXPECT_EQ(indirect_objs[i], arr1->GetDirectObjectAt(i)); |
| 750 } | 745 } |
| 751 } | 746 } |
| 752 | 747 |
| 753 TEST(PDFArrayTest, CloneDirectObject) { | 748 TEST(PDFArrayTest, CloneDirectObject) { |
| 754 CPDF_IndirectObjectHolder objects_holder; | 749 CPDF_IndirectObjectHolder objects_holder; |
| 755 ScopedArray array(new CPDF_Array); | 750 std::unique_ptr<CPDF_Array> array(new CPDF_Array); |
| 756 array->AddReference(&objects_holder, 1234); | 751 array->AddReference(&objects_holder, 1234); |
| 757 ASSERT_EQ(1U, array->GetCount()); | 752 ASSERT_EQ(1U, array->GetCount()); |
| 758 CPDF_Object* obj = array->GetObjectAt(0); | 753 CPDF_Object* obj = array->GetObjectAt(0); |
| 759 ASSERT_TRUE(obj); | 754 ASSERT_TRUE(obj); |
| 760 EXPECT_TRUE(obj->IsReference()); | 755 EXPECT_TRUE(obj->IsReference()); |
| 761 | 756 |
| 762 CPDF_Object* cloned_array_object = array->CloneDirectObject(); | 757 CPDF_Object* cloned_array_object = array->CloneDirectObject(); |
| 763 ASSERT_TRUE(cloned_array_object); | 758 ASSERT_TRUE(cloned_array_object); |
| 764 ASSERT_TRUE(cloned_array_object->IsArray()); | 759 ASSERT_TRUE(cloned_array_object->IsArray()); |
| 765 | 760 |
| 766 ScopedArray cloned_array(cloned_array_object->AsArray()); | 761 std::unique_ptr<CPDF_Array> cloned_array(cloned_array_object->AsArray()); |
| 767 ASSERT_EQ(1U, cloned_array->GetCount()); | 762 ASSERT_EQ(1U, cloned_array->GetCount()); |
| 768 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0); | 763 CPDF_Object* cloned_obj = cloned_array->GetObjectAt(0); |
| 769 EXPECT_FALSE(cloned_obj); | 764 EXPECT_FALSE(cloned_obj); |
| 770 } | 765 } |
| 771 | 766 |
| 772 TEST(PDFDictionaryTest, CloneDirectObject) { | 767 TEST(PDFDictionaryTest, CloneDirectObject) { |
| 773 CPDF_IndirectObjectHolder objects_holder; | 768 CPDF_IndirectObjectHolder objects_holder; |
| 774 ScopedDict dict(new CPDF_Dictionary()); | 769 std::unique_ptr<CPDF_Dictionary> dict(new CPDF_Dictionary()); |
| 775 dict->SetReferenceFor("foo", &objects_holder, 1234); | 770 dict->SetReferenceFor("foo", &objects_holder, 1234); |
| 776 ASSERT_EQ(1U, dict->GetCount()); | 771 ASSERT_EQ(1U, dict->GetCount()); |
| 777 CPDF_Object* obj = dict->GetObjectFor("foo"); | 772 CPDF_Object* obj = dict->GetObjectFor("foo"); |
| 778 ASSERT_TRUE(obj); | 773 ASSERT_TRUE(obj); |
| 779 EXPECT_TRUE(obj->IsReference()); | 774 EXPECT_TRUE(obj->IsReference()); |
| 780 | 775 |
| 781 CPDF_Object* cloned_dict_object = dict->CloneDirectObject(); | 776 CPDF_Object* cloned_dict_object = dict->CloneDirectObject(); |
| 782 ASSERT_TRUE(cloned_dict_object); | 777 ASSERT_TRUE(cloned_dict_object); |
| 783 ASSERT_TRUE(cloned_dict_object->IsDictionary()); | 778 ASSERT_TRUE(cloned_dict_object->IsDictionary()); |
| 784 | 779 |
| 785 ScopedDict cloned_dict(cloned_dict_object->AsDictionary()); | 780 std::unique_ptr<CPDF_Dictionary> cloned_dict( |
| 781 cloned_dict_object->AsDictionary()); |
| 786 ASSERT_EQ(1U, cloned_dict->GetCount()); | 782 ASSERT_EQ(1U, cloned_dict->GetCount()); |
| 787 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); | 783 CPDF_Object* cloned_obj = cloned_dict->GetObjectFor("foo"); |
| 788 EXPECT_FALSE(cloned_obj); | 784 EXPECT_FALSE(cloned_obj); |
| 789 } | 785 } |
| 790 | 786 |
| 791 TEST(PDFObjectTest, CloneCheckLoop) { | 787 TEST(PDFObjectTest, CloneCheckLoop) { |
| 792 { | 788 { |
| 793 // Create an dictionary/array pair with a reference loop. | 789 // Create an dictionary/array pair with a reference loop. |
| 794 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 790 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 795 ScopedArray arr_obj(new CPDF_Array); | 791 std::unique_ptr<CPDF_Array> arr_obj(new CPDF_Array); |
| 796 dict_obj->SetFor("arr", arr_obj.get()); | 792 dict_obj->SetFor("arr", arr_obj.get()); |
| 797 arr_obj->InsertAt(0, dict_obj); | 793 arr_obj->InsertAt(0, dict_obj); |
| 798 | 794 |
| 799 // Clone this object to see whether stack overflow will be triggered. | 795 // Clone this object to see whether stack overflow will be triggered. |
| 800 ScopedArray cloned_array(arr_obj->Clone()->AsArray()); | 796 std::unique_ptr<CPDF_Array> cloned_array(arr_obj->Clone()->AsArray()); |
| 801 // Cloned object should be the same as the original. | 797 // Cloned object should be the same as the original. |
| 802 ASSERT_TRUE(cloned_array); | 798 ASSERT_TRUE(cloned_array); |
| 803 EXPECT_EQ(1u, cloned_array->GetCount()); | 799 EXPECT_EQ(1u, cloned_array->GetCount()); |
| 804 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); | 800 CPDF_Object* cloned_dict = cloned_array->GetObjectAt(0); |
| 805 ASSERT_TRUE(cloned_dict); | 801 ASSERT_TRUE(cloned_dict); |
| 806 ASSERT_TRUE(cloned_dict->IsDictionary()); | 802 ASSERT_TRUE(cloned_dict->IsDictionary()); |
| 807 // Recursively referenced object is not cloned. | 803 // Recursively referenced object is not cloned. |
| 808 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); | 804 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("arr")); |
| 809 } | 805 } |
| 810 { | 806 { |
| 811 // Create a dictionary/stream pair with a reference loop. | 807 // Create a dictionary/stream pair with a reference loop. |
| 812 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 808 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 813 ScopedStream stream_obj(new CPDF_Stream(nullptr, 0, dict_obj)); | 809 std::unique_ptr<CPDF_Stream> stream_obj( |
| 810 new CPDF_Stream(nullptr, 0, dict_obj)); |
| 814 dict_obj->SetFor("stream", stream_obj.get()); | 811 dict_obj->SetFor("stream", stream_obj.get()); |
| 815 | 812 |
| 816 // Clone this object to see whether stack overflow will be triggered. | 813 // Clone this object to see whether stack overflow will be triggered. |
| 817 ScopedStream cloned_stream(stream_obj->Clone()->AsStream()); | 814 std::unique_ptr<CPDF_Stream> cloned_stream(stream_obj->Clone()->AsStream()); |
| 818 // Cloned object should be the same as the original. | 815 // Cloned object should be the same as the original. |
| 819 ASSERT_TRUE(cloned_stream); | 816 ASSERT_TRUE(cloned_stream); |
| 820 CPDF_Object* cloned_dict = cloned_stream->GetDict(); | 817 CPDF_Object* cloned_dict = cloned_stream->GetDict(); |
| 821 ASSERT_TRUE(cloned_dict); | 818 ASSERT_TRUE(cloned_dict); |
| 822 ASSERT_TRUE(cloned_dict->IsDictionary()); | 819 ASSERT_TRUE(cloned_dict->IsDictionary()); |
| 823 // Recursively referenced object is not cloned. | 820 // Recursively referenced object is not cloned. |
| 824 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); | 821 EXPECT_EQ(nullptr, cloned_dict->AsDictionary()->GetObjectFor("stream")); |
| 825 } | 822 } |
| 826 { | 823 { |
| 827 CPDF_IndirectObjectHolder objects_holder; | 824 CPDF_IndirectObjectHolder objects_holder; |
| 828 // Create an object with a reference loop. | 825 // Create an object with a reference loop. |
| 829 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); | 826 CPDF_Dictionary* dict_obj = new CPDF_Dictionary(); |
| 830 CPDF_Array* arr_obj = new CPDF_Array; | 827 CPDF_Array* arr_obj = new CPDF_Array; |
| 831 objects_holder.AddIndirectObject(dict_obj); | 828 objects_holder.AddIndirectObject(dict_obj); |
| 832 EXPECT_EQ(1u, dict_obj->GetObjNum()); | 829 EXPECT_EQ(1u, dict_obj->GetObjNum()); |
| 833 dict_obj->SetFor("arr", arr_obj); | 830 dict_obj->SetFor("arr", arr_obj); |
| 834 arr_obj->InsertAt( | 831 arr_obj->InsertAt( |
| 835 0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); | 832 0, new CPDF_Reference(&objects_holder, dict_obj->GetObjNum())); |
| 836 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); | 833 CPDF_Object* elem0 = arr_obj->GetObjectAt(0); |
| 837 ASSERT_TRUE(elem0); | 834 ASSERT_TRUE(elem0); |
| 838 ASSERT_TRUE(elem0->IsReference()); | 835 ASSERT_TRUE(elem0->IsReference()); |
| 839 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); | 836 EXPECT_EQ(1u, elem0->AsReference()->GetRefObjNum()); |
| 840 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); | 837 EXPECT_EQ(dict_obj, elem0->AsReference()->GetDirect()); |
| 841 | 838 |
| 842 // Clone this object to see whether stack overflow will be triggered. | 839 // Clone this object to see whether stack overflow will be triggered. |
| 843 ScopedDict cloned_dict(ToDictionary(dict_obj->CloneDirectObject())); | 840 std::unique_ptr<CPDF_Dictionary> cloned_dict( |
| 841 ToDictionary(dict_obj->CloneDirectObject())); |
| 844 // Cloned object should be the same as the original. | 842 // Cloned object should be the same as the original. |
| 845 ASSERT_TRUE(cloned_dict); | 843 ASSERT_TRUE(cloned_dict); |
| 846 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); | 844 CPDF_Object* cloned_arr = cloned_dict->GetObjectFor("arr"); |
| 847 ASSERT_TRUE(cloned_arr); | 845 ASSERT_TRUE(cloned_arr); |
| 848 ASSERT_TRUE(cloned_arr->IsArray()); | 846 ASSERT_TRUE(cloned_arr->IsArray()); |
| 849 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); | 847 EXPECT_EQ(1u, cloned_arr->AsArray()->GetCount()); |
| 850 // Recursively referenced object is not cloned. | 848 // Recursively referenced object is not cloned. |
| 851 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); | 849 EXPECT_EQ(nullptr, cloned_arr->AsArray()->GetObjectAt(0)); |
| 852 } | 850 } |
| 853 } | 851 } |
| OLD | NEW |