shill: KeyFileStore: Add methods to search by properties

Add methods to the StoreInterface to return a list of groups that
contain name-value pairs of properties.

BUG=chromium-os:38048
TEST=Unit tests

Change-Id: Ice46774cd31c6ab76df9d2febf4fb66bef819daa
Reviewed-on: https://gerrit.chromium.org/gerrit/41672
Commit-Queue: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/key_file_store.cc b/key_file_store.cc
index 5117b66..76839f4 100644
--- a/key_file_store.cc
+++ b/key_file_store.cc
@@ -4,14 +4,18 @@
 
 #include "shill/key_file_store.h"
 
+#include <map>
+
 #include <base/file_util.h>
 #include <base/string_number_conversions.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include "shill/key_value_store.h"
 #include "shill/logging.h"
 
+using std::map;
 using std::set;
 using std::string;
 using std::vector;
@@ -147,6 +151,18 @@
   return groups_with_key;
 }
 
+set<string> KeyFileStore::GetGroupsWithProperties(
+     const KeyValueStore &properties) const {
+  set<string> groups = GetGroups();
+  set<string> groups_with_properties;
+  for (set<string>::iterator it = groups.begin(); it != groups.end(); ++it) {
+    if (DoesGroupMatchProperties(*it, properties)) {
+      groups_with_properties.insert(*it);
+    }
+  }
+  return groups_with_properties;
+}
+
 bool KeyFileStore::ContainsGroup(const string &group) const {
   CHECK(key_file_);
   return glib_->KeyFileHasGroup(key_file_, group.c_str());
@@ -358,4 +374,39 @@
   return SetString(group, key, crypto_.Encrypt(value));
 }
 
+bool KeyFileStore::DoesGroupMatchProperties(
+    const string &group, const KeyValueStore &properties) const {
+  map<string, bool>::const_iterator bool_it;
+  for (bool_it = properties.bool_properties().begin();
+       bool_it != properties.bool_properties().end();
+       ++bool_it) {
+    bool value;
+    if (!GetBool(group, bool_it->first, &value) ||
+        value != bool_it->second) {
+      return false;
+    }
+  }
+  map<string, int32>::const_iterator int_it;
+  for (int_it = properties.int_properties().begin();
+       int_it != properties.int_properties().end();
+       ++int_it) {
+    int value;
+    if (!GetInt(group, int_it->first, &value) ||
+        value != int_it->second) {
+      return false;
+    }
+  }
+  map<string, string>::const_iterator string_it;
+  for (string_it = properties.string_properties().begin();
+       string_it != properties.string_properties().end();
+       ++string_it) {
+    string value;
+    if (!GetString(group, string_it->first, &value) ||
+        value != string_it->second) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace shill