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

Side by Side Diff: base/values.cc

Issue 2683203004: Move Storage for ListValue and DictValue in Union (Closed)
Patch Set: Rebase 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 case Type::DICTIONARY:
452 // TODO(crbug.com/646113): Implement these once the corresponding derived
453 // classes are removed.
454 case Type::LIST: 501 case Type::LIST:
455 case Type::DICTIONARY: 502 // Currently not implementable due to the presence of unique_ptrs in
brettw 2017/02/14 23:15:04 I don't quite follow. Shouldn't this be the same a
jdoerrie 2017/02/15 15:29:08 Yes, you are right. When writing this I just consi
503 // DictStorage and ListStorage.
504 // TODO(crbug.com/646113): Implement this when DictionaryValues and
505 // ListValues are completely inlined.
506 NOTREACHED();
456 return; 507 return;
457 } 508 }
458 } 509 }
459 510
460 void Value::InternalMoveConstructFrom(Value&& that) { 511 void Value::InternalMoveConstructFrom(Value&& that) {
461 type_ = that.type_; 512 type_ = that.type_;
462 513
463 switch (type_) { 514 switch (type_) {
464 case Type::NONE: 515 case Type::NONE:
465 case Type::BOOLEAN: 516 case Type::BOOLEAN:
466 case Type::INTEGER: 517 case Type::INTEGER:
467 case Type::DOUBLE: 518 case Type::DOUBLE:
468 InternalCopyFundamentalValue(that); 519 InternalCopyFundamentalValue(that);
469 return; 520 return;
470 521
471 case Type::STRING: 522 case Type::STRING:
472 string_value_.InitFromMove(std::move(that.string_value_)); 523 string_value_.InitFromMove(std::move(that.string_value_));
473 return; 524 return;
474 case Type::BINARY: 525 case Type::BINARY:
475 binary_value_.InitFromMove(std::move(that.binary_value_)); 526 binary_value_.InitFromMove(std::move(that.binary_value_));
476 return; 527 return;
477 528 case Type::DICTIONARY:
478 // TODO(crbug.com/646113): Implement these once the corresponding derived 529 dict_ptr_.InitFromMove(std::move(that.dict_ptr_));
479 // classes are removed. 530 return;
480 case Type::LIST: 531 case Type::LIST:
481 case Type::DICTIONARY: 532 list_.InitFromMove(std::move(that.list_));
482 return; 533 return;
483 } 534 }
484 } 535 }
485 536
486 void Value::InternalCopyAssignFrom(const Value& that) { 537 void Value::InternalCopyAssignFrom(const Value& that) {
487 type_ = that.type_; 538 type_ = that.type_;
488 539
489 switch (type_) { 540 switch (type_) {
490 case Type::NONE: 541 case Type::NONE:
491 case Type::BOOLEAN: 542 case Type::BOOLEAN:
492 case Type::INTEGER: 543 case Type::INTEGER:
493 case Type::DOUBLE: 544 case Type::DOUBLE:
494 InternalCopyFundamentalValue(that); 545 InternalCopyFundamentalValue(that);
495 return; 546 return;
496 547
497 case Type::STRING: 548 case Type::STRING:
498 *string_value_ = *that.string_value_; 549 *string_value_ = *that.string_value_;
499 return; 550 return;
500 case Type::BINARY: 551 case Type::BINARY:
501 *binary_value_ = *that.binary_value_; 552 *binary_value_ = *that.binary_value_;
502 return; 553 return;
503 554 case Type::DICTIONARY:
504 // TODO(crbug.com/646113): Implement these once the corresponding derived
505 // classes are removed.
506 case Type::LIST: 555 case Type::LIST:
507 case Type::DICTIONARY: 556 // Currently not implementable due to the presence of unique_ptrs in
brettw 2017/02/14 23:15:05 Same here.
jdoerrie 2017/02/15 15:29:08 Acknowledged.
557 // DictStorage and ListStorage.
558 // TODO(crbug.com/646113): Implement this when DictionaryValues and
559 // ListValues are completely inlined.
560 NOTREACHED();
508 return; 561 return;
509 } 562 }
510 } 563 }
511 564
512 void Value::InternalMoveAssignFrom(Value&& that) { 565 void Value::InternalMoveAssignFrom(Value&& that) {
513 type_ = that.type_; 566 type_ = that.type_;
514 567
515 switch (type_) { 568 switch (type_) {
516 case Type::NONE: 569 case Type::NONE:
517 case Type::BOOLEAN: 570 case Type::BOOLEAN:
518 case Type::INTEGER: 571 case Type::INTEGER:
519 case Type::DOUBLE: 572 case Type::DOUBLE:
520 InternalCopyFundamentalValue(that); 573 InternalCopyFundamentalValue(that);
521 return; 574 return;
522 575
523 case Type::STRING: 576 case Type::STRING:
524 *string_value_ = std::move(*that.string_value_); 577 *string_value_ = std::move(*that.string_value_);
525 return; 578 return;
526 case Type::BINARY: 579 case Type::BINARY:
527 *binary_value_ = std::move(*that.binary_value_); 580 *binary_value_ = std::move(*that.binary_value_);
528 return; 581 return;
529 582 case Type::DICTIONARY:
530 // TODO(crbug.com/646113): Implement these once the corresponding derived 583 *dict_ptr_ = std::move(*that.dict_ptr_);
531 // classes are removed. 584 return;
532 case Type::LIST: 585 case Type::LIST:
533 case Type::DICTIONARY: 586 *list_ = std::move(*that.list_);
534 return; 587 return;
535 } 588 }
536 } 589 }
537 590
538 void Value::InternalCleanup() { 591 void Value::InternalCleanup() {
539 switch (type_) { 592 switch (type_) {
540 case Type::NONE: 593 case Type::NONE:
541 case Type::BOOLEAN: 594 case Type::BOOLEAN:
542 case Type::INTEGER: 595 case Type::INTEGER:
543 case Type::DOUBLE: 596 case Type::DOUBLE:
544 // Nothing to do 597 // Nothing to do
545 return; 598 return;
546 599
547 case Type::STRING: 600 case Type::STRING:
548 string_value_.Destroy(); 601 string_value_.Destroy();
549 return; 602 return;
550 case Type::BINARY: 603 case Type::BINARY:
551 binary_value_.Destroy(); 604 binary_value_.Destroy();
552 return; 605 return;
553 606 case Type::DICTIONARY:
554 // TODO(crbug.com/646113): Implement these once the corresponding derived 607 dict_ptr_.Destroy();
555 // classes are removed. 608 return;
556 case Type::LIST: 609 case Type::LIST:
557 case Type::DICTIONARY: 610 list_.Destroy();
558 return; 611 return;
559 } 612 }
560 } 613 }
561 614
562 ///////////////////// DictionaryValue //////////////////// 615 ///////////////////// DictionaryValue ////////////////////
563 616
564 // static 617 // static
565 std::unique_ptr<DictionaryValue> DictionaryValue::From( 618 std::unique_ptr<DictionaryValue> DictionaryValue::From(
566 std::unique_ptr<Value> value) { 619 std::unique_ptr<Value> value) {
567 DictionaryValue* out; 620 DictionaryValue* out;
568 if (value && value->GetAsDictionary(&out)) { 621 if (value && value->GetAsDictionary(&out)) {
569 ignore_result(value.release()); 622 ignore_result(value.release());
570 return WrapUnique(out); 623 return WrapUnique(out);
571 } 624 }
572 return nullptr; 625 return nullptr;
573 } 626 }
574 627
575 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {} 628 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
576 629
577 DictionaryValue::~DictionaryValue() { 630 DictionaryValue::DictionaryValue(DictionaryValue&& that) = default;
578 Clear();
579 }
580 631
581 bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) { 632 DictionaryValue& DictionaryValue::operator=(DictionaryValue&& that) = default;
582 if (out_value)
583 *out_value = this;
584 return true;
585 }
586 633
587 bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const { 634 DictionaryValue::~DictionaryValue() = default;
588 if (out_value)
589 *out_value = this;
590 return true;
591 }
592 635
593 bool DictionaryValue::HasKey(StringPiece key) const { 636 bool DictionaryValue::HasKey(StringPiece key) const {
594 DCHECK(IsStringUTF8(key)); 637 DCHECK(IsStringUTF8(key));
595 auto current_entry = dictionary_.find(key.as_string()); 638 auto current_entry = (*dict_ptr_)->find(key.as_string());
596 DCHECK((current_entry == dictionary_.end()) || current_entry->second); 639 DCHECK((current_entry == (*dict_ptr_)->end()) || current_entry->second);
597 return current_entry != dictionary_.end(); 640 return current_entry != (*dict_ptr_)->end();
598 } 641 }
599 642
600 void DictionaryValue::Clear() { 643 void DictionaryValue::Clear() {
601 dictionary_.clear(); 644 (*dict_ptr_)->clear();
602 } 645 }
603 646
604 void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) { 647 void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
605 DCHECK(IsStringUTF8(path)); 648 DCHECK(IsStringUTF8(path));
606 DCHECK(in_value); 649 DCHECK(in_value);
607 650
608 StringPiece current_path(path); 651 StringPiece current_path(path);
609 DictionaryValue* current_dictionary = this; 652 DictionaryValue* current_dictionary = this;
610 for (size_t delimiter_position = current_path.find('.'); 653 for (size_t delimiter_position = current_path.find('.');
611 delimiter_position != StringPiece::npos; 654 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) { 689 void DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
647 Set(path, new StringValue(in_value)); 690 Set(path, new StringValue(in_value));
648 } 691 }
649 692
650 void DictionaryValue::SetString(StringPiece path, const string16& in_value) { 693 void DictionaryValue::SetString(StringPiece path, const string16& in_value) {
651 Set(path, new StringValue(in_value)); 694 Set(path, new StringValue(in_value));
652 } 695 }
653 696
654 void DictionaryValue::SetWithoutPathExpansion(StringPiece key, 697 void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
655 std::unique_ptr<Value> in_value) { 698 std::unique_ptr<Value> in_value) {
656 dictionary_[key.as_string()] = std::move(in_value); 699 (**dict_ptr_)[key.as_string()] = std::move(in_value);
657 } 700 }
658 701
659 void DictionaryValue::SetWithoutPathExpansion(StringPiece key, 702 void DictionaryValue::SetWithoutPathExpansion(StringPiece key,
660 Value* in_value) { 703 Value* in_value) {
661 SetWithoutPathExpansion(key, WrapUnique(in_value)); 704 SetWithoutPathExpansion(key, WrapUnique(in_value));
662 } 705 }
663 706
664 void DictionaryValue::SetBooleanWithoutPathExpansion(StringPiece path, 707 void DictionaryValue::SetBooleanWithoutPathExpansion(StringPiece path,
665 bool in_value) { 708 bool in_value) {
666 SetWithoutPathExpansion(path, 709 SetWithoutPathExpansion(path,
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 869
827 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) { 870 bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) {
828 return static_cast<const DictionaryValue&>(*this).GetList( 871 return static_cast<const DictionaryValue&>(*this).GetList(
829 path, 872 path,
830 const_cast<const ListValue**>(out_value)); 873 const_cast<const ListValue**>(out_value));
831 } 874 }
832 875
833 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 876 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
834 const Value** out_value) const { 877 const Value** out_value) const {
835 DCHECK(IsStringUTF8(key)); 878 DCHECK(IsStringUTF8(key));
836 auto entry_iterator = dictionary_.find(key.as_string()); 879 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
837 if (entry_iterator == dictionary_.end()) 880 if (entry_iterator == (*dict_ptr_)->end())
838 return false; 881 return false;
839 882
840 if (out_value) 883 if (out_value)
841 *out_value = entry_iterator->second.get(); 884 *out_value = entry_iterator->second.get();
842 return true; 885 return true;
843 } 886 }
844 887
845 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, 888 bool DictionaryValue::GetWithoutPathExpansion(StringPiece key,
846 Value** out_value) { 889 Value** out_value) {
847 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion( 890 return static_cast<const DictionaryValue&>(*this).GetWithoutPathExpansion(
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 } 998 }
956 999
957 return current_dictionary->RemoveWithoutPathExpansion(current_path, 1000 return current_dictionary->RemoveWithoutPathExpansion(current_path,
958 out_value); 1001 out_value);
959 } 1002 }
960 1003
961 bool DictionaryValue::RemoveWithoutPathExpansion( 1004 bool DictionaryValue::RemoveWithoutPathExpansion(
962 StringPiece key, 1005 StringPiece key,
963 std::unique_ptr<Value>* out_value) { 1006 std::unique_ptr<Value>* out_value) {
964 DCHECK(IsStringUTF8(key)); 1007 DCHECK(IsStringUTF8(key));
965 auto entry_iterator = dictionary_.find(key.as_string()); 1008 auto entry_iterator = (*dict_ptr_)->find(key.as_string());
966 if (entry_iterator == dictionary_.end()) 1009 if (entry_iterator == (*dict_ptr_)->end())
967 return false; 1010 return false;
968 1011
969 if (out_value) 1012 if (out_value)
970 *out_value = std::move(entry_iterator->second); 1013 *out_value = std::move(entry_iterator->second);
971 dictionary_.erase(entry_iterator); 1014 (*dict_ptr_)->erase(entry_iterator);
972 return true; 1015 return true;
973 } 1016 }
974 1017
975 bool DictionaryValue::RemovePath(StringPiece path, 1018 bool DictionaryValue::RemovePath(StringPiece path,
976 std::unique_ptr<Value>* out_value) { 1019 std::unique_ptr<Value>* out_value) {
977 bool result = false; 1020 bool result = false;
978 size_t delimiter_position = path.find('.'); 1021 size_t delimiter_position = path.find('.');
979 1022
980 if (delimiter_position == std::string::npos) 1023 if (delimiter_position == std::string::npos)
981 return RemoveWithoutPathExpansion(path, out_value); 1024 return RemoveWithoutPathExpansion(path, out_value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 continue; 1056 continue;
1014 } 1057 }
1015 } 1058 }
1016 // All other cases: Make a copy and hook it up. 1059 // All other cases: Make a copy and hook it up.
1017 SetWithoutPathExpansion(it.key(), 1060 SetWithoutPathExpansion(it.key(),
1018 base::WrapUnique(merge_value->DeepCopy())); 1061 base::WrapUnique(merge_value->DeepCopy()));
1019 } 1062 }
1020 } 1063 }
1021 1064
1022 void DictionaryValue::Swap(DictionaryValue* other) { 1065 void DictionaryValue::Swap(DictionaryValue* other) {
1023 dictionary_.swap(other->dictionary_); 1066 dict_ptr_->swap(*(other->dict_ptr_));
1024 } 1067 }
1025 1068
1026 DictionaryValue::Iterator::Iterator(const DictionaryValue& target) 1069 DictionaryValue::Iterator::Iterator(const DictionaryValue& target)
1027 : target_(target), 1070 : target_(target), it_((*target.dict_ptr_)->begin()) {}
1028 it_(target.dictionary_.begin()) {}
1029 1071
1030 DictionaryValue::Iterator::Iterator(const Iterator& other) = default; 1072 DictionaryValue::Iterator::Iterator(const Iterator& other) = default;
1031 1073
1032 DictionaryValue::Iterator::~Iterator() {} 1074 DictionaryValue::Iterator::~Iterator() {}
1033 1075
1034 DictionaryValue* DictionaryValue::DeepCopy() const { 1076 DictionaryValue* DictionaryValue::DeepCopy() const {
1035 DictionaryValue* result = new DictionaryValue; 1077 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 } 1078 }
1044 1079
1045 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const { 1080 std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const {
1046 return WrapUnique(DeepCopy()); 1081 return WrapUnique(DeepCopy());
1047 } 1082 }
1048 1083
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 //////////////////// 1084 ///////////////////// ListValue ////////////////////
1072 1085
1073 // static 1086 // static
1074 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) { 1087 std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) {
1075 ListValue* out; 1088 ListValue* out;
1076 if (value && value->GetAsList(&out)) { 1089 if (value && value->GetAsList(&out)) {
1077 ignore_result(value.release()); 1090 ignore_result(value.release());
1078 return WrapUnique(out); 1091 return WrapUnique(out);
1079 } 1092 }
1080 return nullptr; 1093 return nullptr;
1081 } 1094 }
1082 1095
1083 ListValue::ListValue() : Value(Type::LIST) {} 1096 ListValue::ListValue() : Value(Type::LIST) {}
1084 1097
1085 ListValue::~ListValue() { 1098 ListValue::ListValue(ListValue&& that) = default;
1086 Clear(); 1099
1087 } 1100 ListValue& ListValue::operator=(ListValue&& that) = default;
1101
1102 ListValue::~ListValue() = default;
1088 1103
1089 void ListValue::Clear() { 1104 void ListValue::Clear() {
1090 list_.clear(); 1105 list_->clear();
1091 } 1106 }
1092 1107
1093 bool ListValue::Set(size_t index, Value* in_value) { 1108 bool ListValue::Set(size_t index, Value* in_value) {
1094 return Set(index, WrapUnique(in_value)); 1109 return Set(index, WrapUnique(in_value));
1095 } 1110 }
1096 1111
1097 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { 1112 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) {
1098 if (!in_value) 1113 if (!in_value)
1099 return false; 1114 return false;
1100 1115
1101 if (index >= list_.size()) { 1116 if (index >= list_->size()) {
1102 // Pad out any intermediate indexes with null settings 1117 // Pad out any intermediate indexes with null settings
1103 while (index > list_.size()) 1118 while (index > list_->size())
1104 Append(CreateNullValue()); 1119 Append(CreateNullValue());
1105 Append(std::move(in_value)); 1120 Append(std::move(in_value));
1106 } else { 1121 } else {
1107 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed? 1122 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed?
1108 DCHECK(list_[index] != in_value); 1123 DCHECK((*list_)[index] != in_value);
1109 list_[index] = std::move(in_value); 1124 (*list_)[index] = std::move(in_value);
1110 } 1125 }
1111 return true; 1126 return true;
1112 } 1127 }
1113 1128
1114 bool ListValue::Get(size_t index, const Value** out_value) const { 1129 bool ListValue::Get(size_t index, const Value** out_value) const {
1115 if (index >= list_.size()) 1130 if (index >= list_->size())
1116 return false; 1131 return false;
1117 1132
1118 if (out_value) 1133 if (out_value)
1119 *out_value = list_[index].get(); 1134 *out_value = (*list_)[index].get();
1120 1135
1121 return true; 1136 return true;
1122 } 1137 }
1123 1138
1124 bool ListValue::Get(size_t index, Value** out_value) { 1139 bool ListValue::Get(size_t index, Value** out_value) {
1125 return static_cast<const ListValue&>(*this).Get( 1140 return static_cast<const ListValue&>(*this).Get(
1126 index, 1141 index,
1127 const_cast<const Value**>(out_value)); 1142 const_cast<const Value**>(out_value));
1128 } 1143 }
1129 1144
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 return true; 1231 return true;
1217 } 1232 }
1218 1233
1219 bool ListValue::GetList(size_t index, ListValue** out_value) { 1234 bool ListValue::GetList(size_t index, ListValue** out_value) {
1220 return static_cast<const ListValue&>(*this).GetList( 1235 return static_cast<const ListValue&>(*this).GetList(
1221 index, 1236 index,
1222 const_cast<const ListValue**>(out_value)); 1237 const_cast<const ListValue**>(out_value));
1223 } 1238 }
1224 1239
1225 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { 1240 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) {
1226 if (index >= list_.size()) 1241 if (index >= list_->size())
1227 return false; 1242 return false;
1228 1243
1229 if (out_value) 1244 if (out_value)
1230 *out_value = std::move(list_[index]); 1245 *out_value = std::move((*list_)[index]);
1231 1246
1232 list_.erase(list_.begin() + index); 1247 list_->erase(list_->begin() + index);
1233 return true; 1248 return true;
1234 } 1249 }
1235 1250
1236 bool ListValue::Remove(const Value& value, size_t* index) { 1251 bool ListValue::Remove(const Value& value, size_t* index) {
1237 for (auto it = list_.begin(); it != list_.end(); ++it) { 1252 for (auto it = list_->begin(); it != list_->end(); ++it) {
1238 if ((*it)->Equals(&value)) { 1253 if ((*it)->Equals(&value)) {
1239 size_t previous_index = it - list_.begin(); 1254 size_t previous_index = it - list_->begin();
1240 list_.erase(it); 1255 list_->erase(it);
1241 1256
1242 if (index) 1257 if (index)
1243 *index = previous_index; 1258 *index = previous_index;
1244 return true; 1259 return true;
1245 } 1260 }
1246 } 1261 }
1247 return false; 1262 return false;
1248 } 1263 }
1249 1264
1250 ListValue::iterator ListValue::Erase(iterator iter, 1265 ListValue::iterator ListValue::Erase(iterator iter,
1251 std::unique_ptr<Value>* out_value) { 1266 std::unique_ptr<Value>* out_value) {
1252 if (out_value) 1267 if (out_value)
1253 *out_value = std::move(*Storage::iterator(iter)); 1268 *out_value = std::move(*ListStorage::iterator(iter));
1254 1269
1255 return list_.erase(iter); 1270 return list_->erase(iter);
1256 } 1271 }
1257 1272
1258 void ListValue::Append(std::unique_ptr<Value> in_value) { 1273 void ListValue::Append(std::unique_ptr<Value> in_value) {
1259 list_.push_back(std::move(in_value)); 1274 list_->push_back(std::move(in_value));
1260 } 1275 }
1261 1276
1262 #if !defined(OS_LINUX) 1277 #if !defined(OS_LINUX)
1263 void ListValue::Append(Value* in_value) { 1278 void ListValue::Append(Value* in_value) {
1264 DCHECK(in_value); 1279 DCHECK(in_value);
1265 Append(WrapUnique(in_value)); 1280 Append(WrapUnique(in_value));
1266 } 1281 }
1267 #endif 1282 #endif
1268 1283
1269 void ListValue::AppendBoolean(bool in_value) { 1284 void ListValue::AppendBoolean(bool in_value) {
(...skipping 25 matching lines...) Expand all
1295 1310
1296 void ListValue::AppendStrings(const std::vector<string16>& in_values) { 1311 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1297 for (std::vector<string16>::const_iterator it = in_values.begin(); 1312 for (std::vector<string16>::const_iterator it = in_values.begin();
1298 it != in_values.end(); ++it) { 1313 it != in_values.end(); ++it) {
1299 AppendString(*it); 1314 AppendString(*it);
1300 } 1315 }
1301 } 1316 }
1302 1317
1303 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { 1318 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1304 DCHECK(in_value); 1319 DCHECK(in_value);
1305 for (const auto& entry : list_) { 1320 for (const auto& entry : *list_) {
1306 if (entry->Equals(in_value.get())) { 1321 if (entry->Equals(in_value.get())) {
1307 return false; 1322 return false;
1308 } 1323 }
1309 } 1324 }
1310 list_.push_back(std::move(in_value)); 1325 list_->push_back(std::move(in_value));
1311 return true; 1326 return true;
1312 } 1327 }
1313 1328
1314 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { 1329 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1315 DCHECK(in_value); 1330 DCHECK(in_value);
1316 if (index > list_.size()) 1331 if (index > list_->size())
1317 return false; 1332 return false;
1318 1333
1319 list_.insert(list_.begin() + index, std::move(in_value)); 1334 list_->insert(list_->begin() + index, std::move(in_value));
1320 return true; 1335 return true;
1321 } 1336 }
1322 1337
1323 ListValue::const_iterator ListValue::Find(const Value& value) const { 1338 ListValue::const_iterator ListValue::Find(const Value& value) const {
1324 return std::find_if(list_.begin(), list_.end(), 1339 return std::find_if(list_->begin(), list_->end(),
1325 [&value](const std::unique_ptr<Value>& entry) { 1340 [&value](const std::unique_ptr<Value>& entry) {
1326 return entry->Equals(&value); 1341 return entry->Equals(&value);
1327 }); 1342 });
1328 } 1343 }
1329 1344
1330 void ListValue::Swap(ListValue* other) { 1345 void ListValue::Swap(ListValue* other) {
1331 list_.swap(other->list_); 1346 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 } 1347 }
1345 1348
1346 ListValue* ListValue::DeepCopy() const { 1349 ListValue* ListValue::DeepCopy() const {
1347 ListValue* result = new ListValue; 1350 return static_cast<ListValue*>(Value::DeepCopy());
1348
1349 for (const auto& entry : list_)
1350 result->Append(entry->CreateDeepCopy());
1351
1352 return result;
1353 } 1351 }
1354 1352
1355 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const { 1353 std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const {
1356 return WrapUnique(DeepCopy()); 1354 return WrapUnique(DeepCopy());
1357 } 1355 }
1358 1356
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() { 1357 ValueSerializer::~ValueSerializer() {
1379 } 1358 }
1380 1359
1381 ValueDeserializer::~ValueDeserializer() { 1360 ValueDeserializer::~ValueDeserializer() {
1382 } 1361 }
1383 1362
1384 std::ostream& operator<<(std::ostream& out, const Value& value) { 1363 std::ostream& operator<<(std::ostream& out, const Value& value) {
1385 std::string json; 1364 std::string json;
1386 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); 1365 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
1387 return out << json; 1366 return out << json;
1388 } 1367 }
1389 1368
1390 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1369 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1391 if (static_cast<int>(type) < 0 || 1370 if (static_cast<int>(type) < 0 ||
1392 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1371 static_cast<size_t>(type) >= arraysize(kTypeNames))
1393 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1372 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1394 return out << Value::GetTypeName(type); 1373 return out << Value::GetTypeName(type);
1395 } 1374 }
1396 1375
1397 } // namespace base 1376 } // 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