2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
33 // FIXME: Could move what Vector and Deque share into a separate file.
34 // Deque doesn't actually use Vector.
36 #include "PassTraits.h"
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
;
47 template<typename T
, size_t inlineCapacity
= 0>
49 WTF_MAKE_FAST_ALLOCATED
;
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
;
59 Deque(const Deque
<T
, inlineCapacity
>&);
60 Deque
& operator=(const Deque
<T
, inlineCapacity
>&);
63 void swap(Deque
<T
, inlineCapacity
>&);
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
; }
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
); }
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
]; }
81 template<typename U
> void append(const U
&);
82 template<typename U
> void prepend(const U
&);
84 void remove(iterator
&);
85 void remove(const_iterator
&);
89 template<typename Predicate
>
90 iterator
findIf(Predicate
&);
93 friend class DequeIteratorBase
<T
, inlineCapacity
>;
95 typedef VectorBuffer
<T
, inlineCapacity
> Buffer
;
96 typedef VectorTypeOperations
<T
> TypeOperations
;
97 typedef DequeIteratorBase
<T
, inlineCapacity
> IteratorBase
;
99 void remove(size_t position
);
100 void invalidateIterators();
102 void checkValidity() const;
103 void checkIndexValidity(size_t) const;
104 void expandCapacityIfNeeded();
105 void expandCapacity();
111 mutable IteratorBase
* m_iterators
;
115 template<typename T
, size_t inlineCapacity
= 0>
116 class DequeIteratorBase
{
118 typedef DequeIteratorBase
<T
, inlineCapacity
> Base
;
122 DequeIteratorBase(const Deque
<T
, inlineCapacity
>*, size_t);
123 DequeIteratorBase(const Base
&);
124 Base
& operator=(const Base
&);
125 ~DequeIteratorBase();
127 void assign(const Base
& other
) { *this = other
; }
135 bool isEqual(const Base
&) const;
138 void addToIteratorsList();
139 void removeFromIteratorsList();
140 void checkValidity() const;
141 void checkValidity(const Base
&) const;
143 Deque
<T
, inlineCapacity
>* m_deque
;
146 friend class Deque
<T
, inlineCapacity
>;
149 mutable DequeIteratorBase
* m_next
;
150 mutable DequeIteratorBase
* m_previous
;
154 template<typename T
, size_t inlineCapacity
= 0>
155 class DequeIterator
: public DequeIteratorBase
<T
, inlineCapacity
> {
157 typedef DequeIteratorBase
<T
, inlineCapacity
> Base
;
158 typedef DequeIterator
<T
, inlineCapacity
> Iterator
;
161 DequeIterator(Deque
<T
, inlineCapacity
>* deque
, size_t index
) : Base(deque
, index
) { }
163 DequeIterator(const Iterator
& other
) : Base(other
) { }
164 DequeIterator
& operator=(const Iterator
& other
) { Base::assign(other
); return *this; }
166 T
& operator*() const { return *Base::after(); }
167 T
* operator->() const { return Base::after(); }
169 bool operator==(const Iterator
& other
) const { return Base::isEqual(other
); }
170 bool operator!=(const Iterator
& other
) const { return !Base::isEqual(other
); }
172 Iterator
& operator++() { Base::increment(); return *this; }
173 // postfix ++ intentionally omitted
174 Iterator
& operator--() { Base::decrement(); return *this; }
175 // postfix -- intentionally omitted
178 template<typename T
, size_t inlineCapacity
= 0>
179 class DequeConstIterator
: public DequeIteratorBase
<T
, inlineCapacity
> {
181 typedef DequeIteratorBase
<T
, inlineCapacity
> Base
;
182 typedef DequeConstIterator
<T
, inlineCapacity
> Iterator
;
183 typedef DequeIterator
<T
, inlineCapacity
> NonConstIterator
;
186 DequeConstIterator(const Deque
<T
, inlineCapacity
>* deque
, size_t index
) : Base(deque
, index
) { }
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; }
193 const T
& operator*() const { return *Base::after(); }
194 const T
* operator->() const { return Base::after(); }
196 bool operator==(const Iterator
& other
) const { return Base::isEqual(other
); }
197 bool operator!=(const Iterator
& other
) const { return !Base::isEqual(other
); }
199 Iterator
& operator++() { Base::increment(); return *this; }
200 // postfix ++ intentionally omitted
201 Iterator
& operator--() { Base::decrement(); return *this; }
202 // postfix -- intentionally omitted
205 template<typename T
, size_t inlineCapacity
= 0>
206 class DequeReverseIterator
: public DequeIteratorBase
<T
, inlineCapacity
> {
208 typedef DequeIteratorBase
<T
, inlineCapacity
> Base
;
209 typedef DequeReverseIterator
<T
, inlineCapacity
> Iterator
;
212 DequeReverseIterator(const Deque
<T
, inlineCapacity
>* deque
, size_t index
) : Base(deque
, index
) { }
214 DequeReverseIterator(const Iterator
& other
) : Base(other
) { }
215 DequeReverseIterator
& operator=(const Iterator
& other
) { Base::assign(other
); return *this; }
217 T
& operator*() const { return *Base::before(); }
218 T
* operator->() const { return Base::before(); }
220 bool operator==(const Iterator
& other
) const { return Base::isEqual(other
); }
221 bool operator!=(const Iterator
& other
) const { return !Base::isEqual(other
); }
223 Iterator
& operator++() { Base::decrement(); return *this; }
224 // postfix ++ intentionally omitted
225 Iterator
& operator--() { Base::increment(); return *this; }
226 // postfix -- intentionally omitted
229 template<typename T
, size_t inlineCapacity
= 0>
230 class DequeConstReverseIterator
: public DequeIteratorBase
<T
, inlineCapacity
> {
232 typedef DequeIteratorBase
<T
, inlineCapacity
> Base
;
233 typedef DequeConstReverseIterator
<T
, inlineCapacity
> Iterator
;
234 typedef DequeReverseIterator
<T
, inlineCapacity
> NonConstIterator
;
237 DequeConstReverseIterator(const Deque
<T
, inlineCapacity
>* deque
, size_t index
) : Base(deque
, index
) { }
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; }
244 const T
& operator*() const { return *Base::before(); }
245 const T
* operator->() const { return Base::before(); }
247 bool operator==(const Iterator
& other
) const { return Base::isEqual(other
); }
248 bool operator!=(const Iterator
& other
) const { return !Base::isEqual(other
); }
250 Iterator
& operator++() { Base::decrement(); return *this; }
251 // postfix ++ intentionally omitted
252 Iterator
& operator--() { Base::increment(); return *this; }
253 // postfix -- intentionally omitted
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() { }
261 template<typename T
, size_t inlineCapacity
>
262 void Deque
<T
, inlineCapacity
>::checkValidity() const
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);
268 if (!m_buffer
.capacity()) {
272 ASSERT(m_start
< m_buffer
.capacity());
273 ASSERT(m_end
< m_buffer
.capacity());
277 template<typename T
, size_t inlineCapacity
>
278 void Deque
<T
, inlineCapacity
>::checkIndexValidity(size_t index
) const
280 ASSERT(index
<= m_buffer
.capacity());
281 if (m_start
<= m_end
) {
282 ASSERT(index
>= m_start
);
283 ASSERT(index
<= m_end
);
285 ASSERT(index
>= m_start
|| index
<= m_end
);
289 template<typename T
, size_t inlineCapacity
>
290 void Deque
<T
, inlineCapacity
>::invalidateIterators()
293 for (IteratorBase
* p
= m_iterators
; p
; p
= next
) {
303 template<typename T
, size_t inlineCapacity
>
304 inline Deque
<T
, inlineCapacity
>::Deque()
314 template<typename T
, size_t inlineCapacity
>
315 inline Deque
<T
, inlineCapacity
>::Deque(const Deque
<T
, inlineCapacity
>& other
)
316 : m_start(other
.m_start
)
318 , m_buffer(other
.m_buffer
.capacity())
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
);
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
);
332 template<typename T
, size_t inlineCapacity
>
333 void deleteAllValues(const Deque
<T
, inlineCapacity
>& collection
)
335 typedef typename Deque
<T
, inlineCapacity
>::const_iterator iterator
;
336 iterator end
= collection
.end();
337 for (iterator it
= collection
.begin(); it
!= end
; ++it
)
341 template<typename T
, size_t inlineCapacity
>
342 inline Deque
<T
, inlineCapacity
>& Deque
<T
, inlineCapacity
>::operator=(const Deque
<T
, inlineCapacity
>& other
)
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.
346 Deque
<T
> copy(other
);
351 template<typename T
, size_t inlineCapacity
>
352 inline void Deque
<T
, inlineCapacity
>::destroyAll()
354 if (m_start
<= m_end
)
355 TypeOperations::destruct(m_buffer
.buffer() + m_start
, m_buffer
.buffer() + m_end
);
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());
362 template<typename T
, size_t inlineCapacity
>
363 inline Deque
<T
, inlineCapacity
>::~Deque()
366 invalidateIterators();
370 template<typename T
, size_t inlineCapacity
>
371 inline void Deque
<T
, inlineCapacity
>::swap(Deque
<T
, inlineCapacity
>& other
)
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
);
380 other
.checkValidity();
383 template<typename T
, size_t inlineCapacity
>
384 inline void Deque
<T
, inlineCapacity
>::clear()
387 invalidateIterators();
394 template<typename T
, size_t inlineCapacity
>
395 template<typename Predicate
>
396 inline DequeIterator
<T
, inlineCapacity
> Deque
<T
, inlineCapacity
>::findIf(Predicate
& predicate
)
398 iterator end_iterator
= end();
399 for (iterator it
= begin(); it
!= end_iterator
; ++it
) {
406 template<typename T
, size_t inlineCapacity
>
407 inline void Deque
<T
, inlineCapacity
>::expandCapacityIfNeeded()
410 if (m_end
+ 1 != m_start
)
413 if (m_end
!= m_buffer
.capacity() - 1)
415 } else if (m_buffer
.capacity())
421 template<typename T
, size_t inlineCapacity
>
422 void Deque
<T
, inlineCapacity
>::expandCapacity()
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
);
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
);
437 m_buffer
.deallocateBuffer(oldBuffer
);
441 template<typename T
, size_t inlineCapacity
>
442 inline typename Deque
<T
, inlineCapacity
>::PassType Deque
<T
, inlineCapacity
>::takeFirst()
444 T oldFirst
= Pass::transfer(first());
446 return Pass::transfer(oldFirst
);
449 template<typename T
, size_t inlineCapacity
> template<typename U
>
450 inline void Deque
<T
, inlineCapacity
>::append(const U
& value
)
453 expandCapacityIfNeeded();
454 new (&m_buffer
.buffer()[m_end
]) T(value
);
455 if (m_end
== m_buffer
.capacity() - 1)
462 template<typename T
, size_t inlineCapacity
> template<typename U
>
463 inline void Deque
<T
, inlineCapacity
>::prepend(const U
& value
)
466 expandCapacityIfNeeded();
468 m_start
= m_buffer
.capacity() - 1;
471 new (&m_buffer
.buffer()[m_start
]) T(value
);
475 template<typename T
, size_t inlineCapacity
>
476 inline void Deque
<T
, inlineCapacity
>::removeFirst()
479 invalidateIterators();
481 TypeOperations::destruct(&m_buffer
.buffer()[m_start
], &m_buffer
.buffer()[m_start
+ 1]);
482 if (m_start
== m_buffer
.capacity() - 1)
489 template<typename T
, size_t inlineCapacity
>
490 inline void Deque
<T
, inlineCapacity
>::remove(iterator
& it
)
496 template<typename T
, size_t inlineCapacity
>
497 inline void Deque
<T
, inlineCapacity
>::remove(const_iterator
& it
)
503 template<typename T
, size_t inlineCapacity
>
504 inline void Deque
<T
, inlineCapacity
>::remove(size_t position
)
506 if (position
== m_end
)
510 invalidateIterators();
512 T
* buffer
= m_buffer
.buffer();
513 TypeOperations::destruct(&buffer
[position
], &buffer
[position
+ 1]);
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();
520 TypeOperations::moveOverlapping(buffer
+ position
+ 1, buffer
+ m_end
, buffer
+ position
);
521 m_end
= (m_end
- 1 + m_buffer
.capacity()) % m_buffer
.capacity();
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() { }
532 template<typename T
, size_t inlineCapacity
>
533 void DequeIteratorBase
<T
, inlineCapacity
>::checkValidity() const
536 m_deque
->checkIndexValidity(m_index
);
539 template<typename T
, size_t inlineCapacity
>
540 void DequeIteratorBase
<T
, inlineCapacity
>::checkValidity(const Base
& other
) const
543 other
.checkValidity();
544 ASSERT(m_deque
== other
.m_deque
);
547 template<typename T
, size_t inlineCapacity
>
548 void DequeIteratorBase
<T
, inlineCapacity
>::addToIteratorsList()
553 m_next
= m_deque
->m_iterators
;
554 m_deque
->m_iterators
= this;
556 m_next
->m_previous
= this;
561 template<typename T
, size_t inlineCapacity
>
562 void DequeIteratorBase
<T
, inlineCapacity
>::removeFromIteratorsList()
569 ASSERT(m_next
->m_previous
== this);
570 m_next
->m_previous
= m_previous
;
573 ASSERT(m_deque
->m_iterators
!= this);
574 ASSERT(m_previous
->m_next
== this);
575 m_previous
->m_next
= m_next
;
577 ASSERT(m_deque
->m_iterators
== this);
578 m_deque
->m_iterators
= m_next
;
586 template<typename T
, size_t inlineCapacity
>
587 inline DequeIteratorBase
<T
, inlineCapacity
>::DequeIteratorBase()
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
))
597 addToIteratorsList();
601 template<typename T
, size_t inlineCapacity
>
602 inline DequeIteratorBase
<T
, inlineCapacity
>::DequeIteratorBase(const Base
& other
)
603 : m_deque(other
.m_deque
)
604 , m_index(other
.m_index
)
606 addToIteratorsList();
610 template<typename T
, size_t inlineCapacity
>
611 inline DequeIteratorBase
<T
, inlineCapacity
>& DequeIteratorBase
<T
, inlineCapacity
>::operator=(const Base
& other
)
614 other
.checkValidity();
615 removeFromIteratorsList();
617 m_deque
= other
.m_deque
;
618 m_index
= other
.m_index
;
619 addToIteratorsList();
624 template<typename T
, size_t inlineCapacity
>
625 inline DequeIteratorBase
<T
, inlineCapacity
>::~DequeIteratorBase()
628 removeFromIteratorsList();
633 template<typename T
, size_t inlineCapacity
>
634 inline bool DequeIteratorBase
<T
, inlineCapacity
>::isEqual(const Base
& other
) const
636 checkValidity(other
);
637 return m_index
== other
.m_index
;
640 template<typename T
, size_t inlineCapacity
>
641 inline void DequeIteratorBase
<T
, inlineCapacity
>::increment()
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)
653 template<typename T
, size_t inlineCapacity
>
654 inline void DequeIteratorBase
<T
, inlineCapacity
>::decrement()
657 ASSERT(m_index
!= m_deque
->m_start
);
658 ASSERT(m_deque
->m_buffer
.capacity());
660 m_index
= m_deque
->m_buffer
.capacity() - 1;
666 template<typename T
, size_t inlineCapacity
>
667 inline T
* DequeIteratorBase
<T
, inlineCapacity
>::after() const
670 ASSERT(m_index
!= m_deque
->m_end
);
671 return &m_deque
->m_buffer
.buffer()[m_index
];
674 template<typename T
, size_t inlineCapacity
>
675 inline T
* DequeIteratorBase
<T
, inlineCapacity
>::before() const
678 ASSERT(m_index
!= m_deque
->m_start
);
680 return &m_deque
->m_buffer
.buffer()[m_deque
->m_buffer
.capacity() - 1];
681 return &m_deque
->m_buffer
.buffer()[m_index
- 1];
688 #endif // WTF_Deque_h