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 17 matching lines...) Expand all Loading... | |
28 "kTypeNames Has Wrong Size"); | 28 "kTypeNames Has Wrong Size"); |
29 | 29 |
30 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node); | 30 std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node); |
31 | 31 |
32 // Make a deep copy of |node|, but don't include empty lists or dictionaries | 32 // Make a deep copy of |node|, but don't include empty lists or dictionaries |
33 // in the copy. It's possible for this function to return NULL and it | 33 // in the copy. It's possible for this function to return NULL and it |
34 // expects |node| to always be non-NULL. | 34 // expects |node| to always be non-NULL. |
35 std::unique_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) { | 35 std::unique_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) { |
36 std::unique_ptr<ListValue> copy; | 36 std::unique_ptr<ListValue> copy; |
37 for (const auto& entry : list) { | 37 for (const auto& entry : list) { |
38 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(*entry); | 38 std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry); |
39 if (child_copy) { | 39 if (child_copy) { |
40 if (!copy) | 40 if (!copy) |
41 copy.reset(new ListValue); | 41 copy.reset(new ListValue); |
42 copy->Append(std::move(child_copy)); | 42 copy->Append(std::move(child_copy)); |
43 } | 43 } |
44 } | 44 } |
45 return copy; | 45 return copy; |
46 } | 46 } |
47 | 47 |
48 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( | 48 std::unique_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 Value::Value(StringPiece in_string) : Value(in_string.as_string()) {} | 165 Value::Value(StringPiece in_string) : Value(in_string.as_string()) {} |
166 | 166 |
167 Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) { | 167 Value::Value(const std::vector<char>& in_blob) : type_(Type::BINARY) { |
168 binary_value_.Init(in_blob); | 168 binary_value_.Init(in_blob); |
169 } | 169 } |
170 | 170 |
171 Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) { | 171 Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) { |
172 binary_value_.Init(std::move(in_blob)); | 172 binary_value_.Init(std::move(in_blob)); |
173 } | 173 } |
174 | 174 |
175 Value::Value(const ListStorage& in_list) : type_(Type::LIST) { | |
176 list_.Init(in_list); | |
177 } | |
178 | |
179 Value::Value(ListStorage&& in_list) : type_(Type::LIST) { | |
180 list_.Init(std::move(in_list)); | |
181 } | |
182 | |
175 Value& Value::operator=(const Value& that) { | 183 Value& Value::operator=(const Value& that) { |
176 if (this != &that) { | 184 if (this != &that) { |
177 if (type_ == that.type_) { | 185 if (type_ == that.type_) { |
178 InternalCopyAssignFromSameType(that); | 186 InternalCopyAssignFromSameType(that); |
179 } else { | 187 } else { |
180 InternalCleanup(); | 188 InternalCleanup(); |
181 InternalCopyConstructFrom(that); | 189 InternalCopyConstructFrom(that); |
182 } | 190 } |
183 } | 191 } |
184 | 192 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 DictionaryValue* result = new DictionaryValue; | 381 DictionaryValue* result = new DictionaryValue; |
374 | 382 |
375 for (const auto& current_entry : **dict_ptr_) { | 383 for (const auto& current_entry : **dict_ptr_) { |
376 result->SetWithoutPathExpansion(current_entry.first, | 384 result->SetWithoutPathExpansion(current_entry.first, |
377 current_entry.second->CreateDeepCopy()); | 385 current_entry.second->CreateDeepCopy()); |
378 } | 386 } |
379 | 387 |
380 return result; | 388 return result; |
381 } | 389 } |
382 | 390 |
383 case Type::LIST: { | 391 case Type::LIST: |
384 ListValue* result = new ListValue; | 392 return new Value(*list_); |
385 | |
386 for (const auto& entry : *list_) | |
387 result->Append(entry->CreateDeepCopy()); | |
388 | |
389 return result; | |
390 } | |
391 | 393 |
392 default: | 394 default: |
393 NOTREACHED(); | 395 NOTREACHED(); |
394 return nullptr; | 396 return nullptr; |
395 } | 397 } |
396 } | 398 } |
397 | 399 |
398 std::unique_ptr<Value> Value::CreateDeepCopy() const { | 400 std::unique_ptr<Value> Value::CreateDeepCopy() const { |
399 return WrapUnique(DeepCopy()); | 401 return WrapUnique(DeepCopy()); |
400 } | 402 } |
(...skipping 28 matching lines...) Expand all Loading... | |
429 if (lhs.first != rhs.first) | 431 if (lhs.first != rhs.first) |
430 return false; | 432 return false; |
431 | 433 |
432 return lhs.second->Equals(rhs.second.get()); | 434 return lhs.second->Equals(rhs.second.get()); |
433 }); | 435 }); |
434 } | 436 } |
435 case Type::LIST: { | 437 case Type::LIST: { |
436 if (list_->size() != other->list_->size()) | 438 if (list_->size() != other->list_->size()) |
437 return false; | 439 return false; |
438 | 440 |
439 return std::equal(std::begin(*list_), std::end(*list_), | 441 return std::equal( |
440 std::begin(*(other->list_)), | 442 std::begin(*list_), std::end(*list_), std::begin(*(other->list_)), |
441 [](const ListStorage::value_type& lhs, | 443 [](const ListStorage::value_type& lhs, |
442 const ListStorage::value_type& rhs) { | 444 const ListStorage::value_type& rhs) { return lhs.Equals(&rhs); }); |
443 return lhs->Equals(rhs.get()); | |
444 }); | |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 NOTREACHED(); | 448 NOTREACHED(); |
449 return false; | 449 return false; |
450 } | 450 } |
451 | 451 |
452 // static | 452 // static |
453 bool Value::Equals(const Value* a, const Value* b) { | 453 bool Value::Equals(const Value* a, const Value* b) { |
454 if ((a == NULL) && (b == NULL)) return true; | 454 if ((a == NULL) && (b == NULL)) return true; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 case Type::DOUBLE: | 487 case Type::DOUBLE: |
488 InternalCopyFundamentalValue(that); | 488 InternalCopyFundamentalValue(that); |
489 return; | 489 return; |
490 | 490 |
491 case Type::STRING: | 491 case Type::STRING: |
492 string_value_.Init(*that.string_value_); | 492 string_value_.Init(*that.string_value_); |
493 return; | 493 return; |
494 case Type::BINARY: | 494 case Type::BINARY: |
495 binary_value_.Init(*that.binary_value_); | 495 binary_value_.Init(*that.binary_value_); |
496 return; | 496 return; |
497 // DictStorage and ListStorage are move-only types due to the presence of | 497 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
498 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 498 // is why the call to |CreateDeepCopy| is necessary here. |
499 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 499 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
500 // can be copied directly. | 500 // directly. |
501 case Type::DICTIONARY: | 501 case Type::DICTIONARY: |
502 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_)); | 502 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_)); |
brettw
2017/03/17 05:39:19
I suspect this line is causing the Android crash.
jdoerrie
2017/03/23 18:11:17
Unfortunately this didn't solve the issue. After m
| |
503 return; | 503 return; |
504 case Type::LIST: | 504 case Type::LIST: |
505 list_.Init(std::move(*that.CreateDeepCopy()->list_)); | 505 list_.Init(*that.list_); |
506 return; | 506 return; |
507 } | 507 } |
508 } | 508 } |
509 | 509 |
510 void Value::InternalMoveConstructFrom(Value&& that) { | 510 void Value::InternalMoveConstructFrom(Value&& that) { |
511 type_ = that.type_; | 511 type_ = that.type_; |
512 | 512 |
513 switch (type_) { | 513 switch (type_) { |
514 case Type::NONE: | 514 case Type::NONE: |
515 case Type::BOOLEAN: | 515 case Type::BOOLEAN: |
(...skipping 27 matching lines...) Expand all Loading... | |
543 case Type::DOUBLE: | 543 case Type::DOUBLE: |
544 InternalCopyFundamentalValue(that); | 544 InternalCopyFundamentalValue(that); |
545 return; | 545 return; |
546 | 546 |
547 case Type::STRING: | 547 case Type::STRING: |
548 *string_value_ = *that.string_value_; | 548 *string_value_ = *that.string_value_; |
549 return; | 549 return; |
550 case Type::BINARY: | 550 case Type::BINARY: |
551 *binary_value_ = *that.binary_value_; | 551 *binary_value_ = *that.binary_value_; |
552 return; | 552 return; |
553 // DictStorage and ListStorage are move-only types due to the presence of | 553 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
554 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 554 // is why the call to |CreateDeepCopy| is necessary here. |
555 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 555 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
556 // can be copied directly. | 556 // directly. |
557 case Type::DICTIONARY: | 557 case Type::DICTIONARY: |
558 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_); | 558 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_); |
brettw
2017/03/17 05:39:19
Ditto here.
| |
559 return; | 559 return; |
560 case Type::LIST: | 560 case Type::LIST: |
561 *list_ = std::move(*that.CreateDeepCopy()->list_); | 561 *list_ = *that.list_; |
562 return; | 562 return; |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 void Value::InternalMoveAssignFromSameType(Value&& that) { | 566 void Value::InternalMoveAssignFromSameType(Value&& that) { |
567 CHECK_EQ(type_, that.type_); | 567 CHECK_EQ(type_, that.type_); |
568 | 568 |
569 switch (type_) { | 569 switch (type_) { |
570 case Type::NONE: | 570 case Type::NONE: |
571 case Type::BOOLEAN: | 571 case Type::BOOLEAN: |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1088 } | 1088 } |
1089 return nullptr; | 1089 return nullptr; |
1090 } | 1090 } |
1091 | 1091 |
1092 ListValue::ListValue() : Value(Type::LIST) {} | 1092 ListValue::ListValue() : Value(Type::LIST) {} |
1093 | 1093 |
1094 void ListValue::Clear() { | 1094 void ListValue::Clear() { |
1095 list_->clear(); | 1095 list_->clear(); |
1096 } | 1096 } |
1097 | 1097 |
1098 void ListValue::Reserve(size_t n) { | |
1099 list_->reserve(n); | |
1100 } | |
1101 | |
1098 bool ListValue::Set(size_t index, Value* in_value) { | 1102 bool ListValue::Set(size_t index, Value* in_value) { |
1099 return Set(index, WrapUnique(in_value)); | 1103 return Set(index, WrapUnique(in_value)); |
1100 } | 1104 } |
1101 | 1105 |
1102 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { | 1106 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { |
1103 if (!in_value) | 1107 if (!in_value) |
1104 return false; | 1108 return false; |
1105 | 1109 |
1106 if (index >= list_->size()) { | 1110 if (index >= list_->size()) { |
1107 // Pad out any intermediate indexes with null settings | 1111 // Pad out any intermediate indexes with null settings |
1108 while (index > list_->size()) | 1112 while (index > list_->size()) |
1109 Append(CreateNullValue()); | 1113 Append(CreateNullValue()); |
1110 Append(std::move(in_value)); | 1114 Append(std::move(in_value)); |
1111 } else { | 1115 } else { |
1112 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed? | 1116 (*list_)[index] = std::move(*in_value); |
1113 DCHECK((*list_)[index] != in_value); | |
1114 (*list_)[index] = std::move(in_value); | |
1115 } | 1117 } |
1116 return true; | 1118 return true; |
1117 } | 1119 } |
1118 | 1120 |
1119 bool ListValue::Get(size_t index, const Value** out_value) const { | 1121 bool ListValue::Get(size_t index, const Value** out_value) const { |
1120 if (index >= list_->size()) | 1122 if (index >= list_->size()) |
1121 return false; | 1123 return false; |
1122 | 1124 |
1123 if (out_value) | 1125 if (out_value) |
1124 *out_value = (*list_)[index].get(); | 1126 *out_value = &(*list_)[index]; |
1125 | 1127 |
1126 return true; | 1128 return true; |
1127 } | 1129 } |
1128 | 1130 |
1129 bool ListValue::Get(size_t index, Value** out_value) { | 1131 bool ListValue::Get(size_t index, Value** out_value) { |
1130 return static_cast<const ListValue&>(*this).Get( | 1132 return static_cast<const ListValue&>(*this).Get( |
1131 index, | 1133 index, |
1132 const_cast<const Value**>(out_value)); | 1134 const_cast<const Value**>(out_value)); |
1133 } | 1135 } |
1134 | 1136 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1225 return static_cast<const ListValue&>(*this).GetList( | 1227 return static_cast<const ListValue&>(*this).GetList( |
1226 index, | 1228 index, |
1227 const_cast<const ListValue**>(out_value)); | 1229 const_cast<const ListValue**>(out_value)); |
1228 } | 1230 } |
1229 | 1231 |
1230 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) { |
1231 if (index >= list_->size()) | 1233 if (index >= list_->size()) |
1232 return false; | 1234 return false; |
1233 | 1235 |
1234 if (out_value) | 1236 if (out_value) |
1235 *out_value = std::move((*list_)[index]); | 1237 *out_value = MakeUnique<Value>(std::move((*list_)[index])); |
1236 | 1238 |
1237 list_->erase(list_->begin() + index); | 1239 list_->erase(list_->begin() + index); |
1238 return true; | 1240 return true; |
1239 } | 1241 } |
1240 | 1242 |
1241 bool ListValue::Remove(const Value& value, size_t* index) { | 1243 bool ListValue::Remove(const Value& value, size_t* index) { |
1242 for (auto it = list_->begin(); it != list_->end(); ++it) { | 1244 auto it = std::find_if( |
1243 if ((*it)->Equals(&value)) { | 1245 list_->begin(), list_->end(), |
1244 size_t previous_index = it - list_->begin(); | 1246 [&value](const Value& entry) { return entry.Equals(&value); }); |
1245 list_->erase(it); | |
1246 | 1247 |
1247 if (index) | 1248 if (it == list_->end()) |
1248 *index = previous_index; | 1249 return false; |
1249 return true; | 1250 |
1250 } | 1251 if (index) |
1251 } | 1252 *index = std::distance(list_->begin(), it); |
1252 return false; | 1253 |
1254 list_->erase(it); | |
1255 return true; | |
1253 } | 1256 } |
1254 | 1257 |
1255 ListValue::iterator ListValue::Erase(iterator iter, | 1258 ListValue::iterator ListValue::Erase(iterator iter, |
1256 std::unique_ptr<Value>* out_value) { | 1259 std::unique_ptr<Value>* out_value) { |
1257 if (out_value) | 1260 if (out_value) |
1258 *out_value = std::move(*ListStorage::iterator(iter)); | 1261 *out_value = MakeUnique<Value>(std::move(*iter)); |
1259 | 1262 |
1260 return list_->erase(iter); | 1263 return list_->erase(iter); |
1261 } | 1264 } |
1262 | 1265 |
1263 void ListValue::Append(std::unique_ptr<Value> in_value) { | 1266 void ListValue::Append(std::unique_ptr<Value> in_value) { |
1264 list_->push_back(std::move(in_value)); | 1267 list_->push_back(std::move(*in_value)); |
1265 } | 1268 } |
1266 | 1269 |
1267 #if !defined(OS_LINUX) | 1270 #if !defined(OS_LINUX) |
1268 void ListValue::Append(Value* in_value) { | 1271 void ListValue::Append(Value* in_value) { |
1269 DCHECK(in_value); | 1272 DCHECK(in_value); |
1270 Append(WrapUnique(in_value)); | 1273 Append(WrapUnique(in_value)); |
1271 } | 1274 } |
1272 #endif | 1275 #endif |
1273 | 1276 |
1274 void ListValue::AppendBoolean(bool in_value) { | 1277 void ListValue::AppendBoolean(bool in_value) { |
(...skipping 26 matching lines...) Expand all Loading... | |
1301 void ListValue::AppendStrings(const std::vector<string16>& in_values) { | 1304 void ListValue::AppendStrings(const std::vector<string16>& in_values) { |
1302 for (std::vector<string16>::const_iterator it = in_values.begin(); | 1305 for (std::vector<string16>::const_iterator it = in_values.begin(); |
1303 it != in_values.end(); ++it) { | 1306 it != in_values.end(); ++it) { |
1304 AppendString(*it); | 1307 AppendString(*it); |
1305 } | 1308 } |
1306 } | 1309 } |
1307 | 1310 |
1308 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { | 1311 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { |
1309 DCHECK(in_value); | 1312 DCHECK(in_value); |
1310 for (const auto& entry : *list_) { | 1313 for (const auto& entry : *list_) { |
1311 if (entry->Equals(in_value.get())) { | 1314 if (entry.Equals(in_value.get())) { |
1312 return false; | 1315 return false; |
1313 } | 1316 } |
1314 } | 1317 } |
1315 list_->push_back(std::move(in_value)); | 1318 list_->push_back(std::move(*in_value)); |
1316 return true; | 1319 return true; |
1317 } | 1320 } |
1318 | 1321 |
1319 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { | 1322 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { |
1320 DCHECK(in_value); | 1323 DCHECK(in_value); |
1321 if (index > list_->size()) | 1324 if (index > list_->size()) |
1322 return false; | 1325 return false; |
1323 | 1326 |
1324 list_->insert(list_->begin() + index, std::move(in_value)); | 1327 list_->insert(list_->begin() + index, std::move(*in_value)); |
1325 return true; | 1328 return true; |
1326 } | 1329 } |
1327 | 1330 |
1328 ListValue::const_iterator ListValue::Find(const Value& value) const { | 1331 ListValue::const_iterator ListValue::Find(const Value& value) const { |
1329 return std::find_if(list_->begin(), list_->end(), | 1332 return std::find_if( |
1330 [&value](const std::unique_ptr<Value>& entry) { | 1333 list_->begin(), list_->end(), |
1331 return entry->Equals(&value); | 1334 [&value](const Value& entry) { return entry.Equals(&value); }); |
1332 }); | |
1333 } | 1335 } |
1334 | 1336 |
1335 void ListValue::Swap(ListValue* other) { | 1337 void ListValue::Swap(ListValue* other) { |
1336 CHECK(other->is_list()); | 1338 CHECK(other->is_list()); |
1337 list_->swap(*(other->list_)); | 1339 list_->swap(*(other->list_)); |
1338 } | 1340 } |
1339 | 1341 |
1340 ListValue* ListValue::DeepCopy() const { | 1342 ListValue* ListValue::DeepCopy() const { |
1341 return static_cast<ListValue*>(Value::DeepCopy()); | 1343 return static_cast<ListValue*>(Value::DeepCopy()); |
1342 } | 1344 } |
(...skipping 15 matching lines...) Expand all Loading... | |
1358 } | 1360 } |
1359 | 1361 |
1360 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1362 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
1361 if (static_cast<int>(type) < 0 || | 1363 if (static_cast<int>(type) < 0 || |
1362 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1364 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
1363 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1365 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
1364 return out << Value::GetTypeName(type); | 1366 return out << Value::GetTypeName(type); |
1365 } | 1367 } |
1366 | 1368 |
1367 } // namespace base | 1369 } // namespace base |
OLD | NEW |