| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium 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 "base/values.h" | 5 #include "base/values.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cmath> | 10 #include <cmath> |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 return; | 117 return; |
| 118 case Type::BINARY: | 118 case Type::BINARY: |
| 119 binary_value_.Init(); | 119 binary_value_.Init(); |
| 120 return; | 120 return; |
| 121 case Type::DICTIONARY: | 121 case Type::DICTIONARY: |
| 122 dict_ptr_.Init(MakeUnique<DictStorage>()); | 122 dict_ptr_.Init(MakeUnique<DictStorage>()); |
| 123 return; | 123 return; |
| 124 case Type::LIST: | 124 case Type::LIST: |
| 125 list_.Init(); | 125 list_.Init(); |
| 126 return; | 126 return; |
| 127 case Type::DELETED: |
| 128 // TODO(crbug.com/697817): Remove. |
| 129 CHECK(false); |
| 130 return; |
| 127 } | 131 } |
| 128 } | 132 } |
| 129 | 133 |
| 130 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} | 134 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} |
| 131 | 135 |
| 132 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} | 136 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} |
| 133 | 137 |
| 134 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { | 138 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { |
| 135 if (!std::isfinite(double_value_)) { | 139 if (!std::isfinite(double_value_)) { |
| 136 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " | 140 NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 InternalCleanup(); | 197 InternalCleanup(); |
| 194 InternalMoveConstructFrom(std::move(that)); | 198 InternalMoveConstructFrom(std::move(that)); |
| 195 } | 199 } |
| 196 } | 200 } |
| 197 | 201 |
| 198 return *this; | 202 return *this; |
| 199 } | 203 } |
| 200 | 204 |
| 201 Value::~Value() { | 205 Value::~Value() { |
| 202 InternalCleanup(); | 206 InternalCleanup(); |
| 207 type_ = Type::DELETED; |
| 203 } | 208 } |
| 204 | 209 |
| 205 // static | 210 // static |
| 206 const char* Value::GetTypeName(Value::Type type) { | 211 const char* Value::GetTypeName(Value::Type type) { |
| 207 DCHECK_GE(static_cast<int>(type), 0); | 212 DCHECK_GE(static_cast<int>(type), 0); |
| 208 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); | 213 DCHECK_LT(static_cast<size_t>(type), arraysize(kTypeNames)); |
| 209 return kTypeNames[static_cast<size_t>(type)]; | 214 return kTypeNames[static_cast<size_t>(type)]; |
| 210 } | 215 } |
| 211 | 216 |
| 212 bool Value::GetBool() const { | 217 bool Value::GetBool() const { |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 if (list_->size() != other->list_->size()) | 440 if (list_->size() != other->list_->size()) |
| 436 return false; | 441 return false; |
| 437 | 442 |
| 438 return std::equal(std::begin(*list_), std::end(*list_), | 443 return std::equal(std::begin(*list_), std::end(*list_), |
| 439 std::begin(*(other->list_)), | 444 std::begin(*(other->list_)), |
| 440 [](const ListStorage::value_type& lhs, | 445 [](const ListStorage::value_type& lhs, |
| 441 const ListStorage::value_type& rhs) { | 446 const ListStorage::value_type& rhs) { |
| 442 return lhs->Equals(rhs.get()); | 447 return lhs->Equals(rhs.get()); |
| 443 }); | 448 }); |
| 444 } | 449 } |
| 450 case Type::DELETED: |
| 451 // TODO(crbug.com/697817): This means a use-after-free. |
| 452 CHECK(false); |
| 453 return false; |
| 445 } | 454 } |
| 446 | 455 |
| 447 NOTREACHED(); | 456 NOTREACHED(); |
| 448 return false; | 457 return false; |
| 449 } | 458 } |
| 450 | 459 |
| 451 // static | 460 // static |
| 452 bool Value::Equals(const Value* a, const Value* b) { | 461 bool Value::Equals(const Value* a, const Value* b) { |
| 453 if ((a == NULL) && (b == NULL)) return true; | 462 if ((a == NULL) && (b == NULL)) return true; |
| 454 if ((a == NULL) ^ (b == NULL)) return false; | 463 if ((a == NULL) ^ (b == NULL)) return false; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 // DictStorage and ListStorage are move-only types due to the presence of | 505 // DictStorage and ListStorage are move-only types due to the presence of |
| 497 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 506 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. |
| 498 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 507 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage |
| 499 // can be copied directly. | 508 // can be copied directly. |
| 500 case Type::DICTIONARY: | 509 case Type::DICTIONARY: |
| 501 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_)); | 510 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_)); |
| 502 return; | 511 return; |
| 503 case Type::LIST: | 512 case Type::LIST: |
| 504 list_.Init(std::move(*that.CreateDeepCopy()->list_)); | 513 list_.Init(std::move(*that.CreateDeepCopy()->list_)); |
| 505 return; | 514 return; |
| 515 case Type::DELETED: |
| 516 // TODO(crbug.com/697817): This means |that| is used after free. |
| 517 CHECK(false); |
| 518 return; |
| 506 } | 519 } |
| 507 } | 520 } |
| 508 | 521 |
| 509 void Value::InternalMoveConstructFrom(Value&& that) { | 522 void Value::InternalMoveConstructFrom(Value&& that) { |
| 510 type_ = that.type_; | 523 type_ = that.type_; |
| 511 | 524 |
| 512 switch (type_) { | 525 switch (type_) { |
| 513 case Type::NONE: | 526 case Type::NONE: |
| 514 case Type::BOOLEAN: | 527 case Type::BOOLEAN: |
| 515 case Type::INTEGER: | 528 case Type::INTEGER: |
| 516 case Type::DOUBLE: | 529 case Type::DOUBLE: |
| 517 InternalCopyFundamentalValue(that); | 530 InternalCopyFundamentalValue(that); |
| 518 return; | 531 return; |
| 519 | 532 |
| 520 case Type::STRING: | 533 case Type::STRING: |
| 521 string_value_.InitFromMove(std::move(that.string_value_)); | 534 string_value_.InitFromMove(std::move(that.string_value_)); |
| 522 return; | 535 return; |
| 523 case Type::BINARY: | 536 case Type::BINARY: |
| 524 binary_value_.InitFromMove(std::move(that.binary_value_)); | 537 binary_value_.InitFromMove(std::move(that.binary_value_)); |
| 525 return; | 538 return; |
| 526 case Type::DICTIONARY: | 539 case Type::DICTIONARY: |
| 527 dict_ptr_.InitFromMove(std::move(that.dict_ptr_)); | 540 dict_ptr_.InitFromMove(std::move(that.dict_ptr_)); |
| 528 return; | 541 return; |
| 529 case Type::LIST: | 542 case Type::LIST: |
| 530 list_.InitFromMove(std::move(that.list_)); | 543 list_.InitFromMove(std::move(that.list_)); |
| 531 return; | 544 return; |
| 545 case Type::DELETED: |
| 546 // TODO(crbug.com/697817): This means |that| is used after free. |
| 547 CHECK(false); |
| 548 return; |
| 532 } | 549 } |
| 533 } | 550 } |
| 534 | 551 |
| 535 void Value::InternalCopyAssignFromSameType(const Value& that) { | 552 void Value::InternalCopyAssignFromSameType(const Value& that) { |
| 536 CHECK_EQ(type_, that.type_); | 553 CHECK_EQ(type_, that.type_); |
| 537 | 554 |
| 538 switch (type_) { | 555 switch (type_) { |
| 539 case Type::NONE: | 556 case Type::NONE: |
| 540 case Type::BOOLEAN: | 557 case Type::BOOLEAN: |
| 541 case Type::INTEGER: | 558 case Type::INTEGER: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 552 // DictStorage and ListStorage are move-only types due to the presence of | 569 // DictStorage and ListStorage are move-only types due to the presence of |
| 553 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 570 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. |
| 554 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 571 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage |
| 555 // can be copied directly. | 572 // can be copied directly. |
| 556 case Type::DICTIONARY: | 573 case Type::DICTIONARY: |
| 557 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_); | 574 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_); |
| 558 return; | 575 return; |
| 559 case Type::LIST: | 576 case Type::LIST: |
| 560 *list_ = std::move(*that.CreateDeepCopy()->list_); | 577 *list_ = std::move(*that.CreateDeepCopy()->list_); |
| 561 return; | 578 return; |
| 579 case Type::DELETED: |
| 580 // TODO(crbug.com/697817): This means |that| is used after free. |
| 581 CHECK(false); |
| 582 return; |
| 562 } | 583 } |
| 563 } | 584 } |
| 564 | 585 |
| 565 void Value::InternalMoveAssignFromSameType(Value&& that) { | 586 void Value::InternalMoveAssignFromSameType(Value&& that) { |
| 566 CHECK_EQ(type_, that.type_); | 587 CHECK_EQ(type_, that.type_); |
| 567 | 588 |
| 568 switch (type_) { | 589 switch (type_) { |
| 569 case Type::NONE: | 590 case Type::NONE: |
| 570 case Type::BOOLEAN: | 591 case Type::BOOLEAN: |
| 571 case Type::INTEGER: | 592 case Type::INTEGER: |
| 572 case Type::DOUBLE: | 593 case Type::DOUBLE: |
| 573 InternalCopyFundamentalValue(that); | 594 InternalCopyFundamentalValue(that); |
| 574 return; | 595 return; |
| 575 | 596 |
| 576 case Type::STRING: | 597 case Type::STRING: |
| 577 *string_value_ = std::move(*that.string_value_); | 598 *string_value_ = std::move(*that.string_value_); |
| 578 return; | 599 return; |
| 579 case Type::BINARY: | 600 case Type::BINARY: |
| 580 *binary_value_ = std::move(*that.binary_value_); | 601 *binary_value_ = std::move(*that.binary_value_); |
| 581 return; | 602 return; |
| 582 case Type::DICTIONARY: | 603 case Type::DICTIONARY: |
| 583 *dict_ptr_ = std::move(*that.dict_ptr_); | 604 *dict_ptr_ = std::move(*that.dict_ptr_); |
| 584 return; | 605 return; |
| 585 case Type::LIST: | 606 case Type::LIST: |
| 586 *list_ = std::move(*that.list_); | 607 *list_ = std::move(*that.list_); |
| 587 return; | 608 return; |
| 609 case Type::DELETED: |
| 610 // TODO(crbug.com/697817): This means |that| is used after free. |
| 611 CHECK(false); |
| 612 return; |
| 588 } | 613 } |
| 589 } | 614 } |
| 590 | 615 |
| 591 void Value::InternalCleanup() { | 616 void Value::InternalCleanup() { |
| 592 switch (type_) { | 617 switch (type_) { |
| 593 case Type::NONE: | 618 case Type::NONE: |
| 594 case Type::BOOLEAN: | 619 case Type::BOOLEAN: |
| 595 case Type::INTEGER: | 620 case Type::INTEGER: |
| 596 case Type::DOUBLE: | 621 case Type::DOUBLE: |
| 597 // Nothing to do | 622 // Nothing to do |
| 598 return; | 623 return; |
| 599 | 624 |
| 600 case Type::STRING: | 625 case Type::STRING: |
| 601 string_value_.Destroy(); | 626 string_value_.Destroy(); |
| 602 return; | 627 return; |
| 603 case Type::BINARY: | 628 case Type::BINARY: |
| 604 binary_value_.Destroy(); | 629 binary_value_.Destroy(); |
| 605 return; | 630 return; |
| 606 case Type::DICTIONARY: | 631 case Type::DICTIONARY: |
| 607 dict_ptr_.Destroy(); | 632 dict_ptr_.Destroy(); |
| 608 return; | 633 return; |
| 609 case Type::LIST: | 634 case Type::LIST: |
| 610 list_.Destroy(); | 635 list_.Destroy(); |
| 611 return; | 636 return; |
| 637 case Type::DELETED: |
| 638 // TODO(crbug.com/697817): This means a use-after-free. |
| 639 CHECK(false); |
| 640 return; |
| 612 } | 641 } |
| 613 } | 642 } |
| 614 | 643 |
| 615 ///////////////////// DictionaryValue //////////////////// | 644 ///////////////////// DictionaryValue //////////////////// |
| 616 | 645 |
| 617 // static | 646 // static |
| 618 std::unique_ptr<DictionaryValue> DictionaryValue::From( | 647 std::unique_ptr<DictionaryValue> DictionaryValue::From( |
| 619 std::unique_ptr<Value> value) { | 648 std::unique_ptr<Value> value) { |
| 620 DictionaryValue* out; | 649 DictionaryValue* out; |
| 621 if (value && value->GetAsDictionary(&out)) { | 650 if (value && value->GetAsDictionary(&out)) { |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 } | 1384 } |
| 1356 | 1385 |
| 1357 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1386 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
| 1358 if (static_cast<int>(type) < 0 || | 1387 if (static_cast<int>(type) < 0 || |
| 1359 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1388 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
| 1360 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1389 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
| 1361 return out << Value::GetTypeName(type); | 1390 return out << Value::GetTypeName(type); |
| 1362 } | 1391 } |
| 1363 | 1392 |
| 1364 } // namespace base | 1393 } // namespace base |
| OLD | NEW |