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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 if ((*lhs.dict_ptr_)->size() != (*rhs.dict_ptr_)->size()) | 368 if ((*lhs.dict_ptr_)->size() != (*rhs.dict_ptr_)->size()) |
369 return false; | 369 return false; |
370 return std::equal(std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_), | 370 return std::equal(std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_), |
371 std::begin(**rhs.dict_ptr_), | 371 std::begin(**rhs.dict_ptr_), |
372 [](const Value::DictStorage::value_type& u, | 372 [](const Value::DictStorage::value_type& u, |
373 const Value::DictStorage::value_type& v) { | 373 const Value::DictStorage::value_type& v) { |
374 return std::tie(u.first, *u.second) == | 374 return std::tie(u.first, *u.second) == |
375 std::tie(v.first, *v.second); | 375 std::tie(v.first, *v.second); |
376 }); | 376 }); |
377 case Value::Type::LIST: | 377 case Value::Type::LIST: |
378 if (lhs.list_->size() != rhs.list_->size()) | 378 return *lhs.list_ == *rhs.list_; |
379 return false; | |
380 return std::equal( | |
381 std::begin(*lhs.list_), std::end(*lhs.list_), std::begin(*rhs.list_), | |
382 [](const Value::ListStorage::value_type& u, | |
383 const Value::ListStorage::value_type& v) { return *u == *v; }); | |
384 } | 379 } |
385 | 380 |
386 NOTREACHED(); | 381 NOTREACHED(); |
387 return false; | 382 return false; |
388 } | 383 } |
389 | 384 |
390 bool operator!=(const Value& lhs, const Value& rhs) { | 385 bool operator!=(const Value& lhs, const Value& rhs) { |
391 return !(lhs == rhs); | 386 return !(lhs == rhs); |
392 } | 387 } |
393 | 388 |
(...skipping 18 matching lines...) Expand all Loading... |
412 // are completely inlined. | 407 // are completely inlined. |
413 case Value::Type::DICTIONARY: | 408 case Value::Type::DICTIONARY: |
414 return std::lexicographical_compare( | 409 return std::lexicographical_compare( |
415 std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_), | 410 std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_), |
416 std::begin(**rhs.dict_ptr_), std::end(**rhs.dict_ptr_), | 411 std::begin(**rhs.dict_ptr_), std::end(**rhs.dict_ptr_), |
417 [](const Value::DictStorage::value_type& u, | 412 [](const Value::DictStorage::value_type& u, |
418 const Value::DictStorage::value_type& v) { | 413 const Value::DictStorage::value_type& v) { |
419 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second); | 414 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second); |
420 }); | 415 }); |
421 case Value::Type::LIST: | 416 case Value::Type::LIST: |
422 return std::lexicographical_compare( | 417 return *lhs.list_ < *rhs.list_; |
423 std::begin(*lhs.list_), std::end(*lhs.list_), std::begin(*rhs.list_), | |
424 std::end(*rhs.list_), | |
425 [](const Value::ListStorage::value_type& u, | |
426 const Value::ListStorage::value_type& v) { return *u < *v; }); | |
427 } | 418 } |
428 | 419 |
429 NOTREACHED(); | 420 NOTREACHED(); |
430 return false; | 421 return false; |
431 } | 422 } |
432 | 423 |
433 bool operator>(const Value& lhs, const Value& rhs) { | 424 bool operator>(const Value& lhs, const Value& rhs) { |
434 return rhs < lhs; | 425 return rhs < lhs; |
435 } | 426 } |
436 | 427 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 case Type::DOUBLE: | 478 case Type::DOUBLE: |
488 InternalCopyFundamentalValue(that); | 479 InternalCopyFundamentalValue(that); |
489 return; | 480 return; |
490 | 481 |
491 case Type::STRING: | 482 case Type::STRING: |
492 string_value_.Init(*that.string_value_); | 483 string_value_.Init(*that.string_value_); |
493 return; | 484 return; |
494 case Type::BINARY: | 485 case Type::BINARY: |
495 binary_value_.Init(*that.binary_value_); | 486 binary_value_.Init(*that.binary_value_); |
496 return; | 487 return; |
497 // DictStorage and ListStorage are move-only types due to the presence of | 488 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
498 // unique_ptrs. This is why the explicit copy of every element is necessary | 489 // is why the explicit copy of every element is necessary here. |
499 // here. | 490 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
500 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 491 // directly. |
501 // can be copied directly. | |
502 case Type::DICTIONARY: | 492 case Type::DICTIONARY: |
503 dict_ptr_.Init(MakeUnique<DictStorage>()); | 493 dict_ptr_.Init(MakeUnique<DictStorage>()); |
504 for (const auto& it : **that.dict_ptr_) { | 494 for (const auto& it : **that.dict_ptr_) { |
505 (*dict_ptr_) | 495 (*dict_ptr_) |
506 ->emplace_hint((*dict_ptr_)->end(), it.first, | 496 ->emplace_hint((*dict_ptr_)->end(), it.first, |
507 MakeUnique<Value>(*it.second)); | 497 MakeUnique<Value>(*it.second)); |
508 } | 498 } |
509 return; | 499 return; |
510 case Type::LIST: | 500 case Type::LIST: |
511 list_.Init(); | 501 list_.Init(*that.list_); |
512 list_->reserve(that.list_->size()); | |
513 for (const auto& it : *that.list_) | |
514 list_->push_back(MakeUnique<Value>(*it)); | |
515 return; | 502 return; |
516 } | 503 } |
517 } | 504 } |
518 | 505 |
519 void Value::InternalMoveConstructFrom(Value&& that) { | 506 void Value::InternalMoveConstructFrom(Value&& that) { |
520 type_ = that.type_; | 507 type_ = that.type_; |
521 | 508 |
522 switch (type_) { | 509 switch (type_) { |
523 case Type::NONE: | 510 case Type::NONE: |
524 case Type::BOOLEAN: | 511 case Type::BOOLEAN: |
(...skipping 29 matching lines...) Expand all Loading... |
554 case Type::DOUBLE: | 541 case Type::DOUBLE: |
555 InternalCopyFundamentalValue(that); | 542 InternalCopyFundamentalValue(that); |
556 return; | 543 return; |
557 | 544 |
558 case Type::STRING: | 545 case Type::STRING: |
559 *string_value_ = *that.string_value_; | 546 *string_value_ = *that.string_value_; |
560 return; | 547 return; |
561 case Type::BINARY: | 548 case Type::BINARY: |
562 *binary_value_ = *that.binary_value_; | 549 *binary_value_ = *that.binary_value_; |
563 return; | 550 return; |
564 // DictStorage and ListStorage are move-only types due to the presence of | 551 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
565 // unique_ptrs. This is why the explicit call to the copy constructor is | 552 // is why the explicit call to the copy constructor is necessary here. |
566 // necessary here. | 553 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
567 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 554 // directly. |
568 // can be copied directly. | 555 case Type::DICTIONARY: { |
569 case Type::DICTIONARY: | 556 Value copy = that; |
570 *dict_ptr_ = std::move(*Value(that).dict_ptr_); | 557 *dict_ptr_ = std::move(*copy.dict_ptr_); |
571 return; | 558 return; |
| 559 } |
572 case Type::LIST: | 560 case Type::LIST: |
573 *list_ = std::move(*Value(that).list_); | 561 *list_ = *that.list_; |
574 return; | 562 return; |
575 } | 563 } |
576 } | 564 } |
577 | 565 |
578 void Value::InternalCleanup() { | 566 void Value::InternalCleanup() { |
579 switch (type_) { | 567 switch (type_) { |
580 case Type::NONE: | 568 case Type::NONE: |
581 case Type::BOOLEAN: | 569 case Type::BOOLEAN: |
582 case Type::INTEGER: | 570 case Type::INTEGER: |
583 case Type::DOUBLE: | 571 case Type::DOUBLE: |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 } | 1058 } |
1071 return nullptr; | 1059 return nullptr; |
1072 } | 1060 } |
1073 | 1061 |
1074 ListValue::ListValue() : Value(Type::LIST) {} | 1062 ListValue::ListValue() : Value(Type::LIST) {} |
1075 | 1063 |
1076 void ListValue::Clear() { | 1064 void ListValue::Clear() { |
1077 list_->clear(); | 1065 list_->clear(); |
1078 } | 1066 } |
1079 | 1067 |
| 1068 void ListValue::Reserve(size_t n) { |
| 1069 list_->reserve(n); |
| 1070 } |
| 1071 |
1080 bool ListValue::Set(size_t index, Value* in_value) { | 1072 bool ListValue::Set(size_t index, Value* in_value) { |
1081 return Set(index, WrapUnique(in_value)); | 1073 return Set(index, WrapUnique(in_value)); |
1082 } | 1074 } |
1083 | 1075 |
1084 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { | 1076 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { |
1085 if (!in_value) | 1077 if (!in_value) |
1086 return false; | 1078 return false; |
1087 | 1079 |
1088 if (index >= list_->size()) { | 1080 if (index >= list_->size()) { |
1089 // Pad out any intermediate indexes with null settings | 1081 // Pad out any intermediate indexes with null settings |
1090 while (index > list_->size()) | 1082 while (index > list_->size()) |
1091 Append(MakeUnique<Value>()); | 1083 Append(MakeUnique<Value>()); |
1092 Append(std::move(in_value)); | 1084 Append(std::move(in_value)); |
1093 } else { | 1085 } else { |
1094 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed? | 1086 (*list_)[index] = std::move(*in_value); |
1095 DCHECK((*list_)[index] != in_value); | |
1096 (*list_)[index] = std::move(in_value); | |
1097 } | 1087 } |
1098 return true; | 1088 return true; |
1099 } | 1089 } |
1100 | 1090 |
1101 bool ListValue::Get(size_t index, const Value** out_value) const { | 1091 bool ListValue::Get(size_t index, const Value** out_value) const { |
1102 if (index >= list_->size()) | 1092 if (index >= list_->size()) |
1103 return false; | 1093 return false; |
1104 | 1094 |
1105 if (out_value) | 1095 if (out_value) |
1106 *out_value = (*list_)[index].get(); | 1096 *out_value = &(*list_)[index]; |
1107 | 1097 |
1108 return true; | 1098 return true; |
1109 } | 1099 } |
1110 | 1100 |
1111 bool ListValue::Get(size_t index, Value** out_value) { | 1101 bool ListValue::Get(size_t index, Value** out_value) { |
1112 return static_cast<const ListValue&>(*this).Get( | 1102 return static_cast<const ListValue&>(*this).Get( |
1113 index, | 1103 index, |
1114 const_cast<const Value**>(out_value)); | 1104 const_cast<const Value**>(out_value)); |
1115 } | 1105 } |
1116 | 1106 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1206 return static_cast<const ListValue&>(*this).GetList( | 1196 return static_cast<const ListValue&>(*this).GetList( |
1207 index, | 1197 index, |
1208 const_cast<const ListValue**>(out_value)); | 1198 const_cast<const ListValue**>(out_value)); |
1209 } | 1199 } |
1210 | 1200 |
1211 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { | 1201 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { |
1212 if (index >= list_->size()) | 1202 if (index >= list_->size()) |
1213 return false; | 1203 return false; |
1214 | 1204 |
1215 if (out_value) | 1205 if (out_value) |
1216 *out_value = std::move((*list_)[index]); | 1206 *out_value = MakeUnique<Value>(std::move((*list_)[index])); |
1217 | 1207 |
1218 list_->erase(list_->begin() + index); | 1208 list_->erase(list_->begin() + index); |
1219 return true; | 1209 return true; |
1220 } | 1210 } |
1221 | 1211 |
1222 bool ListValue::Remove(const Value& value, size_t* index) { | 1212 bool ListValue::Remove(const Value& value, size_t* index) { |
1223 for (auto it = list_->begin(); it != list_->end(); ++it) { | 1213 auto it = std::find(list_->begin(), list_->end(), value); |
1224 if (**it == value) { | |
1225 size_t previous_index = it - list_->begin(); | |
1226 list_->erase(it); | |
1227 | 1214 |
1228 if (index) | 1215 if (it == list_->end()) |
1229 *index = previous_index; | 1216 return false; |
1230 return true; | 1217 |
1231 } | 1218 if (index) |
1232 } | 1219 *index = std::distance(list_->begin(), it); |
1233 return false; | 1220 |
| 1221 list_->erase(it); |
| 1222 return true; |
1234 } | 1223 } |
1235 | 1224 |
1236 ListValue::iterator ListValue::Erase(iterator iter, | 1225 ListValue::iterator ListValue::Erase(iterator iter, |
1237 std::unique_ptr<Value>* out_value) { | 1226 std::unique_ptr<Value>* out_value) { |
1238 if (out_value) | 1227 if (out_value) |
1239 *out_value = std::move(*ListStorage::iterator(iter)); | 1228 *out_value = MakeUnique<Value>(std::move(*iter)); |
1240 | 1229 |
1241 return list_->erase(iter); | 1230 return list_->erase(iter); |
1242 } | 1231 } |
1243 | 1232 |
1244 void ListValue::Append(std::unique_ptr<Value> in_value) { | 1233 void ListValue::Append(std::unique_ptr<Value> in_value) { |
1245 list_->push_back(std::move(in_value)); | 1234 list_->push_back(std::move(*in_value)); |
1246 } | 1235 } |
1247 | 1236 |
1248 #if !defined(OS_LINUX) | 1237 #if !defined(OS_LINUX) |
1249 void ListValue::Append(Value* in_value) { | 1238 void ListValue::Append(Value* in_value) { |
1250 DCHECK(in_value); | 1239 DCHECK(in_value); |
1251 Append(WrapUnique(in_value)); | 1240 Append(WrapUnique(in_value)); |
1252 } | 1241 } |
1253 #endif | 1242 #endif |
1254 | 1243 |
1255 void ListValue::AppendBoolean(bool in_value) { | 1244 void ListValue::AppendBoolean(bool in_value) { |
(...skipping 25 matching lines...) Expand all Loading... |
1281 | 1270 |
1282 void ListValue::AppendStrings(const std::vector<string16>& in_values) { | 1271 void ListValue::AppendStrings(const std::vector<string16>& in_values) { |
1283 for (std::vector<string16>::const_iterator it = in_values.begin(); | 1272 for (std::vector<string16>::const_iterator it = in_values.begin(); |
1284 it != in_values.end(); ++it) { | 1273 it != in_values.end(); ++it) { |
1285 AppendString(*it); | 1274 AppendString(*it); |
1286 } | 1275 } |
1287 } | 1276 } |
1288 | 1277 |
1289 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { | 1278 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { |
1290 DCHECK(in_value); | 1279 DCHECK(in_value); |
1291 for (const auto& entry : *list_) { | 1280 if (std::find(list_->begin(), list_->end(), *in_value) != list_->end()) |
1292 if (*entry == *in_value) | 1281 return false; |
1293 return false; | 1282 |
1294 } | 1283 list_->push_back(std::move(*in_value)); |
1295 list_->push_back(std::move(in_value)); | |
1296 return true; | 1284 return true; |
1297 } | 1285 } |
1298 | 1286 |
1299 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { | 1287 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { |
1300 DCHECK(in_value); | 1288 DCHECK(in_value); |
1301 if (index > list_->size()) | 1289 if (index > list_->size()) |
1302 return false; | 1290 return false; |
1303 | 1291 |
1304 list_->insert(list_->begin() + index, std::move(in_value)); | 1292 list_->insert(list_->begin() + index, std::move(*in_value)); |
1305 return true; | 1293 return true; |
1306 } | 1294 } |
1307 | 1295 |
1308 ListValue::const_iterator ListValue::Find(const Value& value) const { | 1296 ListValue::const_iterator ListValue::Find(const Value& value) const { |
1309 return std::find_if(list_->begin(), list_->end(), | 1297 return std::find(list_->begin(), list_->end(), value); |
1310 [&value](const std::unique_ptr<Value>& entry) { | |
1311 return *entry == value; | |
1312 }); | |
1313 } | 1298 } |
1314 | 1299 |
1315 void ListValue::Swap(ListValue* other) { | 1300 void ListValue::Swap(ListValue* other) { |
1316 CHECK(other->is_list()); | 1301 CHECK(other->is_list()); |
1317 list_->swap(*(other->list_)); | 1302 list_->swap(*(other->list_)); |
1318 } | 1303 } |
1319 | 1304 |
1320 ListValue* ListValue::DeepCopy() const { | 1305 ListValue* ListValue::DeepCopy() const { |
1321 return new ListValue(*this); | 1306 return new ListValue(*this); |
1322 } | 1307 } |
(...skipping 15 matching lines...) Expand all Loading... |
1338 } | 1323 } |
1339 | 1324 |
1340 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1325 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
1341 if (static_cast<int>(type) < 0 || | 1326 if (static_cast<int>(type) < 0 || |
1342 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1327 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
1343 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1328 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
1344 return out << Value::GetTypeName(type); | 1329 return out << Value::GetTypeName(type); |
1345 } | 1330 } |
1346 | 1331 |
1347 } // namespace base | 1332 } // namespace base |
OLD | NEW |