// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_ #define CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_ #include #include #include #include #include "base/logging.h" #include "base/memory/scoped_ptr.h" // // A container class that provides fast containment test (like a set) // but maintains insertion order for iteration (like list). // // Member types of value (primitives and objects by value), raw pointers // and scoped_refptr<> are supported. // template class list_set { public: list_set() {} list_set(const list_set& other) : list_(other.list_), set_(other.set_) {} list_set& operator=(const list_set& other) { list_ = other.list_; set_ = other.set_; return *this; } void insert(const T& elem) { if (set_.find(elem) != set_.end()) return; set_.insert(elem); list_.push_back(elem); } void erase(const T& elem) { if (set_.find(elem) == set_.end()) return; set_.erase(elem); typename std::list::iterator it = std::find(list_.begin(), list_.end(), elem); DCHECK(it != list_.end()); list_.erase(it); } size_t count(const T& elem) const { return set_.find(elem) == set_.end() ? 0 : 1; } size_t size() const { DCHECK_EQ(list_.size(), set_.size()); return set_.size(); } bool empty() const { DCHECK_EQ(list_.empty(), set_.empty()); return set_.empty(); } class const_iterator; class iterator { public: typedef iterator self_type; typedef T value_type; typedef T& reference; typedef T* pointer; typedef std::bidirectional_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; explicit inline iterator(typename std::list::iterator it) : it_(it) {} inline self_type& operator++() { ++it_; return *this; } inline self_type operator++(int /*ignored*/) { self_type result(*this); ++(*this); return result; } inline self_type& operator--() { --it_; return *this; } inline self_type operator--(int /*ignored*/) { self_type result(*this); --(*this); return result; } inline value_type& operator*() { return *it_; } inline value_type* operator->() { return &(*it_); } inline bool operator==(const iterator& rhs) const { return it_ == rhs.it_; } inline bool operator!=(const iterator& rhs) const { return it_ != rhs.it_; } inline operator const_iterator() const { return const_iterator(it_); } private: typename std::list::iterator it_; }; class const_iterator { public: typedef const_iterator self_type; typedef T value_type; typedef T& reference; typedef T* pointer; typedef std::bidirectional_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; explicit inline const_iterator(typename std::list::const_iterator it) : it_(it) {} inline self_type& operator++() { ++it_; return *this; } inline self_type operator++(int ignored) { self_type result(*this); ++(*this); return result; } inline self_type& operator--() { --it_; return *this; } inline self_type operator--(int ignored) { self_type result(*this); --(*this); return result; } inline const value_type& operator*() { return *it_; } inline const value_type* operator->() { return &(*it_); } inline bool operator==(const const_iterator& rhs) const { return it_ == rhs.it_; } inline bool operator!=(const const_iterator& rhs) const { return it_ != rhs.it_; } private: typename std::list::const_iterator it_; }; iterator begin() { return iterator(list_.begin()); } iterator end() { return iterator(list_.end()); } const_iterator begin() const { return const_iterator(list_.begin()); } const_iterator end() const { return const_iterator(list_.end()); } private: std::list list_; std::set set_; }; // Prevent instantiation of list_set> as the current // implementation would fail. // TODO(jsbell): Support scoped_ptr through specialization. template class list_set >; #endif // CONTENT_BROWSER_INDEXED_DB_LIST_SET_H_