Home | History | Annotate | Download | only in permissions
      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:
     36     const_iterator(const typename Map::const_iterator& it) : it_(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 
     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 
     76   BaseSetOperators(const T& set) {
     77     this->operator=(set);
     78   }
     79 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    237   const_iterator begin() const {
    238     return const_iterator(map().begin());
    239   }
    240 
    241   const_iterator end() const {
    242     return map().end();
    243   }
    244 
    245   const_iterator find(ElementIDType id) const {
    246     return map().find(id);
    247   }
    248 
    249   size_t count(ElementIDType id) const {
    250     return map().count(id);
    251   }
    252 
    253   bool empty() const {
    254     return map().empty();
    255   }
    256 
    257   size_t erase(ElementIDType id) {
    258     return map().erase(id);
    259   }
    260 
    261   // Take ownership and insert |item| into the set.
    262   void insert(ElementType* item) {
    263     map_[item->id()].reset(item);
    264   }
    265 
    266   size_t size() const {
    267     return map().size();
    268   }
    269 
    270   const Map& map() const {
    271     return map_;
    272   }
    273 
    274   Map& map() {
    275     return map_;
    276   }
    277 
    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