summaryrefslogtreecommitdiff
path: root/chromium/cc/base/scoped_ptr_deque.h
blob: cb4adfc15be5273d49a1966708effee66b6873a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2012 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 CC_BASE_SCOPED_PTR_DEQUE_H_
#define CC_BASE_SCOPED_PTR_DEQUE_H_

#include <algorithm>
#include <deque>

#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"

namespace cc {

// This type acts like a deque<scoped_ptr> based on top of std::deque. The
// ScopedPtrDeque has ownership of all elements in the deque.
template <typename T>
class ScopedPtrDeque {
 public:
  typedef typename std::deque<T*>::const_iterator const_iterator;
  typedef typename std::deque<T*>::reverse_iterator reverse_iterator;
  typedef typename std::deque<T*>::const_reverse_iterator
      const_reverse_iterator;

#if defined(OS_ANDROID)
  // On Android the iterator is not a class, so we can't block assignment.
  typedef typename std::deque<T*>::iterator iterator;
#else
  // Ban setting values on the iterator directly. New pointers must be passed
  // to methods on the ScopedPtrDeque class to appear in the deque.
  class iterator : public std::deque<T*>::iterator {
   public:
    explicit iterator(const typename std::deque<T*>::iterator& other)
        : std::deque<T*>::iterator(other) {}
    T* const& operator*() { return std::deque<T*>::iterator::operator*(); }
  };
#endif

  ScopedPtrDeque() {}

  ~ScopedPtrDeque() { clear(); }

  size_t size() const {
    return data_.size();
  }

  T* at(size_t index) const {
    DCHECK(index < size());
    return data_[index];
  }

  T* operator[](size_t index) const {
    return at(index);
  }

  T* front() const {
    DCHECK(!empty());
    return at(0);
  }

  T* back() const {
    DCHECK(!empty());
    return at(size() - 1);
  }

  bool empty() const {
    return data_.empty();
  }

  scoped_ptr<T> take_front() {
    scoped_ptr<T> ret(front());
    data_.pop_front();
    return ret.Pass();
  }

  scoped_ptr<T> take_back() {
    scoped_ptr<T> ret(back());
    data_.pop_back();
    return ret.Pass();
  }

  void clear() {
    STLDeleteElements(&data_);
  }

  void push_front(scoped_ptr<T> item) {
    data_.push_front(item.release());
  }

  void push_back(scoped_ptr<T> item) {
    data_.push_back(item.release());
  }

  void insert(iterator position, scoped_ptr<T> item) {
    DCHECK(position <= end());
    data_.insert(position, item.release());
  }

  scoped_ptr<T> take(iterator position) {
    DCHECK(position < end());
    scoped_ptr<T> ret(*position);
    data_.erase(position);
    return ret.Pass();
  }

  void swap(iterator a, iterator b) {
    DCHECK(a < end());
    DCHECK(b < end());
    if (a == end() || b == end() || a == b)
      return;
    typename std::deque<T*>::iterator writable_a = a;
    typename std::deque<T*>::iterator writable_b = b;
    std::swap(*writable_a, *writable_b);
  }

  iterator begin() { return static_cast<iterator>(data_.begin()); }
  const_iterator begin() const { return data_.begin(); }
  iterator end() { return static_cast<iterator>(data_.end()); }
  const_iterator end() const { return data_.end(); }

  reverse_iterator rbegin() { return data_.rbegin(); }
  const_reverse_iterator rbegin() const { return data_.rbegin(); }
  reverse_iterator rend() { return data_.rend(); }
  const_reverse_iterator rend() const { return data_.rend(); }

 private:
  std::deque<T*> data_;

  DISALLOW_COPY_AND_ASSIGN(ScopedPtrDeque);
};

}  // namespace cc

#endif  // CC_BASE_SCOPED_PTR_DEQUE_H_