Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(22)

Side by Side Diff: base/values.cc

Issue 2771923005: Implement comparison operators for base::Value (Closed)
Patch Set: Declare Operators out of line and update tests Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 default: 385 default:
386 NOTREACHED(); 386 NOTREACHED();
387 return nullptr; 387 return nullptr;
388 } 388 }
389 } 389 }
390 390
391 std::unique_ptr<Value> Value::CreateDeepCopy() const { 391 std::unique_ptr<Value> Value::CreateDeepCopy() const {
392 return WrapUnique(DeepCopy()); 392 return WrapUnique(DeepCopy());
393 } 393 }
394 394
395 bool Value::Equals(const Value* other) const { 395 bool operator==(const Value& lhs, const Value& rhs) {
396 if (other->type() != type()) 396 if (lhs.type_ != rhs.type_)
397 return false; 397 return false;
398 398
399 switch (type()) { 399 switch (lhs.type_) {
400 case Type::NONE: 400 case Value::Type::NONE:
401 return true; 401 return true;
402 case Type::BOOLEAN: 402 case Value::Type::BOOLEAN:
403 return bool_value_ == other->bool_value_; 403 return lhs.bool_value_ == rhs.bool_value_;
404 case Type::INTEGER: 404 case Value::Type::INTEGER:
405 return int_value_ == other->int_value_; 405 return lhs.int_value_ == rhs.int_value_;
406 case Type::DOUBLE: 406 case Value::Type::DOUBLE:
407 return double_value_ == other->double_value_; 407 return lhs.double_value_ == rhs.double_value_;
408 case Type::STRING: 408 case Value::Type::STRING:
409 return *string_value_ == *(other->string_value_); 409 return *lhs.string_value_ == *rhs.string_value_;
410 case Type::BINARY: 410 case Value::Type::BINARY:
411 return *binary_value_ == *(other->binary_value_); 411 return *lhs.binary_value_ == *rhs.binary_value_;
412 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue 412 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
413 // are completely inlined. 413 // are completely inlined.
414 case Type::DICTIONARY: { 414 case Value::Type::DICTIONARY:
415 if ((*dict_ptr_)->size() != (*other->dict_ptr_)->size()) 415 if ((*lhs.dict_ptr_)->size() != (*rhs.dict_ptr_)->size())
416 return false; 416 return false;
417 417 return std::equal(std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_),
418 return std::equal(std::begin(**dict_ptr_), std::end(**dict_ptr_), 418 std::begin(**rhs.dict_ptr_),
419 std::begin(**(other->dict_ptr_)), 419 [](const Value::DictStorage::value_type& u,
420 [](const DictStorage::value_type& lhs, 420 const Value::DictStorage::value_type& v) {
421 const DictStorage::value_type& rhs) { 421 return std::tie(u.first, *u.second) ==
422 if (lhs.first != rhs.first) 422 std::tie(v.first, *v.second);
423 return false;
424
425 return lhs.second->Equals(rhs.second.get());
426 }); 423 });
427 } 424 case Value::Type::LIST:
428 case Type::LIST: { 425 if (lhs.list_->size() != rhs.list_->size())
429 if (list_->size() != other->list_->size())
430 return false; 426 return false;
431 427 return std::equal(
432 return std::equal(std::begin(*list_), std::end(*list_), 428 std::begin(*lhs.list_), std::end(*lhs.list_), std::begin(*rhs.list_),
433 std::begin(*(other->list_)), 429 [](const Value::ListStorage::value_type& u,
434 [](const ListStorage::value_type& lhs, 430 const Value::ListStorage::value_type& v) { return *u == *v; });
435 const ListStorage::value_type& rhs) {
436 return lhs->Equals(rhs.get());
437 });
438 }
439 } 431 }
440 432
441 NOTREACHED(); 433 NOTREACHED();
442 return false; 434 return false;
443 } 435 }
444 436
437 bool operator!=(const Value& lhs, const Value& rhs) {
438 return !(lhs == rhs);
439 }
440
441 bool operator<(const Value& lhs, const Value& rhs) {
442 if (lhs.type_ != rhs.type_)
443 return lhs.type_ < rhs.type_;
444
445 switch (lhs.type_) {
446 case Value::Type::NONE:
447 return false;
448 case Value::Type::BOOLEAN:
449 return lhs.bool_value_ < rhs.bool_value_;
450 case Value::Type::INTEGER:
451 return lhs.int_value_ < rhs.int_value_;
452 case Value::Type::DOUBLE:
453 return lhs.double_value_ < rhs.double_value_;
454 case Value::Type::STRING:
455 return *lhs.string_value_ < *rhs.string_value_;
456 case Value::Type::BINARY:
457 return *lhs.binary_value_ < *rhs.binary_value_;
458 // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue
459 // are completely inlined.
460 case Value::Type::DICTIONARY:
461 return std::lexicographical_compare(
462 std::begin(**lhs.dict_ptr_), std::end(**lhs.dict_ptr_),
463 std::begin(**rhs.dict_ptr_), std::end(**rhs.dict_ptr_),
464 [](const Value::DictStorage::value_type& u,
465 const Value::DictStorage::value_type& v) {
466 return std::tie(u.first, *u.second) < std::tie(v.first, *v.second);
467 });
468 case Value::Type::LIST:
469 return std::lexicographical_compare(
470 std::begin(*lhs.list_), std::end(*lhs.list_), std::begin(*rhs.list_),
471 std::end(*rhs.list_),
472 [](const Value::ListStorage::value_type& u,
473 const Value::ListStorage::value_type& v) { return *u < *v; });
474 }
475
476 NOTREACHED();
477 return false;
478 }
479
480 bool operator>(const Value& lhs, const Value& rhs) {
481 return rhs < lhs;
482 }
483
484 bool operator<=(const Value& lhs, const Value& rhs) {
485 return !(rhs < lhs);
486 }
487
488 bool operator>=(const Value& lhs, const Value& rhs) {
489 return !(lhs < rhs);
490 }
491
492 bool Value::Equals(const Value* other) const {
493 DCHECK(other);
494 return *this == *other;
495 }
496
445 // static 497 // static
446 bool Value::Equals(const Value* a, const Value* b) { 498 bool Value::Equals(const Value* a, const Value* b) {
447 if ((a == NULL) && (b == NULL)) return true; 499 if ((a == NULL) && (b == NULL))
448 if ((a == NULL) ^ (b == NULL)) return false; 500 return true;
449 return a->Equals(b); 501 if ((a == NULL) ^ (b == NULL))
502 return false;
503 return *a == *b;
450 } 504 }
451 505
452 void Value::InternalCopyFundamentalValue(const Value& that) { 506 void Value::InternalCopyFundamentalValue(const Value& that) {
453 switch (type_) { 507 switch (type_) {
454 case Type::NONE: 508 case Type::NONE:
455 // Nothing to do. 509 // Nothing to do.
456 return; 510 return;
457 511
458 case Type::BOOLEAN: 512 case Type::BOOLEAN:
459 bool_value_ = that.bool_value_; 513 bool_value_ = that.bool_value_;
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 1254
1201 if (out_value) 1255 if (out_value)
1202 *out_value = std::move((*list_)[index]); 1256 *out_value = std::move((*list_)[index]);
1203 1257
1204 list_->erase(list_->begin() + index); 1258 list_->erase(list_->begin() + index);
1205 return true; 1259 return true;
1206 } 1260 }
1207 1261
1208 bool ListValue::Remove(const Value& value, size_t* index) { 1262 bool ListValue::Remove(const Value& value, size_t* index) {
1209 for (auto it = list_->begin(); it != list_->end(); ++it) { 1263 for (auto it = list_->begin(); it != list_->end(); ++it) {
1210 if ((*it)->Equals(&value)) { 1264 if (**it == value) {
1211 size_t previous_index = it - list_->begin(); 1265 size_t previous_index = it - list_->begin();
1212 list_->erase(it); 1266 list_->erase(it);
1213 1267
1214 if (index) 1268 if (index)
1215 *index = previous_index; 1269 *index = previous_index;
1216 return true; 1270 return true;
1217 } 1271 }
1218 } 1272 }
1219 return false; 1273 return false;
1220 } 1274 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 void ListValue::AppendStrings(const std::vector<string16>& in_values) { 1322 void ListValue::AppendStrings(const std::vector<string16>& in_values) {
1269 for (std::vector<string16>::const_iterator it = in_values.begin(); 1323 for (std::vector<string16>::const_iterator it = in_values.begin();
1270 it != in_values.end(); ++it) { 1324 it != in_values.end(); ++it) {
1271 AppendString(*it); 1325 AppendString(*it);
1272 } 1326 }
1273 } 1327 }
1274 1328
1275 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { 1329 bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) {
1276 DCHECK(in_value); 1330 DCHECK(in_value);
1277 for (const auto& entry : *list_) { 1331 for (const auto& entry : *list_) {
1278 if (entry->Equals(in_value.get())) { 1332 if (*entry == *in_value)
1279 return false; 1333 return false;
1280 }
1281 } 1334 }
1282 list_->push_back(std::move(in_value)); 1335 list_->push_back(std::move(in_value));
1283 return true; 1336 return true;
1284 } 1337 }
1285 1338
1286 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { 1339 bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) {
1287 DCHECK(in_value); 1340 DCHECK(in_value);
1288 if (index > list_->size()) 1341 if (index > list_->size())
1289 return false; 1342 return false;
1290 1343
1291 list_->insert(list_->begin() + index, std::move(in_value)); 1344 list_->insert(list_->begin() + index, std::move(in_value));
1292 return true; 1345 return true;
1293 } 1346 }
1294 1347
1295 ListValue::const_iterator ListValue::Find(const Value& value) const { 1348 ListValue::const_iterator ListValue::Find(const Value& value) const {
1296 return std::find_if(list_->begin(), list_->end(), 1349 return std::find_if(list_->begin(), list_->end(),
1297 [&value](const std::unique_ptr<Value>& entry) { 1350 [&value](const std::unique_ptr<Value>& entry) {
1298 return entry->Equals(&value); 1351 return *entry == value;
1299 }); 1352 });
1300 } 1353 }
1301 1354
1302 void ListValue::Swap(ListValue* other) { 1355 void ListValue::Swap(ListValue* other) {
1303 CHECK(other->is_list()); 1356 CHECK(other->is_list());
1304 list_->swap(*(other->list_)); 1357 list_->swap(*(other->list_));
1305 } 1358 }
1306 1359
1307 ListValue* ListValue::DeepCopy() const { 1360 ListValue* ListValue::DeepCopy() const {
1308 return static_cast<ListValue*>(Value::DeepCopy()); 1361 return static_cast<ListValue*>(Value::DeepCopy());
(...skipping 16 matching lines...) Expand all
1325 } 1378 }
1326 1379
1327 std::ostream& operator<<(std::ostream& out, const Value::Type& type) { 1380 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1328 if (static_cast<int>(type) < 0 || 1381 if (static_cast<int>(type) < 0 ||
1329 static_cast<size_t>(type) >= arraysize(kTypeNames)) 1382 static_cast<size_t>(type) >= arraysize(kTypeNames))
1330 return out << "Invalid Type (index = " << static_cast<int>(type) << ")"; 1383 return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1331 return out << Value::GetTypeName(type); 1384 return out << Value::GetTypeName(type);
1332 } 1385 }
1333 1386
1334 } // namespace base 1387 } // namespace base
OLDNEW
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698