Fix crash on app list start page contents not existing.
[chromium-blink-merge.git] / extensions / common / permissions / base_set_operators.h
blobd18321ca0afb7852b03519b8f0187a4a3d29cb66
1 // Copyright 2013 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.
5 #ifndef EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_
6 #define EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_
8 #include <iterator>
9 #include <map>
11 #include "base/memory/linked_ptr.h"
12 #include "base/template_util.h"
14 namespace extensions {
16 // Traits for template paramater of |BaseSetOperators<T>|. Specializations
17 // should define |ElementType| for the type of elements to store in the set,
18 // and |EmementIDType| for the type of element identifiers.
19 template <typename T>
20 struct BaseSetOperatorsTraits {};
22 // Set operations shared by |APIPermissionSet| and |ManifestPermissionSet|.
24 // TODO(rpaquay): It would be nice to remove the need for the sub-classes and
25 // instead directly use this class where needed.
26 template <typename T>
27 class BaseSetOperators {
28 public:
29 typedef typename BaseSetOperatorsTraits<T>::ElementType ElementType;
30 typedef typename BaseSetOperatorsTraits<T>::ElementIDType ElementIDType;
31 typedef std::map<ElementIDType, linked_ptr<ElementType> > Map;
33 class const_iterator :
34 public std::iterator<std::input_iterator_tag, const ElementType*> {
35 public:
36 const_iterator(const typename Map::const_iterator& it) : it_(it) {}
37 const_iterator(const const_iterator& ids_it) : it_(ids_it.it_) {}
39 const_iterator& operator++() {
40 ++it_;
41 return *this;
44 const_iterator operator++(int) {
45 const_iterator tmp(it_++);
46 return tmp;
49 bool operator==(const const_iterator& rhs) const {
50 return it_ == rhs.it_;
53 bool operator!=(const const_iterator& rhs) const {
54 return it_ != rhs.it_;
57 const ElementType* operator*() const {
58 return it_->second.get();
61 const ElementType* operator->() const {
62 return it_->second.get();
65 private:
66 typename Map::const_iterator it_;
69 BaseSetOperators() {
70 // Ensure |T| is convertible to us, so we can safely downcast when calling
71 // methods that must exist in |T|.
72 static_assert((base::is_convertible<T*, BaseSetOperators<T>*>::value),
73 "U ptr must implicitly convert to T ptr");
76 BaseSetOperators(const T& set) {
77 this->operator=(set);
80 ~BaseSetOperators() {}
82 T& operator=(const T& rhs) {
83 return Assign(rhs);
86 bool operator==(const T& rhs) const {
87 return Equal(rhs);
90 bool operator!=(const T& rhs) const {
91 return !operator==(rhs);
94 T& Assign(const T& rhs) {
95 const_iterator it = rhs.begin();
96 const const_iterator end = rhs.end();
97 while (it != end) {
98 insert(it->Clone());
99 ++it;
101 return *static_cast<T*>(this);
104 bool Equal(const T& rhs) const {
105 const_iterator it = begin();
106 const_iterator rhs_it = rhs.begin();
107 const_iterator it_end = end();
108 const_iterator rhs_it_end = rhs.end();
110 while (it != it_end && rhs_it != rhs_it_end) {
111 if (it->id() > rhs_it->id())
112 return false;
113 else if (it->id() < rhs_it->id())
114 return false;
115 else if (!it->Equal(*rhs_it))
116 return false;
117 ++it;
118 ++rhs_it;
120 return it == it_end && rhs_it == rhs_it_end;
123 bool Contains(const T& rhs) const {
124 const_iterator it1 = begin();
125 const_iterator it2 = rhs.begin();
126 const_iterator end1 = end();
127 const_iterator end2 = rhs.end();
129 while (it1 != end1 && it2 != end2) {
130 if (it1->id() > it2->id()) {
131 return false;
132 } else if (it1->id() < it2->id()) {
133 ++it1;
134 } else {
135 if (!it1->Contains(*it2))
136 return false;
137 ++it1;
138 ++it2;
142 return it2 == end2;
145 static void Difference(const T& set1, const T& set2, T* set3) {
146 CHECK(set3);
147 set3->clear();
149 const_iterator it1 = set1.begin();
150 const_iterator it2 = set2.begin();
151 const const_iterator end1 = set1.end();
152 const const_iterator end2 = set2.end();
154 while (it1 != end1 && it2 != end2) {
155 if (it1->id() < it2->id()) {
156 set3->insert(it1->Clone());
157 ++it1;
158 } else if (it1->id() > it2->id()) {
159 ++it2;
160 } else {
161 ElementType* p = it1->Diff(*it2);
162 if (p)
163 set3->insert(p);
164 ++it1;
165 ++it2;
169 while (it1 != end1) {
170 set3->insert(it1->Clone());
171 ++it1;
175 static void Intersection(const T& set1, const T& set2, T* set3) {
176 DCHECK(set3);
177 set3->clear();
179 const_iterator it1 = set1.begin();
180 const_iterator it2 = set2.begin();
181 const const_iterator end1 = set1.end();
182 const const_iterator end2 = set2.end();
184 while (it1 != end1 && it2 != end2) {
185 if (it1->id() < it2->id()) {
186 ++it1;
187 } else if (it1->id() > it2->id()) {
188 ++it2;
189 } else {
190 ElementType* p = it1->Intersect(*it2);
191 if (p)
192 set3->insert(p);
193 ++it1;
194 ++it2;
199 static void Union(const T& set1, const T& set2, T* set3) {
200 DCHECK(set3);
201 set3->clear();
203 const_iterator it1 = set1.begin();
204 const_iterator it2 = set2.begin();
205 const const_iterator end1 = set1.end();
206 const const_iterator end2 = set2.end();
208 while (true) {
209 if (it1 == end1) {
210 while (it2 != end2) {
211 set3->insert(it2->Clone());
212 ++it2;
214 break;
216 if (it2 == end2) {
217 while (it1 != end1) {
218 set3->insert(it1->Clone());
219 ++it1;
221 break;
223 if (it1->id() < it2->id()) {
224 set3->insert(it1->Clone());
225 ++it1;
226 } else if (it1->id() > it2->id()) {
227 set3->insert(it2->Clone());
228 ++it2;
229 } else {
230 set3->insert(it1->Union(*it2));
231 ++it1;
232 ++it2;
237 const_iterator begin() const {
238 return const_iterator(map().begin());
241 const_iterator end() const {
242 return map().end();
245 const_iterator find(ElementIDType id) const {
246 return map().find(id);
249 size_t count(ElementIDType id) const {
250 return map().count(id);
253 bool empty() const {
254 return map().empty();
257 size_t erase(ElementIDType id) {
258 return map().erase(id);
261 // Take ownership and insert |item| into the set.
262 void insert(ElementType* item) {
263 map_[item->id()].reset(item);
266 size_t size() const {
267 return map().size();
270 const Map& map() const {
271 return map_;
274 Map& map() {
275 return map_;
278 void clear() {
279 map_.clear();
282 private:
283 Map map_;
286 } // namespace extensions
288 #endif // EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_