Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: base/values.cc

Issue 2683203004: Move Storage for ListValue and DictValue in Union (Closed)
Patch Set: Add missing return statements. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 66
67 case Value::Type::DICTIONARY: 67 case Value::Type::DICTIONARY:
68 return CopyDictionaryWithoutEmptyChildren( 68 return CopyDictionaryWithoutEmptyChildren(
69 static_cast<const DictionaryValue&>(node)); 69 static_cast<const DictionaryValue&>(node));
70 70
71 default: 71 default:
72 return node.CreateDeepCopy(); 72 return node.CreateDeepCopy();
73 } 73 }
74 } 74 }
75 75
76 // TODO(crbug.com/646113): Remove this once all types are implemented.
77 bool IsAssignmentSafe(Value::Type lhs, Value::Type rhs) {
78 auto IsImplemented = [](Value::Type type) {
79 return type == Value::Type::NONE || type == Value::Type::BOOLEAN ||
80 type == Value::Type::INTEGER || type == Value::Type::DOUBLE ||
81 type == Value::Type::STRING || type == Value::Type::BINARY;
82 };
83
84 return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs));
85 }
86
87 } // namespace 76 } // namespace
88 77
89 // static 78 // static
90 std::unique_ptr<Value> Value::CreateNullValue() { 79 std::unique_ptr<Value> Value::CreateNullValue() {
91 return WrapUnique(new Value(Type::NONE)); 80 return WrapUnique(new Value(Type::NONE));
92 } 81 }
93 82
94 // static 83 // static
95 std::unique_ptr<BinaryValue> BinaryValue::CreateWithCopiedBuffer( 84 std::unique_ptr<BinaryValue> BinaryValue::CreateWithCopiedBuffer(
96 const char* buffer, 85 const char* buffer,
(...skipping 25 matching lines...) Expand all
122 return; 111 return;
123 case Type::DOUBLE: 112 case Type::DOUBLE:
124 double_value_ = 0.0; 113 double_value_ = 0.0;
125 return; 114 return;
126 case Type::STRING: 115 case Type::STRING:
127 string_value_.Init(); 116 string_value_.Init();
128 return; 117 return;
129 case Type::BINARY: 118 case Type::BINARY:
130 binary_value_.Init(); 119 binary_value_.Init();
131 return; 120 return;
132 121 case Type::DICTIONARY:
133 // TODO(crbug.com/646113): Implement these once the corresponding derived 122 dict_ptr_.Init(MakeUnique<DictStorage>());
134 // classes are removed. 123 return;
135 case Type::LIST: 124 case Type::LIST:
136 case Type::DICTIONARY: 125 list_.Init();
137 return; 126 return;
138 } 127 }
139 } 128 }
140 129
141 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} 130 Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {}
142 131
143 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} 132 Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {}
144 133
145 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { 134 Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) {
146 if (!std::isfinite(double_value_)) { 135 if (!std::isfinite(double_value_)) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) { 167 Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) {
179 binary_value_.Init(in_blob); 168 binary_value_.Init(in_blob);
180 } 169 }
181 170
182 Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) { 171 Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) {
183 binary_value_.Init(std::move(in_blob)); 172 binary_value_.Init(std::move(in_blob));
184 } 173 }
185 174
186 Value& Value::operator=(const Value& that) { 175 Value& Value::operator=(const Value& that) {
187 if (this != &that) { 176 if (this != &that) {
188 DCHECK(IsAssignmentSafe(type_, that.type_));
189 if (type_ == that.type_) { 177 if (type_ == that.type_) {
190 InternalCopyAssignFrom(that); 178 InternalCopyAssignFrom(that);
191 } else { 179 } else {
192 InternalCleanup(); 180 InternalCleanup();
193 InternalCopyConstructFrom(that); 181 InternalCopyConstructFrom(that);
194 } 182 }
195 } 183 }
196 184
197 return *this; 185 return *this;
198 } 186 }
199 187
200 Value& Value::operator=(Value&& that) { 188 Value& Value::operator=(Value&& that) {
201 if (this != &that) { 189 if (this != &that) {
202 DCHECK(IsAssignmentSafe(type_, that.type_));
203 if (type_ == that.type_) { 190 if (type_ == that.type_) {
204 InternalMoveAssignFrom(std::move(that)); 191 InternalMoveAssignFrom(std::move(that));
205 } else { 192 } else {
206 InternalCleanup(); 193 InternalCleanup();
207 InternalMoveConstructFrom(std::move(that)); 194 InternalMoveConstructFrom(std::move(that));
208 } 195 }
209 } 196 }
210 197
211 return *this; 198 return *this;
212 } 199 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 308
322 bool Value::GetAsBinary(const BinaryValue** out_value) const { 309 bool Value::GetAsBinary(const BinaryValue** out_value) const {
323 if (out_value && is_blob()) { 310 if (out_value && is_blob()) {
324 *out_value = this; 311 *out_value = this;
325 return true; 312 return true;
326 } 313 }
327 return is_blob(); 314 return is_blob();
328 } 315 }
329 316
330 bool Value::GetAsList(ListValue** out_value) { 317 bool Value::GetAsList(ListValue** out_value) {
331 return false; 318 if (out_value && is_list()) {
319 *out_value = static_cast<ListValue*>(this);
320 return true;
321 }
322 return is_list();
332 } 323 }
333 324
334 bool Value::GetAsList(const ListValue** out_value) const { 325 bool Value::GetAsList(const ListValue** out_value) const {
335 return false; 326 if (out_value && is_list()) {
327 *out_value = static_cast<const ListValue*>(this);
328 return true;
329 }
330 return is_list();
336 } 331 }
337 332
338 bool Value::GetAsDictionary(DictionaryValue** out_value) { 333 bool Value::GetAsDictionary(DictionaryValue** out_value) {
339 return false; 334 if (out_value && is_dict()) {
335 *out_value = static_cast<DictionaryValue*>(this);
336 return true;
337 }
338 return is_dict();
340 } 339 }
341 340
342 bool Value::GetAsDictionary(const DictionaryValue** out_value) const { 341 bool Value::GetAsDictionary(const DictionaryValue** out_value) const {
343 return false; 342 if (out_value && is_dict()) {
343 *out_value = static_cast<const DictionaryValue*>(this);
344 return true;
345 }
346 return is_dict();
344 } 347 }
345 348
346 Value* Value::DeepCopy() const { 349 Value* Value::DeepCopy() const {
347 // This method should only be getting called for null Values--all subclasses 350 // This method should only be getting called for null Values--all subclasses
348 // need to provide their own implementation;. 351 // need to provide their own implementation;.
349 switch (type()) { 352 switch (type()) {
350 case Type::NONE: 353 case Type::NONE:
351 return CreateNullValue().release(); 354 return CreateNullValue().release();
352 355
353 // For now, make FundamentalValues for backward-compatibility. Convert to 356 // For now, make FundamentalValues for backward-compatibility. Convert to
354 // Value when that code is deleted. 357 // Value when that code is deleted.
355 case Type::BOOLEAN: 358 case Type::BOOLEAN:
356 return new FundamentalValue(bool_value_); 359 return new FundamentalValue(bool_value_);
357 case Type::INTEGER: 360 case Type::INTEGER:
358 return new FundamentalValue(int_value_); 361 return new FundamentalValue(int_value_);
359 case Type::DOUBLE: 362 case Type::DOUBLE:
360 return new FundamentalValue(double_value_); 363 return new FundamentalValue(double_value_);
361 // For now, make StringValues for backward-compatibility. Convert to 364 // For now, make StringValues for backward-compatibility. Convert to
362 // Value when that code is deleted. 365 // Value when that code is deleted.
363 case Type::STRING: 366 case Type::STRING:
364 return new StringValue(*string_value_); 367 return new StringValue(*string_value_);
365 // For now, make BinaryValues for backward-compatibility. Convert to 368 // For now, make BinaryValues for backward-compatibility. Convert to
366 // Value when that code is deleted. 369 // Value when that code is deleted.
367 case Type::BINARY: 370 case Type::BINARY:
368 return new BinaryValue(*binary_value_); 371 return new BinaryValue(*binary_value_);
369 372
373 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
374 // are completely inlined.
375 case Type::DICTIONARY: {
376 DictionaryValue* result = new DictionaryValue;
377
378 for (const auto& current_entry : **dict_ptr_) {
379 result->SetWithoutPathExpansion(current_entry.first,
380 current_entry.second->CreateDeepCopy());
381 }
382
383 return result;
384 }
385
386 case Type::LIST: {
387 ListValue* result = new ListValue;
388
389 for (const auto& entry : *list_)
390 result->Append(entry->CreateDeepCopy());
391
392 return result;
393 }
394
370 default: 395 default:
371 // All other types should be handled by subclasses.
372 NOTREACHED(); 396 NOTREACHED();
373 return nullptr; 397 return nullptr;
374 } 398 }
375 } 399 }
376 400
377 std::unique_ptr<Value> Value::CreateDeepCopy() const { 401 std::unique_ptr<Value> Value::CreateDeepCopy() const {
378 return WrapUnique(DeepCopy()); 402 return WrapUnique(DeepCopy());
379 } 403 }
380 404
381 bool Value::Equals(const Value* other) const { 405 bool Value::Equals(const Value* other) const {
382 if (other->type() != type()) 406 if (other->type() != type())
383 return false; 407 return false;
384 408
385 switch (type()) { 409 switch (type()) {
386 case Type::NONE: 410 case Type::NONE:
387 return true; 411 return true;
388 case Type::BOOLEAN: 412 case Type::BOOLEAN:
389 return bool_value_ == other->bool_value_; 413 return bool_value_ == other->bool_value_;
390 case Type::INTEGER: 414 case Type::INTEGER:
391 return int_value_ == other->int_value_; 415 return int_value_ == other->int_value_;
392 case Type::DOUBLE: 416 case Type::DOUBLE:
393 return double_value_ == other->double_value_; 417 return double_value_ == other->double_value_;
394 case Type::STRING: 418 case Type::STRING:
395 return *string_value_ == *(other->string_value_); 419 return *string_value_ == *(other->string_value_);
396 case Type::BINARY: 420 case Type::BINARY:
397 return *binary_value_ == *(other->binary_value_); 421 return *binary_value_ == *(other->binary_value_);
398 default: 422 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
399 // This method should only be getting called for the above types -- all 423 // are completely inlined.
400 // subclasses need to provide their own implementation;. 424 case Type::DICTIONARY: {
401 NOTREACHED(); 425 if ((*dict_ptr_)->size() != (*other->dict_ptr_)->size())
402 return false; 426 return false;
427
428 return std::equal(std::begin(**dict_ptr_), std::end(**dict_ptr_),
429 std::begin(**(other->dict_ptr_)),
430 [](const DictStorage::value_type& lhs,
431 const DictStorage::value_type& rhs) {
432 if (lhs.first != rhs.first)
433 return false;
434
435 return lhs.second->Equals(rhs.second.get());
436 });
437 }
438 case Type::LIST: {
439 if (list_->size() != other->list_->size())
440 return false;
441
442 return std::equal(std::begin(*list_), std::end(*list_),
443 std::begin(*(other->list_)),
444 [](const ListStorage::value_type& lhs,
445 const ListStorage::value_type& rhs) {
446 return lhs->Equals(rhs.get());
447 });
448 }
403 } 449 }
450
451 NOTREACHED();
452 return false;
404 } 453 }
405 454
406 // static 455 // static
407 bool Value::Equals(const Value* a, const Value* b) { 456 bool Value::Equals(const Value* a, const Value* b) {
408 if ((a == NULL) && (b == NULL)) return true; 457 if ((a == NULL) && (b == NULL)) return true;
409 if ((a == NULL) ^ (b == NULL)) return false; 458 if ((a == NULL) ^ (b == NULL)) return false;
410 return a->Equals(b); 459 return a->Equals(b);
411 } 460 }
412 461
413 void Value::InternalCopyFundamentalValue(const Value& that) { 462 void Value::InternalCopyFundamentalValue(const Value& that) {
(...skipping 27 matching lines...) Expand all
441 case Type::DOUBLE: 490 case Type::DOUBLE:
442 InternalCopyFundamentalValue(that); 491 InternalCopyFundamentalValue(that);
443 return; 492 return;
444 493
445 case Type::STRING: 494 case Type::STRING:
446 string_value_.Init(*that.string_value_); 495 string_value_.Init(*that.string_value_);
447 return; 496 return;
448 case Type::BINARY: 497 case Type::BINARY:
449 binary_value_.Init(*that.binary_value_); 498 binary_value_.Init(*that.binary_value_);
450 return; 499 return;
451 500 // DictStorage and ListStorage are move-only types due to the presence of
brettw 2017/02/15 21:28:29 I think this comment is out-of-date now.
jdoerrie 2017/02/16 09:19:35 I think it's still relevant. DictStorage and ListS
452 // TODO(crbug.com/646113): Implement these once the corresponding derived 501 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here.
453 // classes are removed. 502 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage
503 // can be copied directly.
504 case Type::DICTIONARY:
505 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_));
506 return;
454 case Type::LIST: 507 case Type::LIST:
455 case Type::DICTIONARY: 508 list_.Init(std::move(*that.CreateDeepCopy()->list_));
456 return; 509 return;
457 } 510 }
458 } 511 }
459 512
460 void Value::InternalMoveConstructFrom(Value&& that) { 513 void Value::InternalMoveConstructFrom(Value&& that) {
461 type_ = that.type_; 514 type_ = that.type_;
462 515
463 switch (type_) { 516 switch (type_) {
464 case Type::NONE: 517 case Type::NONE:
465 case Type::BOOLEAN: 518 case Type::BOOLEAN:
466 case Type::INTEGER: 519 case Type::INTEGER:
467 case Type::DOUBLE: 520 case Type::DOUBLE:
468 InternalCopyFundamentalValue(that); 521 InternalCopyFundamentalValue(that);
469 return; 522 return;
470 523
471 case Type::STRING: 524 case Type::STRING:
472 string_value_.InitFromMove(std::move(that.string_value_)); 525 string_value_.InitFromMove(std::move(that.string_value_));
473 return; 526 return;
474 case Type::BINARY: 527 case Type::BINARY:
475 binary_value_.InitFromMove(std::move(that.binary_value_)); 528 binary_value_.InitFromMove(std::move(that.binary_value_));
476 return; 529 return;
477 530 case Type::DICTIONARY:
478 // TODO(crbug.com/646113): Implement these once the corresponding derived 531 dict_ptr_.InitFromMove(std::move(that.dict_ptr_));
479 // classes are removed. 532 return;
480 case Type::LIST: 533 case Type::LIST:
481 case Type::DICTIONARY: 534 list_.InitFromMove(std::move(that.list_));
482 return; 535 return;
483 } 536 }
484 } 537 }
485 538
486 void Value::InternalCopyAssignFrom(const Value& that) { 539 void Value::InternalCopyAssignFrom(const Value& that) {
487 type_ = that.type_; 540 type_ = that.type_;
488 541
489 switch (type_) { 542 switch (type_) {
490 case Type::NONE: 543 case Type::NONE:
491 case Type::BOOLEAN: 544 case Type::BOOLEAN:
492 case Type::INTEGER: 545 case Type::INTEGER:
493 case Type::DOUBLE: 546 case Type::DOUBLE:
494 InternalCopyFundamentalValue(that); 547 InternalCopyFundamentalValue(that);
495 return; 548 return;
496 549
497 case Type::STRING: 550 case Type::STRING:
498 *string_value_ = *that.string_value_; 551 *string_value_ = *that.string_value_;
499 return; 552 return;
500 case Type::BINARY: 553 case Type::BINARY:
501 *binary_value_ = *that.binary_value_; 554 *binary_value_ = *that.binary_value_;
502 return; 555 return;
503 556 // DictStorage and ListStorage are move-only types due to the presence of
brettw 2017/02/15 21:28:29 Ditto
jdoerrie 2017/02/16 09:19:35 Same as above (s/copy constructor/copy assignment
504 // TODO(crbug.com/646113): Implement these once the corresponding derived 557 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here.
505 // classes are removed. 558 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage
559 // can be copied directly.
560 case Type::DICTIONARY:
561 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_);
562 return;
506 case Type::LIST: 563 case Type::LIST:
507 case Type::DICTIONARY: 564 *list_ = std::move(*that.CreateDeepCopy()->list_);
508 return; 565 return;
509 } 566 }
510 } 567 }
511 568
512 void Value::InternalMoveAssignFrom(Value&& that) { 569 void Value::InternalMoveAssignFrom(Value&& that) {
513 type_ = that.type_; 570 type_ = that.type_;
514 571
515 switch (type_) { 572 switch (type_) {
516 case Type::NONE: 573 case Type::NONE:
517 case Type::BOOLEAN: 574 case Type::BOOLEAN:
518 case Type::INTEGER: 575 case Type::INTEGER:
519 case Type::DOUBLE: 576 case Type::DOUBLE:
520 InternalCopyFundamentalValue(that); 577 InternalCopyFundamentalValue(that);
521 return; 578 return;
522 579
523 case Type::STRING: 580 case Type::STRING:
524 *string_value_ = std::move(*that.string_value_); 581 *string_value_ = std::move(*that.string_value_);
525 return; 582 return;
526 case Type::BINARY: 583 case Type::BINARY:
527 *binary_value_ = std::move(*that.binary_value_); 584 *binary_value_ = std::move(*that.binary_value_);
528 return; 585 return;
529 586 case Type::DICTIONARY:
530 // TODO(crbug.com/646113): Implement these once the corresponding derived 587 *dict_ptr_ = std::move(*that.dict_ptr_);
531 // classes are removed. 588 return;
532 case Type::LIST: 589 case Type::LIST:
533 case Type::DICTIONARY: 590 *list_ = std::move(*that.list_);
534 return; 591 return;
535 } 592 }
536 } 593 }
537 594
538 void Value::InternalCleanup() { 595 void Value::InternalCleanup() {
539 switch (type_) { 596 switch (type_) {
540 case Type::NONE: 597 case Type::NONE:
541 case Type::BOOLEAN: 598 case Type::BOOLEAN:
542 case Type::INTEGER: 599 case Type::INTEGER:
543 case Type::DOUBLE: 600 case Type::DOUBLE:
544 // Nothing to do 601 // Nothing to do
545 return; 602 return;
546 603
547 case Type::STRING: 604 case Type::STRING:
548 string_value_.Destroy(); 605 string_value_.Destroy();
549 return; 606 return;
550 case Type::BINARY: 607 case Type::BINARY:
551 binary_value_.Destroy(); 608 binary_value_.Destroy();
552 return; 609 return;
553 610 case Type::DICTIONARY:
554 // TODO(crbug.com/646113): Implement these once the corresponding derived 611 dict_ptr_.Destroy();
555 // classes are removed. 612 return;
556 case Type::LIST: 613 case Type::LIST:
557 case Type::DICTIONARY: 614 list_.Destroy();
558 return; 615 return;
559 } 616 }
560 } 617 }
561 618
562 ///////////////////// DictionaryValue //////////////////// 619 ///////////////////// DictionaryValue ////////////////////
563 620
564 // static 621 // static
565 std::unique_ptr<DictionaryValue> DictionaryValue::From( 622 std::unique_ptr<DictionaryValue> DictionaryValue::From(
566 std::unique_ptr<Value> value) { 623 std::unique_ptr<Value> value) {
567 DictionaryValue* out; 624 DictionaryValue* out;
568 if (value && value->GetAsDictionary(&out)) { 625 if (value && value->GetAsDictionary(&out)) {
569 ignore_result(value.release()); 626 ignore_result(value.release());
570 return WrapUnique(out); 627 return WrapUnique(out);
571 } 628 }
572 return nullptr; 629 return nullptr;
573 } 630 }
574 631
575 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {} 632 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
576 633
577 DictionaryValue::~DictionaryValue() {
578 Clear();
579 }
580
581 bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) {
582 if (out_value)
583 *out_value = this;
584 return true;
585 }
586
587 bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const {
588 if (out_value)
589 *out_value = this;
590 return true;
591 }
592
593 bool DictionaryValue::HasKey(StringPiece key) const { 634 bool DictionaryValue::HasKey(StringPiece key) const {
594 DCHECK(IsStringUTF8(key)); 635 DCHECK(IsStringUTF8(key));
595 auto current_entry = dictionary_.find(key.as_string()); 636 auto current_entry = (*dict_ptr_)->find(key.as_string());
596 DCHECK((current_entry == dictionary_.end()) || current_entry->second); 637 DCHECK((current_entry == (*dict_ptr_)->end()) || current_entry->second);
597 return current_entry != dictionary_.end(); 638 return current_entry != (*dict_ptr_)->end();
598 } 639 }
599 640
600 void DictionaryValue::Clear() { 641 void DictionaryValue::Clear() {
601 dictionary_.clear(); 642 (*dict_ptr_)->clear();
602 } 643 }
603 644
604 void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) { 645 void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
605 DCHECK(IsStringUTF8(path)); 646 DCHECK(IsStringUTF8(path));
606 DCHECK(in_value); 647 DCHECK(in_value);
607 648
608 StringPiece current_path(path); 649 StringPiece current_path(path);
609 DictionaryValue* current_dictionary = this; 650 DictionaryValue* current_dictionary = this;
610 for (size_t delimiter_position = current_path.find('.'); 651 for (size_t delimiter_position = current_path.find('.');
611 delimiter_position != StringPiece::npos; 652 delimiter_position != StringPiece::npos;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 void DictionaryValue::SetString(StringPiece path, StringPiece in_value) { 687 void DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
647 Set(path, new StringValue(in_value)); 688 Set(path, new StringValue(in_value));
648 } 689 }
649 690
650 void DictionaryValue::SetString(StringPiece path, const string16& in_value) { 691 void DictionaryValue::SetString(StringPiece path, const string16& in_value) {
651 Set(path, new StringValue(in_value)); 692 Set(path, new StringValue(in_value));
652 } 693 }
653 694
654 void DictionaryValue::SetWithoutPathExpansion(StringPiece key, 695 void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
655 std::unique_ptr<Value> in_value) { 696 std::unique_ptr<Value> in_value) {
656 dictionary_[key.as_string()] = std::move(in_value); 697 (**dict_ptr_)[key.as_string()] = std::move(in_value);
657 } 698 }
658 699
659 void DictionaryValue::SetWithoutPathExpansion(StringPiece key, 700 void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
660 Value* in_value) { 701 Value* in_value) {
661 SetWithoutPathExpansion(key, WrapUnique(in_value)); 702 SetWithoutPathExpansion(key, WrapUnique(in_value));
662 } 703 }
663 704
664 void DictionaryValue::SetBooleanWithoutPathExpansion(StringPiece path, 705 void DictionaryValue::SetBooleanWithoutPathExpansion(StringPiece path,
665 bool in_value) { 706 bool in_value) {
666 SetWithoutPathExpansion(path, 707 SetWithoutPathExpansion(path,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 867
827 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) { 868 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
828 return static_cast<const DictionaryValue&>(*this).GetList( 869 return static_cast<const DictionaryValue&>(*this).GetList(
829 path, 870 path,
830 const_cast<const ListValue**>(out_value)); 871 const_cast<const ListValue**>(out_value));
831 } 872 }
832 873
833 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 874 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
834 const Value** out_value) const { 875 const Value** out_value) const {
835 DCHECK(IsStringUTF8(key)); 876 DCHECK(IsStringUTF8(key));
836 auto entry_iterator = dictionary_.find(key.as_string()); 877 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
837 if (entry_iterator == dictionary_.end()) 878 if (entry_iterator == (*dict_ptr_)->end())
838 return false; 879 return false;
839 880
840 if (out_value) 881 if (out_value)
841 *out_value = entry_iterator->second.get(); 882 *out_value = entry_iterator->second.get();
842 return true; 883 return true;
843 } 884 }
844 885
845 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 886 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
846 Value** out_value) { 887 Value** out_value) {
847 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion( 888 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 } 996 }
956 997
957 return current_dictionary->RemoveWithoutPathExpansion(current_path, 998 return current_dictionary->RemoveWithoutPathExpansion(current_path,
958 out_value); 999 out_value);
959 } 1000 }
960 1001
961 bool DictionaryValue::RemoveWithoutPathExpansion( 1002 bool DictionaryValue::RemoveWithoutPathExpansion(
962 StringPiece key, 1003 StringPiece key,
963 std::unique_ptr<Value>* out_value) { 1004 std::unique_ptr<Value>* out_value) {
964 DCHECK(IsStringUTF8(key)); 1005 DCHECK(IsStringUTF8(key));
965 auto entry_iterator = dictionary_.find(key.as_string()); 1006 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
966 if (entry_iterator == dictionary_.end()) 1007 if (entry_iterator == (*dict_ptr_)->end())
967 return false; 1008 return false;
968 1009
969 if (out_value) 1010 if (out_value)
970 *out_value = std::move(entry_iterator->second); 1011 *out_value = std::move(entry_iterator->second);
971 dictionary_.erase(entry_iterator); 1012 (*dict_ptr_)->erase(entry_iterator);
972 return true; 1013 return true;
973 } 1014 }
974 1015
975 bool DictionaryValue::RemovePath(StringPiece path, 1016 bool DictionaryValue::RemovePath(StringPiece path,
976 std::unique_ptr<Value>* out_value) { 1017 std::unique_ptr<Value>* out_value) {
977 bool result = false; 1018 bool result = false;
978 size_t delimiter_position = path.find('.'); 1019 size_t delimiter_position = path.find('.');
979 1020
980 if (delimiter_position == std::string::npos) 1021 if (delimiter_position == std::string::npos)
981 return RemoveWithoutPathExpansion(path, out_value); 1022 return RemoveWithoutPathExpansion(path, out_value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 continue; 1054 continue;
1014 } 1055 }
1015 } 1056 }
1016 // All other cases: Make a copy and hook it up. 1057 // All other cases: Make a copy and hook it up.
1017 SetWithoutPathExpansion(it.key(), 1058 SetWithoutPathExpansion(it.key(),
1018 base::WrapUnique(merge_value->DeepCopy())); 1059 base::WrapUnique(merge_value->DeepCopy()));
1019 } 1060 }
1020 } 1061 }
1021 1062
1022 void DictionaryValue::Swap(DictionaryValue* other) { 1063 void DictionaryValue::Swap(DictionaryValue* other) {
1023 dictionary_.swap(other->dictionary_); 1064 dict_ptr_->swap(*(other->dict_ptr_));
1024 } 1065 }
1025 1066
1026 DictionaryValue::Iterator::Iterator(const DictionaryValue& target) 1067 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
1027 : target_(target), 1068 : target_(target), it_((*target.dict_ptr_)->begin()) {}
1028 it_(target.dictionary_.begin()) {}
1029 1069
1030 DictionaryValue::Iterator::Iterator(const Iterator& other) = default; 1070 DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1031 1071
1032 DictionaryValue::Iterator::~Iterator() {} 1072 DictionaryValue::Iterator::~Iterator() {}
1033 1073
1034 DictionaryValue* DictionaryValue::DeepCopy() const { 1074 DictionaryValue* DictionaryValue::DeepCopy() const {
1035 DictionaryValue* result = new DictionaryValue; 1075 return static_cast<DictionaryValue*>(Value::DeepCopy());
1036
1037 for (const auto& current_entry : dictionary_) {
1038 result->SetWithoutPathExpansion(current_entry.first,
1039 current_entry.second->CreateDeepCopy());
1040 }
1041
1042 return result;
1043 } 1076 }
1044 1077
1045 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const { 1078 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1046 return WrapUnique(DeepCopy()); 1079 return WrapUnique(DeepCopy());
1047 } 1080 }
1048 1081
1049 bool DictionaryValue::Equals(const Value* other) const {
1050 if (other->GetType() != GetType())
1051 return false;
1052
1053 const DictionaryValue* other_dict =
1054 static_cast<const DictionaryValue*>(other);
1055 Iterator lhs_it(*this);
1056 Iterator rhs_it(*other_dict);
1057 while (!lhs_it.IsAtEnd() && !rhs_it.IsAtEnd()) {
1058 if (lhs_it.key() != rhs_it.key() ||
1059 !lhs_it.value().Equals(&rhs_it.value())) {
1060 return false;
1061 }
1062 lhs_it.Advance();
1063 rhs_it.Advance();
1064 }
1065 if (!lhs_it.IsAtEnd() || !rhs_it.IsAtEnd())
1066 return false;
1067
1068 return true;
1069 }
1070
1071 ///////////////////// ListValue //////////////////// 1082 ///////////////////// ListValue ////////////////////
1072 1083
1073 // static 1084 // static
1074 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) { 1085 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
1075 ListValue* out; 1086 ListValue* out;
1076 if (value && value->GetAsList(&out)) { 1087 if (value && value->GetAsList(&out)) {
1077 ignore_result(value.release()); 1088 ignore_result(value.release());
1078 return WrapUnique(out); 1089 return WrapUnique(out);
1079 } 1090 }
1080 return nullptr; 1091 return nullptr;
1081 } 1092 }
1082 1093
1083 ListValue::ListValue() : Value(Type::LIST) {} 1094 ListValue::ListValue() : Value(Type::LIST) {}
1084 1095
1085 ListValue::~ListValue() {
1086 Clear();
1087 }
1088
1089 void ListValue::Clear() { 1096 void ListValue::Clear() {
1090 list_.clear(); 1097 list_->clear();
1091 } 1098 }
1092 1099
1093 bool ListValue::Set(size_t index, Value* in_value) { 1100 bool ListValue::Set(size_t index, Value* in_value) {
1094 return Set(index, WrapUnique(in_value)); 1101 return Set(index, WrapUnique(in_value));
1095 } 1102 }
1096 1103
1097 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { 1104 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
1098 if (!in_value) 1105 if (!in_value)
1099 return false; 1106 return false;
1100 1107
1101 if (index >= list_.size()) { 1108 if (index >= list_->size()) {
1102 // Pad out any intermediate indexes with null settings 1109 // Pad out any intermediate indexes with null settings
1103 while (index > list_.size()) 1110 while (index > list_->size())
1104 Append(CreateNullValue()); 1111 Append(CreateNullValue());
1105 Append(std::move(in_value)); 1112 Append(std::move(in_value));
1106 } else { 1113 } else {
1107 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed? 1114 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed?
1108 DCHECK(list_[index] != in_value); 1115 DCHECK((*list_)[index] != in_value);
1109 list_[index] = std::move(in_value); 1116 (*list_)[index] = std::move(in_value);
1110 } 1117 }
1111 return true; 1118 return true;
1112 } 1119 }
1113 1120
1114 bool ListValue::Get(size_t index, const Value** out_value) const { 1121 bool ListValue::Get(size_t index, const Value** out_value) const {
1115 if (index >= list_.size()) 1122 if (index >= list_->size())
1116 return false; 1123 return false;
1117 1124
1118 if (out_value) 1125 if (out_value)
1119 *out_value = list_[index].get(); 1126 *out_value = (*list_)[index].get();
1120 1127
1121 return true; 1128 return true;
1122 } 1129 }
1123 1130
1124 bool ListValue::Get(size_t index, Value** out_value) { 1131 bool ListValue::Get(size_t index, Value** out_value) {
1125 return static_cast<const ListValue&>(*this).Get( 1132 return static_cast<const ListValue&>(*this).Get(
1126 index, 1133 index,
1127 const_cast<const Value**>(out_value)); 1134 const_cast<const Value**>(out_value));
1128 } 1135 }
1129 1136
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 return true; 1223 return true;
1217 } 1224 }
1218 1225
1219 bool ListValue::GetList(size_t index, ListValue** out_value) { 1226 bool ListValue::GetList(size_t index, ListValue** out_value) {
1220 return static_cast<const ListValue&>(*this).GetList( 1227 return static_cast<const ListValue&>(*this).GetList(
1221 index, 1228 index,
1222 const_cast<const ListValue**>(out_value)); 1229 const_cast<const ListValue**>(out_value));
1223 } 1230 }
1224 1231
1225 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { 1232 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
1226 if (index >= list_.size()) 1233 if (index >= list_->size())
1227 return false; 1234 return false;
1228 1235
1229 if (out_value) 1236 if (out_value)
1230 *out_value = std::move(list_[index]); 1237 *out_value = std::move((*list_)[index]);
1231 1238
1232 list_.erase(list_.begin() + index); 1239 list_->erase(list_->begin() + index);
1233 return true; 1240 return true;
1234 } 1241 }
1235 1242
1236 bool ListValue::Remove(const Value& value, size_t* index) { 1243 bool ListValue::Remove(const Value& value, size_t* index) {
1237 for (auto it = list_.begin(); it != list_.end(); ++it) { 1244 for (auto it = list_->begin(); it != list_->end(); ++it) {
1238 if ((*it)->Equals(&value)) { 1245 if ((*it)->Equals(&value)) {
1239 size_t previous_index = it - list_.begin(); 1246 size_t previous_index = it - list_->begin();
1240 list_.erase(it); 1247 list_->erase(it);
1241 1248
1242 if (index) 1249 if (index)
1243 *index = previous_index; 1250 *index = previous_index;
1244 return true; 1251 return true;
1245 } 1252 }
1246 } 1253 }
1247 return false; 1254 return false;
1248 } 1255 }
1249 1256
1250 ListValue::iterator ListValue::Erase(iterator iter, 1257 ListValue::iterator ListValue::Erase(iterator iter,
1251 std::unique_ptr<Value>* out_value) { 1258 std::unique_ptr<Value>* out_value) {
1252 if (out_value) 1259 if (out_value)
1253 *out_value = std::move(*Storage::iterator(iter)); 1260 *out_value = std::move(*ListStorage::iterator(iter));
1254 1261
1255 return list_.erase(iter); 1262 return list_->erase(iter);
1256 } 1263 }
1257 1264
1258 void ListValue::Append(std::unique_ptr<Value> in_value) { 1265 void ListValue::Append(std::unique_ptr<Value> in_value) {
1259 list_.push_back(std::move(in_value)); 1266 list_->push_back(std::move(in_value));
1260 } 1267 }
1261 1268
1262 #if !defined(OS_LINUX) 1269 #if !defined(OS_LINUX)
1263 void ListValue::Append(Value* in_value) { 1270 void ListValue::Append(Value* in_value) {
1264 DCHECK(in_value); 1271 DCHECK(in_value);
1265 Append(WrapUnique(in_value)); 1272 Append(WrapUnique(in_value));
1266 } 1273 }
1267 #endif 1274 #endif
1268 1275
1269 void ListValue::AppendBoolean(bool in_value) { 1276 void ListValue::AppendBoolean(bool in_value) {
(...skipping 25 matching lines...) Expand all
1295 1302
1296 void ListValue::AppendStrings(const std::vector<string16>& in_values) { 1303 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1297 for (std::vector<string16>::const_iterator it = in_values.begin(); 1304 for (std::vector<string16>::const_iterator it = in_values.begin();
1298 it != in_values.end(); ++it) { 1305 it != in_values.end(); ++it) {
1299 AppendString(*it); 1306 AppendString(*it);
1300 } 1307 }
1301 } 1308 }
1302 1309
1303 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { 1310 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1304 DCHECK(in_value); 1311 DCHECK(in_value);
1305 for (const auto& entry : list_) { 1312 for (const auto& entry : *list_) {
1306 if (entry->Equals(in_value.get())) { 1313 if (entry->Equals(in_value.get())) {
1307 return false; 1314 return false;
1308 } 1315 }
1309 } 1316 }
1310 list_.push_back(std::move(in_value)); 1317 list_->push_back(std::move(in_value));
1311 return true; 1318 return true;
1312 } 1319 }
1313 1320
1314 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { 1321 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1315 DCHECK(in_value); 1322 DCHECK(in_value);
1316 if (index > list_.size()) 1323 if (index > list_->size())
1317 return false; 1324 return false;
1318 1325
1319 list_.insert(list_.begin() + index, std::move(in_value)); 1326 list_->insert(list_->begin() + index, std::move(in_value));
1320 return true; 1327 return true;
1321 } 1328 }
1322 1329
1323 ListValue::const_iterator ListValue::Find(const Value& value) const { 1330 ListValue::const_iterator ListValue::Find(const Value& value) const {
1324 return std::find_if(list_.begin(), list_.end(), 1331 return std::find_if(list_->begin(), list_->end(),
1325 [&value](const std::unique_ptr<Value>& entry) { 1332 [&value](const std::unique_ptr<Value>& entry) {
1326 return entry->Equals(&value); 1333 return entry->Equals(&value);
1327 }); 1334 });
1328 } 1335 }
1329 1336
1330 void ListValue::Swap(ListValue* other) { 1337 void ListValue::Swap(ListValue* other) {
1331 list_.swap(other->list_); 1338 list_->swap(*(other->list_));
1332 }
1333
1334 bool ListValue::GetAsList(ListValue** out_value) {
1335 if (out_value)
1336 *out_value = this;
1337 return true;
1338 }
1339
1340 bool ListValue::GetAsList(const ListValue** out_value) const {
1341 if (out_value)
1342 *out_value = this;
1343 return true;
1344 } 1339 }
1345 1340
1346 ListValue* ListValue::DeepCopy() const { 1341 ListValue* ListValue::DeepCopy() const {
1347 ListValue* result = new ListValue; 1342 return static_cast<ListValue*>(Value::DeepCopy());
1348
1349 for (const auto& entry : list_)
1350 result->Append(entry->CreateDeepCopy());
1351
1352 return result;
1353 } 1343 }
1354 1344
1355 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const { 1345 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1356 return WrapUnique(DeepCopy()); 1346 return WrapUnique(DeepCopy());
1357 } 1347 }
1358 1348
1359 bool ListValue::Equals(const Value* other) const {
1360 if (other->GetType() != GetType())
1361 return false;
1362
1363 const ListValue* other_list =
1364 static_cast<const ListValue*>(other);
1365 Storage::const_iterator lhs_it, rhs_it;
1366 for (lhs_it = begin(), rhs_it = other_list->begin();
1367 lhs_it != end() && rhs_it != other_list->end();
1368 ++lhs_it, ++rhs_it) {
1369 if (!(*lhs_it)->Equals(rhs_it->get()))
1370 return false;
1371 }
1372 if (lhs_it != end() || rhs_it != other_list->end())
1373 return false;
1374
1375 return true;
1376 }
1377
1378 ValueSerializer::~ValueSerializer() { 1349 ValueSerializer::~ValueSerializer() {
1379 } 1350 }
1380 1351
1381 ValueDeserializer::~ValueDeserializer() { 1352 ValueDeserializer::~ValueDeserializer() {
1382 } 1353 }
1383 1354
1384 std::ostream& operator<<(std::ostream& out, const Value& value) { 1355 std::ostream& operator<<(std::ostream& out, const Value& value) {
1385 std::string json; 1356 std::string json;
1386 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); 1357 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
1387 return out << json; 1358 return out << json;
1388 } 1359 }
1389 1360
1390 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1361 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1391 if (static_cast<int>(type) < 0 || 1362 if (static_cast<int>(type) < 0 ||
1392 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1363 static_cast<size_t>(type) >= arraysize(kTypeNames))
1393 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1364 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1394 return out << Value::GetTypeName(type); 1365 return out << Value::GetTypeName(type);
1395 } 1366 }
1396 1367
1397 } // namespace base 1368 } // namespace base
OLDNEW
« base/values.h ('K') | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698