• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_
6 #define EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_
7 
8 #include <iterator>
9 #include <map>
10 
11 #include "base/memory/linked_ptr.h"
12 #include "base/template_util.h"
13 
14 namespace extensions {
15 
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 {};
21 
22 // Set operations shared by |APIPermissionSet| and |ManifestPermissionSet|.
23 //
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;
32 
33   class const_iterator :
34     public std::iterator<std::input_iterator_tag, const ElementType*> {
35    public:
const_iterator(const typename Map::const_iterator & it)36     const_iterator(const typename Map::const_iterator& it) : it_(it) {}
const_iterator(const const_iterator & ids_it)37     const_iterator(const const_iterator& ids_it) : it_(ids_it.it_) {}
38 
39     const_iterator& operator++() {
40       ++it_;
41       return *this;
42     }
43 
44     const_iterator operator++(int) {
45       const_iterator tmp(it_++);
46       return tmp;
47     }
48 
49     bool operator==(const const_iterator& rhs) const {
50       return it_ == rhs.it_;
51     }
52 
53     bool operator!=(const const_iterator& rhs) const {
54       return it_ != rhs.it_;
55     }
56 
57     const ElementType* operator*() const {
58       return it_->second.get();
59     }
60 
61     const ElementType* operator->() const {
62       return it_->second.get();
63     }
64 
65    private:
66     typename Map::const_iterator it_;
67   };
68 
BaseSetOperators()69   BaseSetOperators() {
70     // Ensure |T| is convertible to us, so we can safely downcast when calling
71     // methods that must exist in |T|.
72     COMPILE_ASSERT((base::is_convertible<T*, BaseSetOperators<T>*>::value),
73                    U_ptr_must_implicitly_convert_to_T_ptr);
74   }
75 
BaseSetOperators(const T & set)76   BaseSetOperators(const T& set) {
77     this->operator=(set);
78   }
79 
~BaseSetOperators()80   ~BaseSetOperators() {}
81 
82   T& operator=(const T& rhs) {
83     return Assign(rhs);
84   }
85 
86   bool operator==(const T& rhs) const {
87     return Equal(rhs);
88   }
89 
90   bool operator!=(const T& rhs) const {
91     return !operator==(rhs);
92   }
93 
Assign(const T & 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;
100     }
101     return *static_cast<T*>(this);
102   }
103 
Equal(const T & rhs)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();
109 
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;
119     }
120     return it == it_end && rhs_it == rhs_it_end;
121   }
122 
Contains(const T & rhs)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();
128 
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;
139       }
140     }
141 
142     return it2 == end2;
143   }
144 
Difference(const T & set1,const T & set2,T * set3)145   static void Difference(const T& set1, const T& set2, T* set3) {
146     CHECK(set3);
147     set3->clear();
148 
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();
153 
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;
166       }
167     }
168 
169     while (it1 != end1) {
170       set3->insert(it1->Clone());
171       ++it1;
172     }
173   }
174 
Intersection(const T & set1,const T & set2,T * set3)175   static void Intersection(const T& set1, const T& set2, T* set3) {
176     DCHECK(set3);
177     set3->clear();
178 
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();
183 
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;
195       }
196     }
197   }
198 
Union(const T & set1,const T & set2,T * set3)199   static void Union(const T& set1, const T& set2, T* set3) {
200     DCHECK(set3);
201     set3->clear();
202 
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();
207 
208     while (true) {
209       if (it1 == end1) {
210         while (it2 != end2) {
211           set3->insert(it2->Clone());
212           ++it2;
213         }
214         break;
215       }
216       if (it2 == end2) {
217         while (it1 != end1) {
218           set3->insert(it1->Clone());
219           ++it1;
220         }
221         break;
222       }
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;
233       }
234     }
235   }
236 
begin()237   const_iterator begin() const {
238     return const_iterator(map().begin());
239   }
240 
end()241   const_iterator end() const {
242     return map().end();
243   }
244 
find(ElementIDType id)245   const_iterator find(ElementIDType id) const {
246     return map().find(id);
247   }
248 
count(ElementIDType id)249   size_t count(ElementIDType id) const {
250     return map().count(id);
251   }
252 
empty()253   bool empty() const {
254     return map().empty();
255   }
256 
erase(ElementIDType id)257   size_t erase(ElementIDType id) {
258     return map().erase(id);
259   }
260 
261   // Take ownership and insert |item| into the set.
insert(ElementType * item)262   void insert(ElementType* item) {
263     map_[item->id()].reset(item);
264   }
265 
size()266   size_t size() const {
267     return map().size();
268   }
269 
map()270   const Map& map() const {
271     return map_;
272   }
273 
map()274   Map& map() {
275     return map_;
276   }
277 
clear()278   void clear() {
279     map_.clear();
280   }
281 
282  private:
283   Map map_;
284 };
285 
286 }  // namespace extensions
287 
288 #endif  // EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_
289