]>
Commit | Line | Data |
---|---|---|
b37bf2e1 A |
1 | /* |
2 | * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. | |
ba379fdc | 3 | * Copyright (C) 2009 Google Inc. All rights reserved. |
b37bf2e1 A |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
15 | * its contributors may be used to endorse or promote products derived | |
16 | * from this software without specific prior written permission. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
19 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
21 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #ifndef WTF_Deque_h | |
31 | #define WTF_Deque_h | |
32 | ||
33 | // FIXME: Could move what Vector and Deque share into a separate file. | |
34 | // Deque doesn't actually use Vector. | |
35 | ||
14957cd0 | 36 | #include "PassTraits.h" |
b37bf2e1 A |
37 | #include "Vector.h" |
38 | ||
39 | namespace WTF { | |
40 | ||
14957cd0 A |
41 | template<typename T, size_t inlineCapacity> class DequeIteratorBase; |
42 | template<typename T, size_t inlineCapacity> class DequeIterator; | |
43 | template<typename T, size_t inlineCapacity> class DequeConstIterator; | |
44 | template<typename T, size_t inlineCapacity> class DequeReverseIterator; | |
45 | template<typename T, size_t inlineCapacity> class DequeConstReverseIterator; | |
b37bf2e1 | 46 | |
14957cd0 A |
47 | template<typename T, size_t inlineCapacity = 0> |
48 | class Deque { | |
49 | WTF_MAKE_FAST_ALLOCATED; | |
b37bf2e1 | 50 | public: |
14957cd0 A |
51 | typedef DequeIterator<T, inlineCapacity> iterator; |
52 | typedef DequeConstIterator<T, inlineCapacity> const_iterator; | |
53 | typedef DequeReverseIterator<T, inlineCapacity> reverse_iterator; | |
54 | typedef DequeConstReverseIterator<T, inlineCapacity> const_reverse_iterator; | |
55 | typedef PassTraits<T> Pass; | |
56 | typedef typename PassTraits<T>::PassType PassType; | |
b37bf2e1 A |
57 | |
58 | Deque(); | |
14957cd0 A |
59 | Deque(const Deque<T, inlineCapacity>&); |
60 | Deque& operator=(const Deque<T, inlineCapacity>&); | |
b37bf2e1 A |
61 | ~Deque(); |
62 | ||
14957cd0 | 63 | void swap(Deque<T, inlineCapacity>&); |
b37bf2e1 A |
64 | |
65 | size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } | |
66 | bool isEmpty() const { return m_start == m_end; } | |
67 | ||
68 | iterator begin() { return iterator(this, m_start); } | |
69 | iterator end() { return iterator(this, m_end); } | |
70 | const_iterator begin() const { return const_iterator(this, m_start); } | |
71 | const_iterator end() const { return const_iterator(this, m_end); } | |
72 | reverse_iterator rbegin() { return reverse_iterator(this, m_end); } | |
73 | reverse_iterator rend() { return reverse_iterator(this, m_start); } | |
74 | const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); } | |
75 | const_reverse_iterator rend() const { return const_reverse_iterator(this, m_start); } | |
76 | ||
77 | T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } | |
78 | const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } | |
14957cd0 | 79 | PassType takeFirst(); |
b37bf2e1 A |
80 | |
81 | template<typename U> void append(const U&); | |
82 | template<typename U> void prepend(const U&); | |
83 | void removeFirst(); | |
ba379fdc A |
84 | void remove(iterator&); |
85 | void remove(const_iterator&); | |
b37bf2e1 A |
86 | |
87 | void clear(); | |
88 | ||
ba379fdc A |
89 | template<typename Predicate> |
90 | iterator findIf(Predicate&); | |
91 | ||
b37bf2e1 | 92 | private: |
14957cd0 | 93 | friend class DequeIteratorBase<T, inlineCapacity>; |
b37bf2e1 | 94 | |
14957cd0 | 95 | typedef VectorBuffer<T, inlineCapacity> Buffer; |
b37bf2e1 | 96 | typedef VectorTypeOperations<T> TypeOperations; |
14957cd0 | 97 | typedef DequeIteratorBase<T, inlineCapacity> IteratorBase; |
b37bf2e1 | 98 | |
ba379fdc | 99 | void remove(size_t position); |
b37bf2e1 A |
100 | void invalidateIterators(); |
101 | void destroyAll(); | |
102 | void checkValidity() const; | |
103 | void checkIndexValidity(size_t) const; | |
104 | void expandCapacityIfNeeded(); | |
105 | void expandCapacity(); | |
106 | ||
107 | size_t m_start; | |
108 | size_t m_end; | |
109 | Buffer m_buffer; | |
110 | #ifndef NDEBUG | |
111 | mutable IteratorBase* m_iterators; | |
112 | #endif | |
113 | }; | |
114 | ||
14957cd0 | 115 | template<typename T, size_t inlineCapacity = 0> |
b37bf2e1 A |
116 | class DequeIteratorBase { |
117 | private: | |
14957cd0 | 118 | typedef DequeIteratorBase<T, inlineCapacity> Base; |
b37bf2e1 A |
119 | |
120 | protected: | |
121 | DequeIteratorBase(); | |
14957cd0 | 122 | DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t); |
b37bf2e1 A |
123 | DequeIteratorBase(const Base&); |
124 | Base& operator=(const Base&); | |
125 | ~DequeIteratorBase(); | |
126 | ||
127 | void assign(const Base& other) { *this = other; } | |
128 | ||
129 | void increment(); | |
130 | void decrement(); | |
131 | ||
132 | T* before() const; | |
133 | T* after() const; | |
134 | ||
135 | bool isEqual(const Base&) const; | |
136 | ||
137 | private: | |
138 | void addToIteratorsList(); | |
ba379fdc | 139 | void removeFromIteratorsList(); |
b37bf2e1 A |
140 | void checkValidity() const; |
141 | void checkValidity(const Base&) const; | |
142 | ||
14957cd0 | 143 | Deque<T, inlineCapacity>* m_deque; |
b37bf2e1 A |
144 | size_t m_index; |
145 | ||
14957cd0 | 146 | friend class Deque<T, inlineCapacity>; |
b37bf2e1 A |
147 | |
148 | #ifndef NDEBUG | |
149 | mutable DequeIteratorBase* m_next; | |
150 | mutable DequeIteratorBase* m_previous; | |
151 | #endif | |
152 | }; | |
153 | ||
14957cd0 A |
154 | template<typename T, size_t inlineCapacity = 0> |
155 | class DequeIterator : public DequeIteratorBase<T, inlineCapacity> { | |
b37bf2e1 | 156 | private: |
14957cd0 A |
157 | typedef DequeIteratorBase<T, inlineCapacity> Base; |
158 | typedef DequeIterator<T, inlineCapacity> Iterator; | |
b37bf2e1 A |
159 | |
160 | public: | |
14957cd0 | 161 | DequeIterator(Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
b37bf2e1 A |
162 | |
163 | DequeIterator(const Iterator& other) : Base(other) { } | |
164 | DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
165 | ||
166 | T& operator*() const { return *Base::after(); } | |
167 | T* operator->() const { return Base::after(); } | |
168 | ||
169 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
170 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
171 | ||
172 | Iterator& operator++() { Base::increment(); return *this; } | |
173 | // postfix ++ intentionally omitted | |
174 | Iterator& operator--() { Base::decrement(); return *this; } | |
175 | // postfix -- intentionally omitted | |
176 | }; | |
177 | ||
14957cd0 A |
178 | template<typename T, size_t inlineCapacity = 0> |
179 | class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> { | |
b37bf2e1 | 180 | private: |
14957cd0 A |
181 | typedef DequeIteratorBase<T, inlineCapacity> Base; |
182 | typedef DequeConstIterator<T, inlineCapacity> Iterator; | |
183 | typedef DequeIterator<T, inlineCapacity> NonConstIterator; | |
b37bf2e1 A |
184 | |
185 | public: | |
14957cd0 | 186 | DequeConstIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
b37bf2e1 A |
187 | |
188 | DequeConstIterator(const Iterator& other) : Base(other) { } | |
189 | DequeConstIterator(const NonConstIterator& other) : Base(other) { } | |
190 | DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
191 | DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } | |
192 | ||
193 | const T& operator*() const { return *Base::after(); } | |
194 | const T* operator->() const { return Base::after(); } | |
195 | ||
196 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
197 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
198 | ||
199 | Iterator& operator++() { Base::increment(); return *this; } | |
200 | // postfix ++ intentionally omitted | |
201 | Iterator& operator--() { Base::decrement(); return *this; } | |
202 | // postfix -- intentionally omitted | |
203 | }; | |
204 | ||
14957cd0 A |
205 | template<typename T, size_t inlineCapacity = 0> |
206 | class DequeReverseIterator : public DequeIteratorBase<T, inlineCapacity> { | |
b37bf2e1 | 207 | private: |
14957cd0 A |
208 | typedef DequeIteratorBase<T, inlineCapacity> Base; |
209 | typedef DequeReverseIterator<T, inlineCapacity> Iterator; | |
b37bf2e1 A |
210 | |
211 | public: | |
14957cd0 | 212 | DequeReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
b37bf2e1 A |
213 | |
214 | DequeReverseIterator(const Iterator& other) : Base(other) { } | |
215 | DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
216 | ||
217 | T& operator*() const { return *Base::before(); } | |
218 | T* operator->() const { return Base::before(); } | |
219 | ||
220 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
221 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
222 | ||
223 | Iterator& operator++() { Base::decrement(); return *this; } | |
224 | // postfix ++ intentionally omitted | |
225 | Iterator& operator--() { Base::increment(); return *this; } | |
226 | // postfix -- intentionally omitted | |
227 | }; | |
228 | ||
14957cd0 A |
229 | template<typename T, size_t inlineCapacity = 0> |
230 | class DequeConstReverseIterator : public DequeIteratorBase<T, inlineCapacity> { | |
b37bf2e1 | 231 | private: |
14957cd0 A |
232 | typedef DequeIteratorBase<T, inlineCapacity> Base; |
233 | typedef DequeConstReverseIterator<T, inlineCapacity> Iterator; | |
234 | typedef DequeReverseIterator<T, inlineCapacity> NonConstIterator; | |
b37bf2e1 A |
235 | |
236 | public: | |
14957cd0 | 237 | DequeConstReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } |
b37bf2e1 A |
238 | |
239 | DequeConstReverseIterator(const Iterator& other) : Base(other) { } | |
240 | DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { } | |
241 | DequeConstReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
242 | DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } | |
243 | ||
244 | const T& operator*() const { return *Base::before(); } | |
245 | const T* operator->() const { return Base::before(); } | |
246 | ||
247 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
248 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
249 | ||
250 | Iterator& operator++() { Base::decrement(); return *this; } | |
251 | // postfix ++ intentionally omitted | |
252 | Iterator& operator--() { Base::increment(); return *this; } | |
253 | // postfix -- intentionally omitted | |
254 | }; | |
255 | ||
256 | #ifdef NDEBUG | |
14957cd0 A |
257 | template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkValidity() const { } |
258 | template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkIndexValidity(size_t) const { } | |
259 | template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::invalidateIterators() { } | |
b37bf2e1 | 260 | #else |
14957cd0 A |
261 | template<typename T, size_t inlineCapacity> |
262 | void Deque<T, inlineCapacity>::checkValidity() const | |
b37bf2e1 | 263 | { |
14957cd0 A |
264 | // In this implementation a capacity of 1 would confuse append() and |
265 | // other places that assume the index after capacity - 1 is 0. | |
266 | ASSERT(m_buffer.capacity() != 1); | |
267 | ||
b37bf2e1 A |
268 | if (!m_buffer.capacity()) { |
269 | ASSERT(!m_start); | |
270 | ASSERT(!m_end); | |
271 | } else { | |
272 | ASSERT(m_start < m_buffer.capacity()); | |
273 | ASSERT(m_end < m_buffer.capacity()); | |
274 | } | |
275 | } | |
276 | ||
14957cd0 A |
277 | template<typename T, size_t inlineCapacity> |
278 | void Deque<T, inlineCapacity>::checkIndexValidity(size_t index) const | |
b37bf2e1 A |
279 | { |
280 | ASSERT(index <= m_buffer.capacity()); | |
281 | if (m_start <= m_end) { | |
282 | ASSERT(index >= m_start); | |
283 | ASSERT(index <= m_end); | |
284 | } else { | |
285 | ASSERT(index >= m_start || index <= m_end); | |
286 | } | |
287 | } | |
288 | ||
14957cd0 A |
289 | template<typename T, size_t inlineCapacity> |
290 | void Deque<T, inlineCapacity>::invalidateIterators() | |
b37bf2e1 A |
291 | { |
292 | IteratorBase* next; | |
293 | for (IteratorBase* p = m_iterators; p; p = next) { | |
294 | next = p->m_next; | |
295 | p->m_deque = 0; | |
296 | p->m_next = 0; | |
297 | p->m_previous = 0; | |
298 | } | |
299 | m_iterators = 0; | |
300 | } | |
301 | #endif | |
302 | ||
14957cd0 A |
303 | template<typename T, size_t inlineCapacity> |
304 | inline Deque<T, inlineCapacity>::Deque() | |
b37bf2e1 A |
305 | : m_start(0) |
306 | , m_end(0) | |
307 | #ifndef NDEBUG | |
308 | , m_iterators(0) | |
309 | #endif | |
310 | { | |
311 | checkValidity(); | |
312 | } | |
313 | ||
14957cd0 A |
314 | template<typename T, size_t inlineCapacity> |
315 | inline Deque<T, inlineCapacity>::Deque(const Deque<T, inlineCapacity>& other) | |
b37bf2e1 A |
316 | : m_start(other.m_start) |
317 | , m_end(other.m_end) | |
318 | , m_buffer(other.m_buffer.capacity()) | |
319 | #ifndef NDEBUG | |
320 | , m_iterators(0) | |
321 | #endif | |
322 | { | |
323 | const T* otherBuffer = other.m_buffer.buffer(); | |
324 | if (m_start <= m_end) | |
325 | TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start); | |
326 | else { | |
327 | TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer()); | |
328 | TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start); | |
329 | } | |
330 | } | |
331 | ||
14957cd0 A |
332 | template<typename T, size_t inlineCapacity> |
333 | void deleteAllValues(const Deque<T, inlineCapacity>& collection) | |
9dae56ea | 334 | { |
14957cd0 | 335 | typedef typename Deque<T, inlineCapacity>::const_iterator iterator; |
9dae56ea A |
336 | iterator end = collection.end(); |
337 | for (iterator it = collection.begin(); it != end; ++it) | |
338 | delete *it; | |
339 | } | |
340 | ||
14957cd0 A |
341 | template<typename T, size_t inlineCapacity> |
342 | inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other) | |
b37bf2e1 | 343 | { |
14957cd0 A |
344 | // FIXME: This is inefficient if we're using an inline buffer and T is |
345 | // expensive to copy since it will copy the buffer twice instead of once. | |
b37bf2e1 A |
346 | Deque<T> copy(other); |
347 | swap(copy); | |
348 | return *this; | |
349 | } | |
350 | ||
14957cd0 A |
351 | template<typename T, size_t inlineCapacity> |
352 | inline void Deque<T, inlineCapacity>::destroyAll() | |
b37bf2e1 A |
353 | { |
354 | if (m_start <= m_end) | |
355 | TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); | |
356 | else { | |
357 | TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); | |
358 | TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity()); | |
359 | } | |
360 | } | |
361 | ||
14957cd0 A |
362 | template<typename T, size_t inlineCapacity> |
363 | inline Deque<T, inlineCapacity>::~Deque() | |
b37bf2e1 A |
364 | { |
365 | checkValidity(); | |
366 | invalidateIterators(); | |
367 | destroyAll(); | |
368 | } | |
369 | ||
14957cd0 A |
370 | template<typename T, size_t inlineCapacity> |
371 | inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other) | |
b37bf2e1 A |
372 | { |
373 | checkValidity(); | |
374 | other.checkValidity(); | |
375 | invalidateIterators(); | |
376 | std::swap(m_start, other.m_start); | |
377 | std::swap(m_end, other.m_end); | |
378 | m_buffer.swap(other.m_buffer); | |
379 | checkValidity(); | |
380 | other.checkValidity(); | |
381 | } | |
382 | ||
14957cd0 A |
383 | template<typename T, size_t inlineCapacity> |
384 | inline void Deque<T, inlineCapacity>::clear() | |
b37bf2e1 A |
385 | { |
386 | checkValidity(); | |
387 | invalidateIterators(); | |
388 | destroyAll(); | |
389 | m_start = 0; | |
390 | m_end = 0; | |
391 | checkValidity(); | |
392 | } | |
393 | ||
14957cd0 | 394 | template<typename T, size_t inlineCapacity> |
ba379fdc | 395 | template<typename Predicate> |
14957cd0 | 396 | inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate) |
ba379fdc A |
397 | { |
398 | iterator end_iterator = end(); | |
399 | for (iterator it = begin(); it != end_iterator; ++it) { | |
400 | if (predicate(*it)) | |
401 | return it; | |
402 | } | |
403 | return end_iterator; | |
404 | } | |
405 | ||
14957cd0 A |
406 | template<typename T, size_t inlineCapacity> |
407 | inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded() | |
b37bf2e1 A |
408 | { |
409 | if (m_start) { | |
410 | if (m_end + 1 != m_start) | |
411 | return; | |
412 | } else if (m_end) { | |
413 | if (m_end != m_buffer.capacity() - 1) | |
414 | return; | |
415 | } else if (m_buffer.capacity()) | |
416 | return; | |
417 | ||
418 | expandCapacity(); | |
419 | } | |
420 | ||
14957cd0 A |
421 | template<typename T, size_t inlineCapacity> |
422 | void Deque<T, inlineCapacity>::expandCapacity() | |
b37bf2e1 A |
423 | { |
424 | checkValidity(); | |
425 | size_t oldCapacity = m_buffer.capacity(); | |
426 | size_t newCapacity = max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1); | |
427 | T* oldBuffer = m_buffer.buffer(); | |
428 | m_buffer.allocateBuffer(newCapacity); | |
429 | if (m_start <= m_end) | |
430 | TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start); | |
431 | else { | |
432 | TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); | |
433 | size_t newStart = newCapacity - (oldCapacity - m_start); | |
434 | TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart); | |
435 | m_start = newStart; | |
436 | } | |
437 | m_buffer.deallocateBuffer(oldBuffer); | |
438 | checkValidity(); | |
439 | } | |
440 | ||
14957cd0 A |
441 | template<typename T, size_t inlineCapacity> |
442 | inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeFirst() | |
443 | { | |
444 | T oldFirst = Pass::transfer(first()); | |
445 | removeFirst(); | |
446 | return Pass::transfer(oldFirst); | |
447 | } | |
448 | ||
449 | template<typename T, size_t inlineCapacity> template<typename U> | |
450 | inline void Deque<T, inlineCapacity>::append(const U& value) | |
b37bf2e1 A |
451 | { |
452 | checkValidity(); | |
453 | expandCapacityIfNeeded(); | |
454 | new (&m_buffer.buffer()[m_end]) T(value); | |
455 | if (m_end == m_buffer.capacity() - 1) | |
456 | m_end = 0; | |
457 | else | |
458 | ++m_end; | |
459 | checkValidity(); | |
460 | } | |
461 | ||
14957cd0 A |
462 | template<typename T, size_t inlineCapacity> template<typename U> |
463 | inline void Deque<T, inlineCapacity>::prepend(const U& value) | |
b37bf2e1 A |
464 | { |
465 | checkValidity(); | |
466 | expandCapacityIfNeeded(); | |
467 | if (!m_start) | |
468 | m_start = m_buffer.capacity() - 1; | |
469 | else | |
470 | --m_start; | |
471 | new (&m_buffer.buffer()[m_start]) T(value); | |
472 | checkValidity(); | |
473 | } | |
474 | ||
14957cd0 A |
475 | template<typename T, size_t inlineCapacity> |
476 | inline void Deque<T, inlineCapacity>::removeFirst() | |
b37bf2e1 A |
477 | { |
478 | checkValidity(); | |
479 | invalidateIterators(); | |
480 | ASSERT(!isEmpty()); | |
481 | TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]); | |
482 | if (m_start == m_buffer.capacity() - 1) | |
483 | m_start = 0; | |
484 | else | |
485 | ++m_start; | |
486 | checkValidity(); | |
487 | } | |
488 | ||
14957cd0 A |
489 | template<typename T, size_t inlineCapacity> |
490 | inline void Deque<T, inlineCapacity>::remove(iterator& it) | |
ba379fdc A |
491 | { |
492 | it.checkValidity(); | |
493 | remove(it.m_index); | |
494 | } | |
495 | ||
14957cd0 A |
496 | template<typename T, size_t inlineCapacity> |
497 | inline void Deque<T, inlineCapacity>::remove(const_iterator& it) | |
ba379fdc A |
498 | { |
499 | it.checkValidity(); | |
500 | remove(it.m_index); | |
501 | } | |
502 | ||
14957cd0 A |
503 | template<typename T, size_t inlineCapacity> |
504 | inline void Deque<T, inlineCapacity>::remove(size_t position) | |
ba379fdc A |
505 | { |
506 | if (position == m_end) | |
507 | return; | |
508 | ||
509 | checkValidity(); | |
510 | invalidateIterators(); | |
511 | ||
512 | T* buffer = m_buffer.buffer(); | |
513 | TypeOperations::destruct(&buffer[position], &buffer[position + 1]); | |
514 | ||
515 | // Find which segment of the circular buffer contained the remove element, and only move elements in that part. | |
516 | if (position >= m_start) { | |
517 | TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1); | |
518 | m_start = (m_start + 1) % m_buffer.capacity(); | |
519 | } else { | |
520 | TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position); | |
521 | m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); | |
522 | } | |
523 | checkValidity(); | |
524 | } | |
525 | ||
b37bf2e1 | 526 | #ifdef NDEBUG |
14957cd0 A |
527 | template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { } |
528 | template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity(const DequeIteratorBase<T, inlineCapacity>&) const { } | |
529 | template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { } | |
530 | template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { } | |
b37bf2e1 | 531 | #else |
14957cd0 A |
532 | template<typename T, size_t inlineCapacity> |
533 | void DequeIteratorBase<T, inlineCapacity>::checkValidity() const | |
b37bf2e1 A |
534 | { |
535 | ASSERT(m_deque); | |
536 | m_deque->checkIndexValidity(m_index); | |
537 | } | |
538 | ||
14957cd0 A |
539 | template<typename T, size_t inlineCapacity> |
540 | void DequeIteratorBase<T, inlineCapacity>::checkValidity(const Base& other) const | |
b37bf2e1 A |
541 | { |
542 | checkValidity(); | |
543 | other.checkValidity(); | |
544 | ASSERT(m_deque == other.m_deque); | |
545 | } | |
546 | ||
14957cd0 A |
547 | template<typename T, size_t inlineCapacity> |
548 | void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() | |
b37bf2e1 A |
549 | { |
550 | if (!m_deque) | |
551 | m_next = 0; | |
552 | else { | |
553 | m_next = m_deque->m_iterators; | |
554 | m_deque->m_iterators = this; | |
555 | if (m_next) | |
556 | m_next->m_previous = this; | |
557 | } | |
558 | m_previous = 0; | |
559 | } | |
ba379fdc | 560 | |
14957cd0 A |
561 | template<typename T, size_t inlineCapacity> |
562 | void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() | |
ba379fdc A |
563 | { |
564 | if (!m_deque) { | |
565 | ASSERT(!m_next); | |
566 | ASSERT(!m_previous); | |
567 | } else { | |
568 | if (m_next) { | |
569 | ASSERT(m_next->m_previous == this); | |
570 | m_next->m_previous = m_previous; | |
571 | } | |
572 | if (m_previous) { | |
573 | ASSERT(m_deque->m_iterators != this); | |
574 | ASSERT(m_previous->m_next == this); | |
575 | m_previous->m_next = m_next; | |
576 | } else { | |
577 | ASSERT(m_deque->m_iterators == this); | |
578 | m_deque->m_iterators = m_next; | |
579 | } | |
580 | } | |
581 | m_next = 0; | |
582 | m_previous = 0; | |
583 | } | |
b37bf2e1 A |
584 | #endif |
585 | ||
14957cd0 A |
586 | template<typename T, size_t inlineCapacity> |
587 | inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase() | |
b37bf2e1 A |
588 | : m_deque(0) |
589 | { | |
590 | } | |
591 | ||
14957cd0 A |
592 | template<typename T, size_t inlineCapacity> |
593 | inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index) | |
594 | : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque)) | |
b37bf2e1 A |
595 | , m_index(index) |
596 | { | |
597 | addToIteratorsList(); | |
598 | checkValidity(); | |
599 | } | |
600 | ||
14957cd0 A |
601 | template<typename T, size_t inlineCapacity> |
602 | inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Base& other) | |
b37bf2e1 A |
603 | : m_deque(other.m_deque) |
604 | , m_index(other.m_index) | |
605 | { | |
606 | addToIteratorsList(); | |
607 | checkValidity(); | |
608 | } | |
609 | ||
14957cd0 A |
610 | template<typename T, size_t inlineCapacity> |
611 | inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const Base& other) | |
ba379fdc A |
612 | { |
613 | checkValidity(); | |
614 | other.checkValidity(); | |
615 | removeFromIteratorsList(); | |
616 | ||
617 | m_deque = other.m_deque; | |
618 | m_index = other.m_index; | |
619 | addToIteratorsList(); | |
620 | checkValidity(); | |
621 | return *this; | |
622 | } | |
623 | ||
14957cd0 A |
624 | template<typename T, size_t inlineCapacity> |
625 | inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase() | |
b37bf2e1 A |
626 | { |
627 | #ifndef NDEBUG | |
ba379fdc | 628 | removeFromIteratorsList(); |
b37bf2e1 | 629 | m_deque = 0; |
b37bf2e1 A |
630 | #endif |
631 | } | |
632 | ||
14957cd0 A |
633 | template<typename T, size_t inlineCapacity> |
634 | inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const Base& other) const | |
b37bf2e1 A |
635 | { |
636 | checkValidity(other); | |
637 | return m_index == other.m_index; | |
638 | } | |
639 | ||
14957cd0 A |
640 | template<typename T, size_t inlineCapacity> |
641 | inline void DequeIteratorBase<T, inlineCapacity>::increment() | |
b37bf2e1 A |
642 | { |
643 | checkValidity(); | |
644 | ASSERT(m_index != m_deque->m_end); | |
645 | ASSERT(m_deque->m_buffer.capacity()); | |
646 | if (m_index == m_deque->m_buffer.capacity() - 1) | |
647 | m_index = 0; | |
648 | else | |
649 | ++m_index; | |
650 | checkValidity(); | |
651 | } | |
652 | ||
14957cd0 A |
653 | template<typename T, size_t inlineCapacity> |
654 | inline void DequeIteratorBase<T, inlineCapacity>::decrement() | |
b37bf2e1 A |
655 | { |
656 | checkValidity(); | |
657 | ASSERT(m_index != m_deque->m_start); | |
658 | ASSERT(m_deque->m_buffer.capacity()); | |
659 | if (!m_index) | |
660 | m_index = m_deque->m_buffer.capacity() - 1; | |
661 | else | |
662 | --m_index; | |
663 | checkValidity(); | |
664 | } | |
665 | ||
14957cd0 A |
666 | template<typename T, size_t inlineCapacity> |
667 | inline T* DequeIteratorBase<T, inlineCapacity>::after() const | |
b37bf2e1 A |
668 | { |
669 | checkValidity(); | |
670 | ASSERT(m_index != m_deque->m_end); | |
671 | return &m_deque->m_buffer.buffer()[m_index]; | |
672 | } | |
673 | ||
14957cd0 A |
674 | template<typename T, size_t inlineCapacity> |
675 | inline T* DequeIteratorBase<T, inlineCapacity>::before() const | |
b37bf2e1 A |
676 | { |
677 | checkValidity(); | |
678 | ASSERT(m_index != m_deque->m_start); | |
679 | if (!m_index) | |
680 | return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; | |
681 | return &m_deque->m_buffer.buffer()[m_index - 1]; | |
682 | } | |
683 | ||
684 | } // namespace WTF | |
685 | ||
686 | using WTF::Deque; | |
687 | ||
688 | #endif // WTF_Deque_h |