OLD | NEW |
(Empty) | |
| 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 |
| 13 namespace extensions { |
| 14 |
| 15 // Traits for template paramater of |BaseSetOperators<T>|. Specializations |
| 16 // should define |ElementType| for the type of elements to store in the set, |
| 17 // and |EmementIDType| for the type of element identifiers. |
| 18 template <typename T> |
| 19 struct BaseSetOperatorsTraits {}; |
| 20 |
| 21 // Set operations shared by |APIPermissionSet| and |ManifestPermissionSet|. |
| 22 // |
| 23 // TODO(rpaquay): It would be nice to remove the need for the sub-classes and |
| 24 // instead directly use this class where needed. |
| 25 template <typename T> |
| 26 class BaseSetOperators { |
| 27 public: |
| 28 typedef typename BaseSetOperatorsTraits<T>::ElementType ElementType; |
| 29 typedef typename BaseSetOperatorsTraits<T>::ElementIDType ElementIDType; |
| 30 typedef std::map<ElementIDType, linked_ptr<ElementType> > Map; |
| 31 |
| 32 class const_iterator : |
| 33 public std::iterator<std::input_iterator_tag, const ElementType*> { |
| 34 public: |
| 35 const_iterator(const typename Map::const_iterator& it) : it_(it) {} |
| 36 const_iterator(const const_iterator& ids_it) : it_(ids_it.it_) {} |
| 37 |
| 38 const_iterator& operator++() { |
| 39 ++it_; |
| 40 return *this; |
| 41 } |
| 42 |
| 43 const_iterator operator++(int) { |
| 44 const_iterator tmp(it_++); |
| 45 return tmp; |
| 46 } |
| 47 |
| 48 bool operator==(const const_iterator& rhs) const { |
| 49 return it_ == rhs.it_; |
| 50 } |
| 51 |
| 52 bool operator!=(const const_iterator& rhs) const { |
| 53 return it_ != rhs.it_; |
| 54 } |
| 55 |
| 56 const ElementType* operator*() const { |
| 57 return it_->second.get(); |
| 58 } |
| 59 |
| 60 const ElementType* operator->() const { |
| 61 return it_->second.get(); |
| 62 } |
| 63 |
| 64 private: |
| 65 typename Map::const_iterator it_; |
| 66 }; |
| 67 |
| 68 BaseSetOperators() { |
| 69 // Ensure |T| is convertible to us, so we can safely downcast when calling |
| 70 // methods that must exist in |T|. |
| 71 COMPILE_ASSERT((base::is_convertible<T*, BaseSetOperators<T>*>::value), |
| 72 U_ptr_must_implicitly_convert_to_T_ptr); |
| 73 } |
| 74 |
| 75 BaseSetOperators(const T& set) { |
| 76 this->operator=(set); |
| 77 } |
| 78 |
| 79 ~BaseSetOperators() {} |
| 80 |
| 81 T& operator=(const T& rhs) { |
| 82 return Assign(rhs); |
| 83 } |
| 84 |
| 85 bool operator==(const T& rhs) const { |
| 86 return Equal(rhs); |
| 87 } |
| 88 |
| 89 bool operator!=(const T& rhs) const { |
| 90 return !operator==(rhs); |
| 91 } |
| 92 |
| 93 T& Assign(const T& rhs) { |
| 94 T::const_iterator it = rhs.begin(); |
| 95 const T::const_iterator end = rhs.end(); |
| 96 while (it != end) { |
| 97 insert(it->Clone()); |
| 98 ++it; |
| 99 } |
| 100 return *static_cast<T*>(this); |
| 101 } |
| 102 |
| 103 bool Equal(const T& rhs) const { |
| 104 T::const_iterator it = begin(); |
| 105 T::const_iterator rhs_it = rhs.begin(); |
| 106 T::const_iterator it_end = end(); |
| 107 T::const_iterator rhs_it_end = rhs.end(); |
| 108 |
| 109 while (it != it_end && rhs_it != rhs_it_end) { |
| 110 if (it->id() > rhs_it->id()) |
| 111 return false; |
| 112 else if (it->id() < rhs_it->id()) |
| 113 return false; |
| 114 else if (!it->Equal(*rhs_it)) |
| 115 return false; |
| 116 ++it; |
| 117 ++rhs_it; |
| 118 } |
| 119 return it == it_end && rhs_it == rhs_it_end; |
| 120 } |
| 121 |
| 122 bool Contains(const T& rhs) const { |
| 123 T::const_iterator it1 = begin(); |
| 124 T::const_iterator it2 = rhs.begin(); |
| 125 T::const_iterator end1 = end(); |
| 126 T::const_iterator end2 = rhs.end(); |
| 127 |
| 128 while (it1 != end1 && it2 != end2) { |
| 129 if (it1->id() > it2->id()) { |
| 130 return false; |
| 131 } else if (it1->id() < it2->id()) { |
| 132 ++it1; |
| 133 } else { |
| 134 if (!it1->Contains(*it2)) |
| 135 return false; |
| 136 ++it1; |
| 137 ++it2; |
| 138 } |
| 139 } |
| 140 |
| 141 return it2 == end2; |
| 142 } |
| 143 |
| 144 static void Difference(const T& set1, const T& set2, T* set3) { |
| 145 CHECK(set3); |
| 146 set3->clear(); |
| 147 |
| 148 T::const_iterator it1 = set1.begin(); |
| 149 T::const_iterator it2 = set2.begin(); |
| 150 const T::const_iterator end1 = set1.end(); |
| 151 const T::const_iterator end2 = set2.end(); |
| 152 |
| 153 while (it1 != end1 && it2 != end2) { |
| 154 if (it1->id() < it2->id()) { |
| 155 set3->insert(it1->Clone()); |
| 156 ++it1; |
| 157 } else if (it1->id() > it2->id()) { |
| 158 ++it2; |
| 159 } else { |
| 160 T::ElementType* p = it1->Diff(*it2); |
| 161 if (p) |
| 162 set3->insert(p); |
| 163 ++it1; |
| 164 ++it2; |
| 165 } |
| 166 } |
| 167 |
| 168 while (it1 != end1) { |
| 169 set3->insert(it1->Clone()); |
| 170 ++it1; |
| 171 } |
| 172 } |
| 173 |
| 174 static void Intersection(const T& set1, const T& set2, T* set3) { |
| 175 DCHECK(set3); |
| 176 set3->clear(); |
| 177 |
| 178 T::const_iterator it1 = set1.begin(); |
| 179 T::const_iterator it2 = set2.begin(); |
| 180 const T::const_iterator end1 = set1.end(); |
| 181 const T::const_iterator end2 = set2.end(); |
| 182 |
| 183 while (it1 != end1 && it2 != end2) { |
| 184 if (it1->id() < it2->id()) { |
| 185 ++it1; |
| 186 } else if (it1->id() > it2->id()) { |
| 187 ++it2; |
| 188 } else { |
| 189 T::ElementType* p = it1->Intersect(*it2); |
| 190 if (p) |
| 191 set3->insert(p); |
| 192 ++it1; |
| 193 ++it2; |
| 194 } |
| 195 } |
| 196 } |
| 197 |
| 198 static void Union(const T& set1, const T& set2, T* set3) { |
| 199 DCHECK(set3); |
| 200 set3->clear(); |
| 201 |
| 202 T::const_iterator it1 = set1.begin(); |
| 203 T::const_iterator it2 = set2.begin(); |
| 204 const T::const_iterator end1 = set1.end(); |
| 205 const T::const_iterator end2 = set2.end(); |
| 206 |
| 207 while (true) { |
| 208 if (it1 == end1) { |
| 209 while (it2 != end2) { |
| 210 set3->insert(it2->Clone()); |
| 211 ++it2; |
| 212 } |
| 213 break; |
| 214 } |
| 215 if (it2 == end2) { |
| 216 while (it1 != end1) { |
| 217 set3->insert(it1->Clone()); |
| 218 ++it1; |
| 219 } |
| 220 break; |
| 221 } |
| 222 if (it1->id() < it2->id()) { |
| 223 set3->insert(it1->Clone()); |
| 224 ++it1; |
| 225 } else if (it1->id() > it2->id()) { |
| 226 set3->insert(it2->Clone()); |
| 227 ++it2; |
| 228 } else { |
| 229 set3->insert(it1->Union(*it2)); |
| 230 ++it1; |
| 231 ++it2; |
| 232 } |
| 233 } |
| 234 } |
| 235 |
| 236 const_iterator begin() const { |
| 237 return const_iterator(map().begin()); |
| 238 } |
| 239 |
| 240 const_iterator end() const { |
| 241 return map().end(); |
| 242 } |
| 243 |
| 244 const_iterator find(ElementIDType id) const { |
| 245 return map().find(id); |
| 246 } |
| 247 |
| 248 size_t count(ElementIDType id) const { |
| 249 return map().count(id); |
| 250 } |
| 251 |
| 252 bool empty() const { |
| 253 return map().empty(); |
| 254 } |
| 255 |
| 256 size_t erase(ElementIDType id) { |
| 257 return map().erase(id); |
| 258 } |
| 259 |
| 260 // Take ownership and insert |item| into the set. |
| 261 void insert(ElementType* item) { |
| 262 map_[item->id()].reset(item); |
| 263 } |
| 264 |
| 265 size_t size() const { |
| 266 return map().size(); |
| 267 } |
| 268 |
| 269 const Map& map() const { |
| 270 return map_; |
| 271 } |
| 272 |
| 273 Map& map() { |
| 274 return map_; |
| 275 } |
| 276 |
| 277 void clear() { |
| 278 map_.clear(); |
| 279 } |
| 280 |
| 281 private: |
| 282 Map map_; |
| 283 }; |
| 284 |
| 285 } // namespace extensions |
| 286 |
| 287 #endif // EXTENSIONS_COMMON_PERMISSIONS_BASE_SET_OPERATORS_H_ |
OLD | NEW |