]>
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 | ||
36 | #include "Vector.h" | |
37 | ||
38 | namespace WTF { | |
39 | ||
40 | template<typename T> class DequeIteratorBase; | |
41 | template<typename T> class DequeIterator; | |
42 | template<typename T> class DequeConstIterator; | |
43 | template<typename T> class DequeReverseIterator; | |
44 | template<typename T> class DequeConstReverseIterator; | |
45 | ||
46 | template<typename T> | |
ba379fdc | 47 | class Deque : public FastAllocBase { |
b37bf2e1 A |
48 | public: |
49 | typedef DequeIterator<T> iterator; | |
50 | typedef DequeConstIterator<T> const_iterator; | |
51 | typedef DequeReverseIterator<T> reverse_iterator; | |
52 | typedef DequeConstReverseIterator<T> const_reverse_iterator; | |
53 | ||
54 | Deque(); | |
55 | Deque(const Deque<T>&); | |
56 | Deque& operator=(const Deque<T>&); | |
57 | ~Deque(); | |
58 | ||
59 | void swap(Deque<T>&); | |
60 | ||
61 | size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } | |
62 | bool isEmpty() const { return m_start == m_end; } | |
63 | ||
64 | iterator begin() { return iterator(this, m_start); } | |
65 | iterator end() { return iterator(this, m_end); } | |
66 | const_iterator begin() const { return const_iterator(this, m_start); } | |
67 | const_iterator end() const { return const_iterator(this, m_end); } | |
68 | reverse_iterator rbegin() { return reverse_iterator(this, m_end); } | |
69 | reverse_iterator rend() { return reverse_iterator(this, m_start); } | |
70 | const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); } | |
71 | const_reverse_iterator rend() const { return const_reverse_iterator(this, m_start); } | |
72 | ||
73 | T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } | |
74 | const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } | |
75 | ||
76 | template<typename U> void append(const U&); | |
77 | template<typename U> void prepend(const U&); | |
78 | void removeFirst(); | |
ba379fdc A |
79 | void remove(iterator&); |
80 | void remove(const_iterator&); | |
b37bf2e1 A |
81 | |
82 | void clear(); | |
83 | ||
ba379fdc A |
84 | template<typename Predicate> |
85 | iterator findIf(Predicate&); | |
86 | ||
b37bf2e1 A |
87 | private: |
88 | friend class DequeIteratorBase<T>; | |
89 | ||
90 | typedef VectorBuffer<T, 0> Buffer; | |
91 | typedef VectorTypeOperations<T> TypeOperations; | |
92 | typedef DequeIteratorBase<T> IteratorBase; | |
93 | ||
ba379fdc | 94 | void remove(size_t position); |
b37bf2e1 A |
95 | void invalidateIterators(); |
96 | void destroyAll(); | |
97 | void checkValidity() const; | |
98 | void checkIndexValidity(size_t) const; | |
99 | void expandCapacityIfNeeded(); | |
100 | void expandCapacity(); | |
101 | ||
102 | size_t m_start; | |
103 | size_t m_end; | |
104 | Buffer m_buffer; | |
105 | #ifndef NDEBUG | |
106 | mutable IteratorBase* m_iterators; | |
107 | #endif | |
108 | }; | |
109 | ||
110 | template<typename T> | |
111 | class DequeIteratorBase { | |
112 | private: | |
113 | typedef DequeIteratorBase<T> Base; | |
114 | ||
115 | protected: | |
116 | DequeIteratorBase(); | |
117 | DequeIteratorBase(const Deque<T>*, size_t); | |
118 | DequeIteratorBase(const Base&); | |
119 | Base& operator=(const Base&); | |
120 | ~DequeIteratorBase(); | |
121 | ||
122 | void assign(const Base& other) { *this = other; } | |
123 | ||
124 | void increment(); | |
125 | void decrement(); | |
126 | ||
127 | T* before() const; | |
128 | T* after() const; | |
129 | ||
130 | bool isEqual(const Base&) const; | |
131 | ||
132 | private: | |
133 | void addToIteratorsList(); | |
ba379fdc | 134 | void removeFromIteratorsList(); |
b37bf2e1 A |
135 | void checkValidity() const; |
136 | void checkValidity(const Base&) const; | |
137 | ||
138 | Deque<T>* m_deque; | |
139 | size_t m_index; | |
140 | ||
141 | friend class Deque<T>; | |
142 | ||
143 | #ifndef NDEBUG | |
144 | mutable DequeIteratorBase* m_next; | |
145 | mutable DequeIteratorBase* m_previous; | |
146 | #endif | |
147 | }; | |
148 | ||
149 | template<typename T> | |
150 | class DequeIterator : public DequeIteratorBase<T> { | |
151 | private: | |
152 | typedef DequeIteratorBase<T> Base; | |
153 | typedef DequeIterator<T> Iterator; | |
154 | ||
155 | public: | |
156 | DequeIterator(Deque<T>* deque, size_t index) : Base(deque, index) { } | |
157 | ||
158 | DequeIterator(const Iterator& other) : Base(other) { } | |
159 | DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
160 | ||
161 | T& operator*() const { return *Base::after(); } | |
162 | T* operator->() const { return Base::after(); } | |
163 | ||
164 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
165 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
166 | ||
167 | Iterator& operator++() { Base::increment(); return *this; } | |
168 | // postfix ++ intentionally omitted | |
169 | Iterator& operator--() { Base::decrement(); return *this; } | |
170 | // postfix -- intentionally omitted | |
171 | }; | |
172 | ||
173 | template<typename T> | |
174 | class DequeConstIterator : public DequeIteratorBase<T> { | |
175 | private: | |
176 | typedef DequeIteratorBase<T> Base; | |
177 | typedef DequeConstIterator<T> Iterator; | |
178 | typedef DequeIterator<T> NonConstIterator; | |
179 | ||
180 | public: | |
181 | DequeConstIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } | |
182 | ||
183 | DequeConstIterator(const Iterator& other) : Base(other) { } | |
184 | DequeConstIterator(const NonConstIterator& other) : Base(other) { } | |
185 | DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
186 | DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } | |
187 | ||
188 | const T& operator*() const { return *Base::after(); } | |
189 | const T* operator->() const { return Base::after(); } | |
190 | ||
191 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
192 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
193 | ||
194 | Iterator& operator++() { Base::increment(); return *this; } | |
195 | // postfix ++ intentionally omitted | |
196 | Iterator& operator--() { Base::decrement(); return *this; } | |
197 | // postfix -- intentionally omitted | |
198 | }; | |
199 | ||
200 | template<typename T> | |
201 | class DequeReverseIterator : public DequeIteratorBase<T> { | |
202 | private: | |
203 | typedef DequeIteratorBase<T> Base; | |
204 | typedef DequeReverseIterator<T> Iterator; | |
205 | ||
206 | public: | |
207 | DequeReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } | |
208 | ||
209 | DequeReverseIterator(const Iterator& other) : Base(other) { } | |
210 | DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
211 | ||
212 | T& operator*() const { return *Base::before(); } | |
213 | T* operator->() const { return Base::before(); } | |
214 | ||
215 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
216 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
217 | ||
218 | Iterator& operator++() { Base::decrement(); return *this; } | |
219 | // postfix ++ intentionally omitted | |
220 | Iterator& operator--() { Base::increment(); return *this; } | |
221 | // postfix -- intentionally omitted | |
222 | }; | |
223 | ||
224 | template<typename T> | |
225 | class DequeConstReverseIterator : public DequeIteratorBase<T> { | |
226 | private: | |
227 | typedef DequeIteratorBase<T> Base; | |
228 | typedef DequeConstReverseIterator<T> Iterator; | |
229 | typedef DequeReverseIterator<T> NonConstIterator; | |
230 | ||
231 | public: | |
232 | DequeConstReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { } | |
233 | ||
234 | DequeConstReverseIterator(const Iterator& other) : Base(other) { } | |
235 | DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { } | |
236 | DequeConstReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } | |
237 | DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } | |
238 | ||
239 | const T& operator*() const { return *Base::before(); } | |
240 | const T* operator->() const { return Base::before(); } | |
241 | ||
242 | bool operator==(const Iterator& other) const { return Base::isEqual(other); } | |
243 | bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } | |
244 | ||
245 | Iterator& operator++() { Base::decrement(); return *this; } | |
246 | // postfix ++ intentionally omitted | |
247 | Iterator& operator--() { Base::increment(); return *this; } | |
248 | // postfix -- intentionally omitted | |
249 | }; | |
250 | ||
251 | #ifdef NDEBUG | |
252 | template<typename T> inline void Deque<T>::checkValidity() const { } | |
253 | template<typename T> inline void Deque<T>::checkIndexValidity(size_t) const { } | |
254 | template<typename T> inline void Deque<T>::invalidateIterators() { } | |
255 | #else | |
256 | template<typename T> | |
257 | void Deque<T>::checkValidity() const | |
258 | { | |
259 | if (!m_buffer.capacity()) { | |
260 | ASSERT(!m_start); | |
261 | ASSERT(!m_end); | |
262 | } else { | |
263 | ASSERT(m_start < m_buffer.capacity()); | |
264 | ASSERT(m_end < m_buffer.capacity()); | |
265 | } | |
266 | } | |
267 | ||
268 | template<typename T> | |
269 | void Deque<T>::checkIndexValidity(size_t index) const | |
270 | { | |
271 | ASSERT(index <= m_buffer.capacity()); | |
272 | if (m_start <= m_end) { | |
273 | ASSERT(index >= m_start); | |
274 | ASSERT(index <= m_end); | |
275 | } else { | |
276 | ASSERT(index >= m_start || index <= m_end); | |
277 | } | |
278 | } | |
279 | ||
280 | template<typename T> | |
281 | void Deque<T>::invalidateIterators() | |
282 | { | |
283 | IteratorBase* next; | |
284 | for (IteratorBase* p = m_iterators; p; p = next) { | |
285 | next = p->m_next; | |
286 | p->m_deque = 0; | |
287 | p->m_next = 0; | |
288 | p->m_previous = 0; | |
289 | } | |
290 | m_iterators = 0; | |
291 | } | |
292 | #endif | |
293 | ||
294 | template<typename T> | |
295 | inline Deque<T>::Deque() | |
296 | : m_start(0) | |
297 | , m_end(0) | |
298 | #ifndef NDEBUG | |
299 | , m_iterators(0) | |
300 | #endif | |
301 | { | |
302 | checkValidity(); | |
303 | } | |
304 | ||
305 | template<typename T> | |
306 | inline Deque<T>::Deque(const Deque<T>& other) | |
307 | : m_start(other.m_start) | |
308 | , m_end(other.m_end) | |
309 | , m_buffer(other.m_buffer.capacity()) | |
310 | #ifndef NDEBUG | |
311 | , m_iterators(0) | |
312 | #endif | |
313 | { | |
314 | const T* otherBuffer = other.m_buffer.buffer(); | |
315 | if (m_start <= m_end) | |
316 | TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start); | |
317 | else { | |
318 | TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer()); | |
319 | TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start); | |
320 | } | |
321 | } | |
322 | ||
9dae56ea A |
323 | template<typename T> |
324 | void deleteAllValues(const Deque<T>& collection) | |
325 | { | |
326 | typedef typename Deque<T>::const_iterator iterator; | |
327 | iterator end = collection.end(); | |
328 | for (iterator it = collection.begin(); it != end; ++it) | |
329 | delete *it; | |
330 | } | |
331 | ||
b37bf2e1 A |
332 | template<typename T> |
333 | inline Deque<T>& Deque<T>::operator=(const Deque<T>& other) | |
334 | { | |
335 | Deque<T> copy(other); | |
336 | swap(copy); | |
337 | return *this; | |
338 | } | |
339 | ||
340 | template<typename T> | |
341 | inline void Deque<T>::destroyAll() | |
342 | { | |
343 | if (m_start <= m_end) | |
344 | TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); | |
345 | else { | |
346 | TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); | |
347 | TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity()); | |
348 | } | |
349 | } | |
350 | ||
351 | template<typename T> | |
352 | inline Deque<T>::~Deque() | |
353 | { | |
354 | checkValidity(); | |
355 | invalidateIterators(); | |
356 | destroyAll(); | |
357 | } | |
358 | ||
ba379fdc | 359 | template<typename T> |
b37bf2e1 A |
360 | inline void Deque<T>::swap(Deque<T>& other) |
361 | { | |
362 | checkValidity(); | |
363 | other.checkValidity(); | |
364 | invalidateIterators(); | |
365 | std::swap(m_start, other.m_start); | |
366 | std::swap(m_end, other.m_end); | |
367 | m_buffer.swap(other.m_buffer); | |
368 | checkValidity(); | |
369 | other.checkValidity(); | |
370 | } | |
371 | ||
ba379fdc | 372 | template<typename T> |
b37bf2e1 A |
373 | inline void Deque<T>::clear() |
374 | { | |
375 | checkValidity(); | |
376 | invalidateIterators(); | |
377 | destroyAll(); | |
378 | m_start = 0; | |
379 | m_end = 0; | |
380 | checkValidity(); | |
381 | } | |
382 | ||
ba379fdc A |
383 | template<typename T> |
384 | template<typename Predicate> | |
385 | inline DequeIterator<T> Deque<T>::findIf(Predicate& predicate) | |
386 | { | |
387 | iterator end_iterator = end(); | |
388 | for (iterator it = begin(); it != end_iterator; ++it) { | |
389 | if (predicate(*it)) | |
390 | return it; | |
391 | } | |
392 | return end_iterator; | |
393 | } | |
394 | ||
b37bf2e1 A |
395 | template<typename T> |
396 | inline void Deque<T>::expandCapacityIfNeeded() | |
397 | { | |
398 | if (m_start) { | |
399 | if (m_end + 1 != m_start) | |
400 | return; | |
401 | } else if (m_end) { | |
402 | if (m_end != m_buffer.capacity() - 1) | |
403 | return; | |
404 | } else if (m_buffer.capacity()) | |
405 | return; | |
406 | ||
407 | expandCapacity(); | |
408 | } | |
409 | ||
410 | template<typename T> | |
411 | void Deque<T>::expandCapacity() | |
412 | { | |
413 | checkValidity(); | |
414 | size_t oldCapacity = m_buffer.capacity(); | |
415 | size_t newCapacity = max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1); | |
416 | T* oldBuffer = m_buffer.buffer(); | |
417 | m_buffer.allocateBuffer(newCapacity); | |
418 | if (m_start <= m_end) | |
419 | TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start); | |
420 | else { | |
421 | TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); | |
422 | size_t newStart = newCapacity - (oldCapacity - m_start); | |
423 | TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart); | |
424 | m_start = newStart; | |
425 | } | |
426 | m_buffer.deallocateBuffer(oldBuffer); | |
427 | checkValidity(); | |
428 | } | |
429 | ||
430 | template<typename T> template<typename U> | |
431 | inline void Deque<T>::append(const U& value) | |
432 | { | |
433 | checkValidity(); | |
434 | expandCapacityIfNeeded(); | |
435 | new (&m_buffer.buffer()[m_end]) T(value); | |
436 | if (m_end == m_buffer.capacity() - 1) | |
437 | m_end = 0; | |
438 | else | |
439 | ++m_end; | |
440 | checkValidity(); | |
441 | } | |
442 | ||
443 | template<typename T> template<typename U> | |
444 | inline void Deque<T>::prepend(const U& value) | |
445 | { | |
446 | checkValidity(); | |
447 | expandCapacityIfNeeded(); | |
448 | if (!m_start) | |
449 | m_start = m_buffer.capacity() - 1; | |
450 | else | |
451 | --m_start; | |
452 | new (&m_buffer.buffer()[m_start]) T(value); | |
453 | checkValidity(); | |
454 | } | |
455 | ||
456 | template<typename T> | |
457 | inline void Deque<T>::removeFirst() | |
458 | { | |
459 | checkValidity(); | |
460 | invalidateIterators(); | |
461 | ASSERT(!isEmpty()); | |
462 | TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]); | |
463 | if (m_start == m_buffer.capacity() - 1) | |
464 | m_start = 0; | |
465 | else | |
466 | ++m_start; | |
467 | checkValidity(); | |
468 | } | |
469 | ||
ba379fdc A |
470 | template<typename T> |
471 | inline void Deque<T>::remove(iterator& it) | |
472 | { | |
473 | it.checkValidity(); | |
474 | remove(it.m_index); | |
475 | } | |
476 | ||
477 | template<typename T> | |
478 | inline void Deque<T>::remove(const_iterator& it) | |
479 | { | |
480 | it.checkValidity(); | |
481 | remove(it.m_index); | |
482 | } | |
483 | ||
484 | template<typename T> | |
485 | inline void Deque<T>::remove(size_t position) | |
486 | { | |
487 | if (position == m_end) | |
488 | return; | |
489 | ||
490 | checkValidity(); | |
491 | invalidateIterators(); | |
492 | ||
493 | T* buffer = m_buffer.buffer(); | |
494 | TypeOperations::destruct(&buffer[position], &buffer[position + 1]); | |
495 | ||
496 | // Find which segment of the circular buffer contained the remove element, and only move elements in that part. | |
497 | if (position >= m_start) { | |
498 | TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1); | |
499 | m_start = (m_start + 1) % m_buffer.capacity(); | |
500 | } else { | |
501 | TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position); | |
502 | m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); | |
503 | } | |
504 | checkValidity(); | |
505 | } | |
506 | ||
b37bf2e1 A |
507 | #ifdef NDEBUG |
508 | template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { } | |
509 | template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { } | |
510 | template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { } | |
ba379fdc | 511 | template<typename T> inline void DequeIteratorBase<T>::removeFromIteratorsList() { } |
b37bf2e1 A |
512 | #else |
513 | template<typename T> | |
514 | void DequeIteratorBase<T>::checkValidity() const | |
515 | { | |
516 | ASSERT(m_deque); | |
517 | m_deque->checkIndexValidity(m_index); | |
518 | } | |
519 | ||
520 | template<typename T> | |
521 | void DequeIteratorBase<T>::checkValidity(const Base& other) const | |
522 | { | |
523 | checkValidity(); | |
524 | other.checkValidity(); | |
525 | ASSERT(m_deque == other.m_deque); | |
526 | } | |
527 | ||
528 | template<typename T> | |
529 | void DequeIteratorBase<T>::addToIteratorsList() | |
530 | { | |
531 | if (!m_deque) | |
532 | m_next = 0; | |
533 | else { | |
534 | m_next = m_deque->m_iterators; | |
535 | m_deque->m_iterators = this; | |
536 | if (m_next) | |
537 | m_next->m_previous = this; | |
538 | } | |
539 | m_previous = 0; | |
540 | } | |
ba379fdc A |
541 | |
542 | template<typename T> | |
543 | void DequeIteratorBase<T>::removeFromIteratorsList() | |
544 | { | |
545 | if (!m_deque) { | |
546 | ASSERT(!m_next); | |
547 | ASSERT(!m_previous); | |
548 | } else { | |
549 | if (m_next) { | |
550 | ASSERT(m_next->m_previous == this); | |
551 | m_next->m_previous = m_previous; | |
552 | } | |
553 | if (m_previous) { | |
554 | ASSERT(m_deque->m_iterators != this); | |
555 | ASSERT(m_previous->m_next == this); | |
556 | m_previous->m_next = m_next; | |
557 | } else { | |
558 | ASSERT(m_deque->m_iterators == this); | |
559 | m_deque->m_iterators = m_next; | |
560 | } | |
561 | } | |
562 | m_next = 0; | |
563 | m_previous = 0; | |
564 | } | |
b37bf2e1 A |
565 | #endif |
566 | ||
567 | template<typename T> | |
568 | inline DequeIteratorBase<T>::DequeIteratorBase() | |
569 | : m_deque(0) | |
570 | { | |
571 | } | |
572 | ||
573 | template<typename T> | |
574 | inline DequeIteratorBase<T>::DequeIteratorBase(const Deque<T>* deque, size_t index) | |
575 | : m_deque(const_cast<Deque<T>*>(deque)) | |
576 | , m_index(index) | |
577 | { | |
578 | addToIteratorsList(); | |
579 | checkValidity(); | |
580 | } | |
581 | ||
582 | template<typename T> | |
583 | inline DequeIteratorBase<T>::DequeIteratorBase(const Base& other) | |
584 | : m_deque(other.m_deque) | |
585 | , m_index(other.m_index) | |
586 | { | |
587 | addToIteratorsList(); | |
588 | checkValidity(); | |
589 | } | |
590 | ||
ba379fdc A |
591 | template<typename T> |
592 | inline DequeIteratorBase<T>& DequeIteratorBase<T>::operator=(const Base& other) | |
593 | { | |
594 | checkValidity(); | |
595 | other.checkValidity(); | |
596 | removeFromIteratorsList(); | |
597 | ||
598 | m_deque = other.m_deque; | |
599 | m_index = other.m_index; | |
600 | addToIteratorsList(); | |
601 | checkValidity(); | |
602 | return *this; | |
603 | } | |
604 | ||
b37bf2e1 A |
605 | template<typename T> |
606 | inline DequeIteratorBase<T>::~DequeIteratorBase() | |
607 | { | |
608 | #ifndef NDEBUG | |
ba379fdc | 609 | removeFromIteratorsList(); |
b37bf2e1 | 610 | m_deque = 0; |
b37bf2e1 A |
611 | #endif |
612 | } | |
613 | ||
614 | template<typename T> | |
615 | inline bool DequeIteratorBase<T>::isEqual(const Base& other) const | |
616 | { | |
617 | checkValidity(other); | |
618 | return m_index == other.m_index; | |
619 | } | |
620 | ||
621 | template<typename T> | |
622 | inline void DequeIteratorBase<T>::increment() | |
623 | { | |
624 | checkValidity(); | |
625 | ASSERT(m_index != m_deque->m_end); | |
626 | ASSERT(m_deque->m_buffer.capacity()); | |
627 | if (m_index == m_deque->m_buffer.capacity() - 1) | |
628 | m_index = 0; | |
629 | else | |
630 | ++m_index; | |
631 | checkValidity(); | |
632 | } | |
633 | ||
634 | template<typename T> | |
635 | inline void DequeIteratorBase<T>::decrement() | |
636 | { | |
637 | checkValidity(); | |
638 | ASSERT(m_index != m_deque->m_start); | |
639 | ASSERT(m_deque->m_buffer.capacity()); | |
640 | if (!m_index) | |
641 | m_index = m_deque->m_buffer.capacity() - 1; | |
642 | else | |
643 | --m_index; | |
644 | checkValidity(); | |
645 | } | |
646 | ||
647 | template<typename T> | |
648 | inline T* DequeIteratorBase<T>::after() const | |
649 | { | |
650 | checkValidity(); | |
651 | ASSERT(m_index != m_deque->m_end); | |
652 | return &m_deque->m_buffer.buffer()[m_index]; | |
653 | } | |
654 | ||
655 | template<typename T> | |
656 | inline T* DequeIteratorBase<T>::before() const | |
657 | { | |
658 | checkValidity(); | |
659 | ASSERT(m_index != m_deque->m_start); | |
660 | if (!m_index) | |
661 | return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; | |
662 | return &m_deque->m_buffer.buffer()[m_index - 1]; | |
663 | } | |
664 | ||
665 | } // namespace WTF | |
666 | ||
667 | using WTF::Deque; | |
668 | ||
669 | #endif // WTF_Deque_h |