| 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 for (const auto& current_entry : **dict_ptr_) { | 368 for (const auto& current_entry : **dict_ptr_) { |
| 369 result->SetWithoutPathExpansion(current_entry.first, | 369 result->SetWithoutPathExpansion(current_entry.first, |
| 370 current_entry.second->CreateDeepCopy()); | 370 current_entry.second->CreateDeepCopy()); |
| 371 } | 371 } |
| 372 | 372 |
| 373 return result; | 373 return result; |
| 374 } | 374 } |
| 375 | 375 |
| 376 case Type::LIST: { | 376 case Type::LIST: { |
| 377 ListValue* result = new ListValue; | 377 ListValue* result = new ListValue; |
| 378 | 378 *result->list_ = *list_; |
| 379 for (const auto& entry : *list_) | |
| 380 result->Append(entry->CreateDeepCopy()); | |
| 381 | |
| 382 return result; | 379 return result; |
| 383 } | 380 } |
| 384 | 381 |
| 385 default: | 382 default: |
| 386 NOTREACHED(); | 383 NOTREACHED(); |
| 387 return nullptr; | 384 return nullptr; |
| 388 } | 385 } |
| 389 } | 386 } |
| 390 | 387 |
| 391 std::unique_ptr<Value> Value::CreateDeepCopy() const { | 388 std::unique_ptr<Value> Value::CreateDeepCopy() const { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 422 if (lhs.first != rhs.first) | 419 if (lhs.first != rhs.first) |
| 423 return false; | 420 return false; |
| 424 | 421 |
| 425 return lhs.second->Equals(rhs.second.get()); | 422 return lhs.second->Equals(rhs.second.get()); |
| 426 }); | 423 }); |
| 427 } | 424 } |
| 428 case Type::LIST: { | 425 case Type::LIST: { |
| 429 if (list_->size() != other->list_->size()) | 426 if (list_->size() != other->list_->size()) |
| 430 return false; | 427 return false; |
| 431 | 428 |
| 432 return std::equal(std::begin(*list_), std::end(*list_), | 429 return std::equal( |
| 433 std::begin(*(other->list_)), | 430 std::begin(*list_), std::end(*list_), std::begin(*(other->list_)), |
| 434 [](const ListStorage::value_type& lhs, | 431 [](const ListStorage::value_type& lhs, |
| 435 const ListStorage::value_type& rhs) { | 432 const ListStorage::value_type& rhs) { return lhs.Equals(&rhs); }); |
| 436 return lhs->Equals(rhs.get()); | |
| 437 }); | |
| 438 } | 433 } |
| 439 } | 434 } |
| 440 | 435 |
| 441 NOTREACHED(); | 436 NOTREACHED(); |
| 442 return false; | 437 return false; |
| 443 } | 438 } |
| 444 | 439 |
| 445 // static | 440 // static |
| 446 bool Value::Equals(const Value* a, const Value* b) { | 441 bool Value::Equals(const Value* a, const Value* b) { |
| 447 if ((a == NULL) && (b == NULL)) return true; | 442 if ((a == NULL) && (b == NULL)) return true; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 case Type::DOUBLE: | 475 case Type::DOUBLE: |
| 481 InternalCopyFundamentalValue(that); | 476 InternalCopyFundamentalValue(that); |
| 482 return; | 477 return; |
| 483 | 478 |
| 484 case Type::STRING: | 479 case Type::STRING: |
| 485 string_value_.Init(*that.string_value_); | 480 string_value_.Init(*that.string_value_); |
| 486 return; | 481 return; |
| 487 case Type::BINARY: | 482 case Type::BINARY: |
| 488 binary_value_.Init(*that.binary_value_); | 483 binary_value_.Init(*that.binary_value_); |
| 489 return; | 484 return; |
| 490 // DictStorage and ListStorage are move-only types due to the presence of | 485 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
| 491 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 486 // is why the call to |CreateDeepCopy| is necessary here. |
| 492 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 487 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
| 493 // can be copied directly. | 488 // directly. |
| 494 case Type::DICTIONARY: | 489 case Type::DICTIONARY: { |
| 495 dict_ptr_.Init(std::move(*that.CreateDeepCopy()->dict_ptr_)); | 490 auto deep_copy = that.CreateDeepCopy(); |
| 491 dict_ptr_.Init(std::move(*deep_copy->dict_ptr_)); |
| 496 return; | 492 return; |
| 493 } |
| 497 case Type::LIST: | 494 case Type::LIST: |
| 498 list_.Init(std::move(*that.CreateDeepCopy()->list_)); | 495 list_.Init(*that.list_); |
| 499 return; | 496 return; |
| 500 } | 497 } |
| 501 } | 498 } |
| 502 | 499 |
| 503 void Value::InternalMoveConstructFrom(Value&& that) { | 500 void Value::InternalMoveConstructFrom(Value&& that) { |
| 504 type_ = that.type_; | 501 type_ = that.type_; |
| 505 | 502 |
| 506 switch (type_) { | 503 switch (type_) { |
| 507 case Type::NONE: | 504 case Type::NONE: |
| 508 case Type::BOOLEAN: | 505 case Type::BOOLEAN: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 538 case Type::DOUBLE: | 535 case Type::DOUBLE: |
| 539 InternalCopyFundamentalValue(that); | 536 InternalCopyFundamentalValue(that); |
| 540 return; | 537 return; |
| 541 | 538 |
| 542 case Type::STRING: | 539 case Type::STRING: |
| 543 *string_value_ = *that.string_value_; | 540 *string_value_ = *that.string_value_; |
| 544 return; | 541 return; |
| 545 case Type::BINARY: | 542 case Type::BINARY: |
| 546 *binary_value_ = *that.binary_value_; | 543 *binary_value_ = *that.binary_value_; |
| 547 return; | 544 return; |
| 548 // DictStorage and ListStorage are move-only types due to the presence of | 545 // DictStorage is a move-only type due to the presence of unique_ptrs. This |
| 549 // unique_ptrs. This is why the call to |CreateDeepCopy| is necessary here. | 546 // is why the call to |CreateDeepCopy| is necessary here. |
| 550 // TODO(crbug.com/646113): Clean this up when DictStorage and ListStorage | 547 // TODO(crbug.com/646113): Clean this up when DictStorage can be copied |
| 551 // can be copied directly. | 548 // directly. |
| 552 case Type::DICTIONARY: | 549 case Type::DICTIONARY: { |
| 553 *dict_ptr_ = std::move(*that.CreateDeepCopy()->dict_ptr_); | 550 auto deep_copy = that.CreateDeepCopy(); |
| 551 *dict_ptr_ = std::move(*deep_copy->dict_ptr_); |
| 554 return; | 552 return; |
| 553 } |
| 555 case Type::LIST: | 554 case Type::LIST: |
| 556 *list_ = std::move(*that.CreateDeepCopy()->list_); | 555 *list_ = *that.list_; |
| 557 return; | 556 return; |
| 558 } | 557 } |
| 559 } | 558 } |
| 560 | 559 |
| 561 void Value::InternalCleanup() { | 560 void Value::InternalCleanup() { |
| 562 switch (type_) { | 561 switch (type_) { |
| 563 case Type::NONE: | 562 case Type::NONE: |
| 564 case Type::BOOLEAN: | 563 case Type::BOOLEAN: |
| 565 case Type::INTEGER: | 564 case Type::INTEGER: |
| 566 case Type::DOUBLE: | 565 case Type::DOUBLE: |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 } | 1054 } |
| 1056 return nullptr; | 1055 return nullptr; |
| 1057 } | 1056 } |
| 1058 | 1057 |
| 1059 ListValue::ListValue() : Value(Type::LIST) {} | 1058 ListValue::ListValue() : Value(Type::LIST) {} |
| 1060 | 1059 |
| 1061 void ListValue::Clear() { | 1060 void ListValue::Clear() { |
| 1062 list_->clear(); | 1061 list_->clear(); |
| 1063 } | 1062 } |
| 1064 | 1063 |
| 1064 void ListValue::Reserve(size_t n) { |
| 1065 list_->reserve(n); |
| 1066 } |
| 1067 |
| 1065 bool ListValue::Set(size_t index, Value* in_value) { | 1068 bool ListValue::Set(size_t index, Value* in_value) { |
| 1066 return Set(index, WrapUnique(in_value)); | 1069 return Set(index, WrapUnique(in_value)); |
| 1067 } | 1070 } |
| 1068 | 1071 |
| 1069 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { | 1072 bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { |
| 1070 if (!in_value) | 1073 if (!in_value) |
| 1071 return false; | 1074 return false; |
| 1072 | 1075 |
| 1073 if (index >= list_->size()) { | 1076 if (index >= list_->size()) { |
| 1074 // Pad out any intermediate indexes with null settings | 1077 // Pad out any intermediate indexes with null settings |
| 1075 while (index > list_->size()) | 1078 while (index > list_->size()) |
| 1076 Append(CreateNullValue()); | 1079 Append(CreateNullValue()); |
| 1077 Append(std::move(in_value)); | 1080 Append(std::move(in_value)); |
| 1078 } else { | 1081 } else { |
| 1079 // TODO(dcheng): remove this DCHECK once the raw pointer version is removed? | 1082 (*list_)[index] = std::move(*in_value); |
| 1080 DCHECK((*list_)[index] != in_value); | |
| 1081 (*list_)[index] = std::move(in_value); | |
| 1082 } | 1083 } |
| 1083 return true; | 1084 return true; |
| 1084 } | 1085 } |
| 1085 | 1086 |
| 1086 bool ListValue::Get(size_t index, const Value** out_value) const { | 1087 bool ListValue::Get(size_t index, const Value** out_value) const { |
| 1087 if (index >= list_->size()) | 1088 if (index >= list_->size()) |
| 1088 return false; | 1089 return false; |
| 1089 | 1090 |
| 1090 if (out_value) | 1091 if (out_value) |
| 1091 *out_value = (*list_)[index].get(); | 1092 *out_value = &(*list_)[index]; |
| 1092 | 1093 |
| 1093 return true; | 1094 return true; |
| 1094 } | 1095 } |
| 1095 | 1096 |
| 1096 bool ListValue::Get(size_t index, Value** out_value) { | 1097 bool ListValue::Get(size_t index, Value** out_value) { |
| 1097 return static_cast<const ListValue&>(*this).Get( | 1098 return static_cast<const ListValue&>(*this).Get( |
| 1098 index, | 1099 index, |
| 1099 const_cast<const Value**>(out_value)); | 1100 const_cast<const Value**>(out_value)); |
| 1100 } | 1101 } |
| 1101 | 1102 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 return static_cast<const ListValue&>(*this).GetList( | 1193 return static_cast<const ListValue&>(*this).GetList( |
| 1193 index, | 1194 index, |
| 1194 const_cast<const ListValue**>(out_value)); | 1195 const_cast<const ListValue**>(out_value)); |
| 1195 } | 1196 } |
| 1196 | 1197 |
| 1197 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { | 1198 bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { |
| 1198 if (index >= list_->size()) | 1199 if (index >= list_->size()) |
| 1199 return false; | 1200 return false; |
| 1200 | 1201 |
| 1201 if (out_value) | 1202 if (out_value) |
| 1202 *out_value = std::move((*list_)[index]); | 1203 *out_value = MakeUnique<Value>(std::move((*list_)[index])); |
| 1203 | 1204 |
| 1204 list_->erase(list_->begin() + index); | 1205 list_->erase(list_->begin() + index); |
| 1205 return true; | 1206 return true; |
| 1206 } | 1207 } |
| 1207 | 1208 |
| 1208 bool ListValue::Remove(const Value& value, size_t* index) { | 1209 bool ListValue::Remove(const Value& value, size_t* index) { |
| 1209 for (auto it = list_->begin(); it != list_->end(); ++it) { | 1210 auto it = std::find_if( |
| 1210 if ((*it)->Equals(&value)) { | 1211 list_->begin(), list_->end(), |
| 1211 size_t previous_index = it - list_->begin(); | 1212 [&value](const Value& entry) { return entry.Equals(&value); }); |
| 1212 list_->erase(it); | |
| 1213 | 1213 |
| 1214 if (index) | 1214 if (it == list_->end()) |
| 1215 *index = previous_index; | 1215 return false; |
| 1216 return true; | 1216 |
| 1217 } | 1217 if (index) |
| 1218 } | 1218 *index = std::distance(list_->begin(), it); |
| 1219 return false; | 1219 |
| 1220 list_->erase(it); |
| 1221 return true; |
| 1220 } | 1222 } |
| 1221 | 1223 |
| 1222 ListValue::iterator ListValue::Erase(iterator iter, | 1224 ListValue::iterator ListValue::Erase(iterator iter, |
| 1223 std::unique_ptr<Value>* out_value) { | 1225 std::unique_ptr<Value>* out_value) { |
| 1224 if (out_value) | 1226 if (out_value) |
| 1225 *out_value = std::move(*ListStorage::iterator(iter)); | 1227 *out_value = MakeUnique<Value>(std::move(*iter)); |
| 1226 | 1228 |
| 1227 return list_->erase(iter); | 1229 return list_->erase(iter); |
| 1228 } | 1230 } |
| 1229 | 1231 |
| 1230 void ListValue::Append(std::unique_ptr<Value> in_value) { | 1232 void ListValue::Append(std::unique_ptr<Value> in_value) { |
| 1231 list_->push_back(std::move(in_value)); | 1233 list_->push_back(std::move(*in_value)); |
| 1232 } | 1234 } |
| 1233 | 1235 |
| 1234 #if !defined(OS_LINUX) | 1236 #if !defined(OS_LINUX) |
| 1235 void ListValue::Append(Value* in_value) { | 1237 void ListValue::Append(Value* in_value) { |
| 1236 DCHECK(in_value); | 1238 DCHECK(in_value); |
| 1237 Append(WrapUnique(in_value)); | 1239 Append(WrapUnique(in_value)); |
| 1238 } | 1240 } |
| 1239 #endif | 1241 #endif |
| 1240 | 1242 |
| 1241 void ListValue::AppendBoolean(bool in_value) { | 1243 void ListValue::AppendBoolean(bool in_value) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1268 void ListValue::AppendStrings(const std::vector<string16>& in_values) { | 1270 void ListValue::AppendStrings(const std::vector<string16>& in_values) { |
| 1269 for (std::vector<string16>::const_iterator it = in_values.begin(); | 1271 for (std::vector<string16>::const_iterator it = in_values.begin(); |
| 1270 it != in_values.end(); ++it) { | 1272 it != in_values.end(); ++it) { |
| 1271 AppendString(*it); | 1273 AppendString(*it); |
| 1272 } | 1274 } |
| 1273 } | 1275 } |
| 1274 | 1276 |
| 1275 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { | 1277 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { |
| 1276 DCHECK(in_value); | 1278 DCHECK(in_value); |
| 1277 for (const auto& entry : *list_) { | 1279 for (const auto& entry : *list_) { |
| 1278 if (entry->Equals(in_value.get())) { | 1280 if (entry.Equals(in_value.get())) { |
| 1279 return false; | 1281 return false; |
| 1280 } | 1282 } |
| 1281 } | 1283 } |
| 1282 list_->push_back(std::move(in_value)); | 1284 list_->push_back(std::move(*in_value)); |
| 1283 return true; | 1285 return true; |
| 1284 } | 1286 } |
| 1285 | 1287 |
| 1286 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { | 1288 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { |
| 1287 DCHECK(in_value); | 1289 DCHECK(in_value); |
| 1288 if (index > list_->size()) | 1290 if (index > list_->size()) |
| 1289 return false; | 1291 return false; |
| 1290 | 1292 |
| 1291 list_->insert(list_->begin() + index, std::move(in_value)); | 1293 list_->insert(list_->begin() + index, std::move(*in_value)); |
| 1292 return true; | 1294 return true; |
| 1293 } | 1295 } |
| 1294 | 1296 |
| 1295 ListValue::const_iterator ListValue::Find(const Value& value) const { | 1297 ListValue::const_iterator ListValue::Find(const Value& value) const { |
| 1296 return std::find_if(list_->begin(), list_->end(), | 1298 return std::find_if( |
| 1297 [&value](const std::unique_ptr<Value>& entry) { | 1299 list_->begin(), list_->end(), |
| 1298 return entry->Equals(&value); | 1300 [&value](const Value& entry) { return entry.Equals(&value); }); |
| 1299 }); | |
| 1300 } | 1301 } |
| 1301 | 1302 |
| 1302 void ListValue::Swap(ListValue* other) { | 1303 void ListValue::Swap(ListValue* other) { |
| 1303 CHECK(other->is_list()); | 1304 CHECK(other->is_list()); |
| 1304 list_->swap(*(other->list_)); | 1305 list_->swap(*(other->list_)); |
| 1305 } | 1306 } |
| 1306 | 1307 |
| 1307 ListValue* ListValue::DeepCopy() const { | 1308 ListValue* ListValue::DeepCopy() const { |
| 1308 return static_cast<ListValue*>(Value::DeepCopy()); | 1309 return static_cast<ListValue*>(Value::DeepCopy()); |
| 1309 } | 1310 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1325 } | 1326 } |
| 1326 | 1327 |
| 1327 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { | 1328 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { |
| 1328 if (static_cast<int>(type) < 0 || | 1329 if (static_cast<int>(type) < 0 || |
| 1329 static_cast<size_t>(type) >= arraysize(kTypeNames)) | 1330 static_cast<size_t>(type) >= arraysize(kTypeNames)) |
| 1330 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; | 1331 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; |
| 1331 return out << Value::GetTypeName(type); | 1332 return out << Value::GetTypeName(type); |
| 1332 } | 1333 } |
| 1333 | 1334 |
| 1334 } // namespace base | 1335 } // namespace base |
| OLD | NEW |