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 |