Home | History | Annotate | Download | only in indexed_db
      1 // Copyright (c) 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 CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_
      6 #define CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_
      7 
      8 #include <algorithm>
      9 #include <iterator>
     10 #include <list>
     11 #include <set>
     12 #include "base/logging.h"
     13 #include "base/memory/scoped_ptr.h"
     14 
     15 //
     16 // A container class that provides fast containment test (like a set)
     17 // but maintains insertion order for iteration (like list).
     18 //
     19 // Member types of value (primitives and objects by value), raw pointers
     20 // and scoped_refptr<> are supported.
     21 //
     22 template <typename T>
     23 class list_set {
     24  public:
     25   list_set() {}
     26   list_set(const list_set<T>& other) : list_(other.list_), set_(other.set_) {}
     27   list_set& operator=(const list_set<T>& other) {
     28     list_ = other.list_;
     29     set_ = other.set_;
     30     return *this;
     31   }
     32 
     33   void insert(const T& elem) {
     34     if (set_.find(elem) != set_.end())
     35       return;
     36     set_.insert(elem);
     37     list_.push_back(elem);
     38   }
     39 
     40   void erase(const T& elem) {
     41     if (set_.find(elem) == set_.end())
     42       return;
     43     set_.erase(elem);
     44     typename std::list<T>::iterator it =
     45         std::find(list_.begin(), list_.end(), elem);
     46     DCHECK(it != list_.end());
     47     list_.erase(it);
     48   }
     49 
     50   size_t count(const T& elem) const {
     51     return set_.find(elem) == set_.end() ? 0 : 1;
     52   }
     53 
     54   size_t size() const {
     55     DCHECK_EQ(list_.size(), set_.size());
     56     return set_.size();
     57   }
     58 
     59   bool empty() const {
     60     DCHECK_EQ(list_.empty(), set_.empty());
     61     return set_.empty();
     62   }
     63 
     64   class const_iterator;
     65 
     66   class iterator {
     67    public:
     68     typedef iterator self_type;
     69     typedef T value_type;
     70     typedef T& reference;
     71     typedef T* pointer;
     72     typedef std::bidirectional_iterator_tag iterator_category;
     73     typedef std::ptrdiff_t difference_type;
     74 
     75     explicit inline iterator(typename std::list<T>::iterator it) : it_(it) {}
     76     inline self_type& operator++() {
     77       ++it_;
     78       return *this;
     79     }
     80     inline self_type operator++(int /*ignored*/) {
     81       self_type result(*this);
     82       ++(*this);
     83       return result;
     84     }
     85     inline self_type& operator--() {
     86       --it_;
     87       return *this;
     88     }
     89     inline self_type operator--(int /*ignored*/) {
     90       self_type result(*this);
     91       --(*this);
     92       return result;
     93     }
     94     inline value_type& operator*() { return *it_; }
     95     inline value_type* operator->() { return &(*it_); }
     96     inline bool operator==(const iterator& rhs) const { return it_ == rhs.it_; }
     97     inline bool operator!=(const iterator& rhs) const { return it_ != rhs.it_; }
     98 
     99     inline operator const_iterator() const { return const_iterator(it_); }
    100 
    101    private:
    102     typename std::list<T>::iterator it_;
    103   };
    104 
    105   class const_iterator {
    106    public:
    107     typedef const_iterator self_type;
    108     typedef T value_type;
    109     typedef T& reference;
    110     typedef T* pointer;
    111     typedef std::bidirectional_iterator_tag iterator_category;
    112     typedef std::ptrdiff_t difference_type;
    113 
    114     explicit inline const_iterator(typename std::list<T>::const_iterator it)
    115         : it_(it) {}
    116     inline self_type& operator++() {
    117       ++it_;
    118       return *this;
    119     }
    120     inline self_type operator++(int ignored) {
    121       self_type result(*this);
    122       ++(*this);
    123       return result;
    124     }
    125     inline self_type& operator--() {
    126       --it_;
    127       return *this;
    128     }
    129     inline self_type operator--(int ignored) {
    130       self_type result(*this);
    131       --(*this);
    132       return result;
    133     }
    134     inline const value_type& operator*() { return *it_; }
    135     inline const value_type* operator->() { return &(*it_); }
    136     inline bool operator==(const const_iterator& rhs) const {
    137       return it_ == rhs.it_;
    138     }
    139     inline bool operator!=(const const_iterator& rhs) const {
    140       return it_ != rhs.it_;
    141     }
    142 
    143    private:
    144     typename std::list<T>::const_iterator it_;
    145   };
    146 
    147   iterator begin() { return iterator(list_.begin()); }
    148   iterator end() { return iterator(list_.end()); }
    149   const_iterator begin() const { return const_iterator(list_.begin()); }
    150   const_iterator end() const { return const_iterator(list_.end()); }
    151 
    152  private:
    153   std::list<T> list_;
    154   std::set<T> set_;
    155 };
    156 
    157 // Prevent instantiation of list_set<scoped_ptr<T>> as the current
    158 // implementation would fail.
    159 // TODO(jsbell): Support scoped_ptr through specialization.
    160 template <typename T>
    161 class list_set<scoped_ptr<T> >;
    162 
    163 #endif  // CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_
    164