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