Adds Find method to the ListValue class.

This method makes working with lists easierand will be needed from the
refactored signed settings code.

BUG=chromium-os:14054
TEST=base_unittest --gtest_filter=ValuesTest.List


Review URL: http://codereview.chromium.org/7892052

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101741 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 5fb35372c80f9436a980281cc826d8a72fcf8915
diff --git a/base/values.cc b/base/values.cc
index 17aba16..60b0d70 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -4,6 +4,8 @@
 
 #include "base/values.h"
 
+#include <algorithm>
+
 #include "base/float_util.h"
 #include "base/logging.h"
 #include "base/string_util.h"
@@ -58,6 +60,22 @@
   }
 }
 
+// A small functor for comparing Values for std::find_if and similar.
+class ValueEquals {
+ public:
+  // Pass the value against which all consecutive calls of the () operator will
+  // compare their argument to. This Value object must not be destroyed while
+  // the ValueEquals is  in use.
+  ValueEquals(const Value* first) : first_(first) { }
+
+  bool operator ()(const Value* second) const {
+    return first_->Equals(second);
+  }
+
+ private:
+  const Value* first_;
+};
+
 }  // namespace
 
 namespace base {
@@ -865,6 +883,10 @@
   return true;
 }
 
+ListValue::const_iterator ListValue::Find(const Value& value) const {
+  return std::find_if(list_.begin(), list_.end(), ValueEquals(&value));
+}
+
 bool ListValue::GetAsList(ListValue** out_value) {
   if (out_value)
     *out_value = this;
diff --git a/base/values.h b/base/values.h
index a30791b..90cc40c 100644
--- a/base/values.h
+++ b/base/values.h
@@ -418,6 +418,11 @@
   // Returns true if successful, or false if the index was out of range.
   bool Insert(size_t index, Value* in_value);
 
+  // Searches for the first instance of |value| in the list using the Equals
+  // method of the Value type.
+  // Returns a const_iterator to the found item or to end() if none exists.
+  const_iterator Find(const Value& value) const;
+
   // Swaps contents with the |other| list.
   void Swap(ListValue* other) {
     list_.swap(other->list_);
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index 553e8e1..458a4e1 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -93,6 +93,15 @@
   ASSERT_EQ(88.8, double_value);
   ASSERT_TRUE(mixed_list->GetString(3, &string_value));
   ASSERT_EQ("foo", string_value);
+
+  // Try searching in the mixed list.
+  scoped_ptr<Value> sought_value(Value::CreateIntegerValue(42));
+  scoped_ptr<Value> not_found_value(Value::CreateBooleanValue(false));
+
+  ASSERT_NE(mixed_list->end(), mixed_list->Find(*sought_value));
+  ASSERT_TRUE((*mixed_list->Find(*sought_value))->GetAsInteger(&int_value));
+  ASSERT_EQ(42, int_value);
+  ASSERT_EQ(mixed_list->end(), mixed_list->Find(*not_found_value));
 }
 
 TEST(ValuesTest, BinaryValue) {