| 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 |