1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/prefs/pref_value_map.h"
6
7#include "base/logging.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/stl_util-inl.h"
10#include "base/values.h"
11
12PrefValueMap::PrefValueMap() {}
13
14PrefValueMap::~PrefValueMap() {
15  Clear();
16}
17
18bool PrefValueMap::GetValue(const std::string& key, const Value** value) const {
19  const Map::const_iterator entry = prefs_.find(key);
20  if (entry != prefs_.end()) {
21    if (value)
22      *value = entry->second;
23    return true;
24  }
25
26  return false;
27}
28
29bool PrefValueMap::GetValue(const std::string& key, Value** value) {
30  const Map::const_iterator entry = prefs_.find(key);
31  if (entry != prefs_.end()) {
32    if (value)
33      *value = entry->second;
34    return true;
35  }
36
37  return false;
38}
39
40bool PrefValueMap::SetValue(const std::string& key, Value* value) {
41  DCHECK(value);
42  scoped_ptr<Value> value_ptr(value);
43  const Map::iterator entry = prefs_.find(key);
44  if (entry != prefs_.end()) {
45    if (Value::Equals(entry->second, value))
46      return false;
47    delete entry->second;
48    entry->second = value_ptr.release();
49  } else {
50    prefs_[key] = value_ptr.release();
51  }
52
53  return true;
54}
55
56bool PrefValueMap::RemoveValue(const std::string& key) {
57  const Map::iterator entry = prefs_.find(key);
58  if (entry != prefs_.end()) {
59    delete entry->second;
60    prefs_.erase(entry);
61    return true;
62  }
63
64  return false;
65}
66
67void PrefValueMap::Clear() {
68  STLDeleteValues(&prefs_);
69  prefs_.clear();
70}
71
72PrefValueMap::iterator PrefValueMap::begin() {
73  return prefs_.begin();
74}
75
76PrefValueMap::iterator PrefValueMap::end() {
77  return prefs_.end();
78}
79
80PrefValueMap::const_iterator PrefValueMap::begin() const {
81  return prefs_.begin();
82}
83
84PrefValueMap::const_iterator PrefValueMap::end() const {
85  return prefs_.end();
86}
87
88bool PrefValueMap::GetBoolean(const std::string& key,
89                              bool* value) const {
90  const Value* stored_value = NULL;
91  return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value);
92}
93
94bool PrefValueMap::GetString(const std::string& key,
95                             std::string* value) const {
96  const Value* stored_value = NULL;
97  return GetValue(key, &stored_value) && stored_value->GetAsString(value);
98}
99
100void PrefValueMap::SetString(const std::string& key,
101                             const std::string& value) {
102  SetValue(key, Value::CreateStringValue(value));
103}
104
105void PrefValueMap::GetDifferingKeys(
106    const PrefValueMap* other,
107    std::vector<std::string>* differing_keys) const {
108  differing_keys->clear();
109
110  // Walk over the maps in lockstep, adding everything that is different.
111  Map::const_iterator this_pref(prefs_.begin());
112  Map::const_iterator other_pref(other->prefs_.begin());
113  while (this_pref != prefs_.end() && other_pref != other->prefs_.end()) {
114    const int diff = this_pref->first.compare(other_pref->first);
115    if (diff == 0) {
116      if (!this_pref->second->Equals(other_pref->second))
117        differing_keys->push_back(this_pref->first);
118      ++this_pref;
119      ++other_pref;
120    } else if (diff < 0) {
121      differing_keys->push_back(this_pref->first);
122      ++this_pref;
123    } else if (diff > 0) {
124      differing_keys->push_back(other_pref->first);
125      ++other_pref;
126    }
127  }
128
129  // Add the remaining entries.
130  for ( ; this_pref != prefs_.end(); ++this_pref)
131      differing_keys->push_back(this_pref->first);
132  for ( ; other_pref != other->prefs_.end(); ++other_pref)
133      differing_keys->push_back(other_pref->first);
134}
135