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