|
1 /* |
|
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public License |
|
15 * along with this library; see the file COPYING.LIB. If not, write to |
|
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
17 * Boston, MA 02110-1301, USA. |
|
18 * |
|
19 */ |
|
20 |
|
21 #ifndef WTF_Vector_h |
|
22 #define WTF_Vector_h |
|
23 |
|
24 #include "FastAllocBase.h" |
|
25 #include "Noncopyable.h" |
|
26 #include "NotFound.h" |
|
27 #include "ValueCheck.h" |
|
28 #include "VectorTraits.h" |
|
29 #include <limits> |
|
30 #include <utility> |
|
31 |
|
32 #if PLATFORM(QT) |
|
33 #include <QDataStream> |
|
34 #endif |
|
35 |
|
36 namespace WTF { |
|
37 |
|
38 using std::min; |
|
39 using std::max; |
|
40 |
|
41 // WTF_ALIGN_OF / WTF_ALIGNED |
|
42 #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW) |
|
43 #define WTF_ALIGN_OF(type) __alignof__(type) |
|
44 #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n))) |
|
45 #elif COMPILER(MSVC) |
|
46 #define WTF_ALIGN_OF(type) __alignof(type) |
|
47 #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable |
|
48 #else |
|
49 #error WTF_ALIGN macros need alignment control. |
|
50 #endif |
|
51 |
|
52 #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) |
|
53 typedef char __attribute__((__may_alias__)) AlignedBufferChar; |
|
54 #else |
|
55 typedef char AlignedBufferChar; |
|
56 #endif |
|
57 |
|
58 template <size_t size, size_t alignment> struct AlignedBuffer; |
|
59 template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; }; |
|
60 template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); }; |
|
61 template <size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); }; |
|
62 template <size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); }; |
|
63 template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); }; |
|
64 template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); }; |
|
65 template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); }; |
|
66 |
|
67 template <size_t size, size_t alignment> |
|
68 void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b) |
|
69 { |
|
70 for (size_t i = 0; i < size; ++i) |
|
71 std::swap(a.buffer[i], b.buffer[i]); |
|
72 } |
|
73 |
|
74 template <bool needsDestruction, typename T> |
|
75 struct VectorDestructor; |
|
76 |
|
77 template<typename T> |
|
78 struct VectorDestructor<false, T> |
|
79 { |
|
80 static void destruct(T*, T*) {} |
|
81 }; |
|
82 |
|
83 template<typename T> |
|
84 struct VectorDestructor<true, T> |
|
85 { |
|
86 static void destruct(T* begin, T* end) |
|
87 { |
|
88 for (T* cur = begin; cur != end; ++cur) |
|
89 cur->~T(); |
|
90 } |
|
91 }; |
|
92 |
|
93 template <bool needsInitialization, bool canInitializeWithMemset, typename T> |
|
94 struct VectorInitializer; |
|
95 |
|
96 template<bool ignore, typename T> |
|
97 struct VectorInitializer<false, ignore, T> |
|
98 { |
|
99 static void initialize(T*, T*) {} |
|
100 }; |
|
101 |
|
102 template<typename T> |
|
103 struct VectorInitializer<true, false, T> |
|
104 { |
|
105 static void initialize(T* begin, T* end) |
|
106 { |
|
107 for (T* cur = begin; cur != end; ++cur) |
|
108 new (cur) T; |
|
109 } |
|
110 }; |
|
111 |
|
112 template<typename T> |
|
113 struct VectorInitializer<true, true, T> |
|
114 { |
|
115 static void initialize(T* begin, T* end) |
|
116 { |
|
117 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin)); |
|
118 } |
|
119 }; |
|
120 |
|
121 template <bool canMoveWithMemcpy, typename T> |
|
122 struct VectorMover; |
|
123 |
|
124 template<typename T> |
|
125 struct VectorMover<false, T> |
|
126 { |
|
127 static void move(const T* src, const T* srcEnd, T* dst) |
|
128 { |
|
129 while (src != srcEnd) { |
|
130 new (dst) T(*src); |
|
131 src->~T(); |
|
132 ++dst; |
|
133 ++src; |
|
134 } |
|
135 } |
|
136 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) |
|
137 { |
|
138 if (src > dst) |
|
139 move(src, srcEnd, dst); |
|
140 else { |
|
141 T* dstEnd = dst + (srcEnd - src); |
|
142 while (src != srcEnd) { |
|
143 --srcEnd; |
|
144 --dstEnd; |
|
145 new (dstEnd) T(*srcEnd); |
|
146 srcEnd->~T(); |
|
147 } |
|
148 } |
|
149 } |
|
150 }; |
|
151 |
|
152 template<typename T> |
|
153 struct VectorMover<true, T> |
|
154 { |
|
155 static void move(const T* src, const T* srcEnd, T* dst) |
|
156 { |
|
157 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); |
|
158 } |
|
159 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) |
|
160 { |
|
161 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); |
|
162 } |
|
163 }; |
|
164 |
|
165 template <bool canCopyWithMemcpy, typename T> |
|
166 struct VectorCopier; |
|
167 |
|
168 template<typename T> |
|
169 struct VectorCopier<false, T> |
|
170 { |
|
171 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) |
|
172 { |
|
173 while (src != srcEnd) { |
|
174 new (dst) T(*src); |
|
175 ++dst; |
|
176 ++src; |
|
177 } |
|
178 } |
|
179 }; |
|
180 |
|
181 template<typename T> |
|
182 struct VectorCopier<true, T> |
|
183 { |
|
184 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) |
|
185 { |
|
186 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); |
|
187 } |
|
188 }; |
|
189 |
|
190 template <bool canFillWithMemset, typename T> |
|
191 struct VectorFiller; |
|
192 |
|
193 template<typename T> |
|
194 struct VectorFiller<false, T> |
|
195 { |
|
196 static void uninitializedFill(T* dst, T* dstEnd, const T& val) |
|
197 { |
|
198 while (dst != dstEnd) { |
|
199 new (dst) T(val); |
|
200 ++dst; |
|
201 } |
|
202 } |
|
203 }; |
|
204 |
|
205 template<typename T> |
|
206 struct VectorFiller<true, T> |
|
207 { |
|
208 static void uninitializedFill(T* dst, T* dstEnd, const T& val) |
|
209 { |
|
210 ASSERT(sizeof(T) == sizeof(char)); |
|
211 memset(dst, val, dstEnd - dst); |
|
212 } |
|
213 }; |
|
214 |
|
215 template<bool canCompareWithMemcmp, typename T> |
|
216 struct VectorComparer; |
|
217 |
|
218 template<typename T> |
|
219 struct VectorComparer<false, T> |
|
220 { |
|
221 static bool compare(const T* a, const T* b, size_t size) |
|
222 { |
|
223 for (size_t i = 0; i < size; ++i) |
|
224 if (a[i] != b[i]) |
|
225 return false; |
|
226 return true; |
|
227 } |
|
228 }; |
|
229 |
|
230 template<typename T> |
|
231 struct VectorComparer<true, T> |
|
232 { |
|
233 static bool compare(const T* a, const T* b, size_t size) |
|
234 { |
|
235 return memcmp(a, b, sizeof(T) * size) == 0; |
|
236 } |
|
237 }; |
|
238 |
|
239 template<typename T> |
|
240 struct VectorTypeOperations |
|
241 { |
|
242 static void destruct(T* begin, T* end) |
|
243 { |
|
244 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end); |
|
245 } |
|
246 |
|
247 static void initialize(T* begin, T* end) |
|
248 { |
|
249 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end); |
|
250 } |
|
251 |
|
252 static void move(const T* src, const T* srcEnd, T* dst) |
|
253 { |
|
254 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst); |
|
255 } |
|
256 |
|
257 static void moveOverlapping(const T* src, const T* srcEnd, T* dst) |
|
258 { |
|
259 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst); |
|
260 } |
|
261 |
|
262 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) |
|
263 { |
|
264 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst); |
|
265 } |
|
266 |
|
267 static void uninitializedFill(T* dst, T* dstEnd, const T& val) |
|
268 { |
|
269 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val); |
|
270 } |
|
271 |
|
272 static bool compare(const T* a, const T* b, size_t size) |
|
273 { |
|
274 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size); |
|
275 } |
|
276 }; |
|
277 |
|
278 template<typename T> |
|
279 class VectorBufferBase : public Noncopyable { |
|
280 public: |
|
281 void allocateBuffer(size_t newCapacity) |
|
282 { |
|
283 m_capacity = newCapacity; |
|
284 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) |
|
285 CRASH(); |
|
286 m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T))); |
|
287 } |
|
288 |
|
289 bool tryAllocateBuffer(size_t newCapacity) |
|
290 { |
|
291 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) |
|
292 return false; |
|
293 |
|
294 T* newBuffer; |
|
295 if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) { |
|
296 m_capacity = newCapacity; |
|
297 m_buffer = newBuffer; |
|
298 return true; |
|
299 } |
|
300 return false; |
|
301 } |
|
302 |
|
303 void deallocateBuffer(T* bufferToDeallocate) |
|
304 { |
|
305 if (m_buffer == bufferToDeallocate) { |
|
306 m_buffer = 0; |
|
307 m_capacity = 0; |
|
308 } |
|
309 fastFree(bufferToDeallocate); |
|
310 } |
|
311 |
|
312 T* buffer() { return m_buffer; } |
|
313 const T* buffer() const { return m_buffer; } |
|
314 T** bufferSlot() { return &m_buffer; } |
|
315 size_t capacity() const { return m_capacity; } |
|
316 |
|
317 T* releaseBuffer() |
|
318 { |
|
319 T* buffer = m_buffer; |
|
320 m_buffer = 0; |
|
321 m_capacity = 0; |
|
322 return buffer; |
|
323 } |
|
324 |
|
325 protected: |
|
326 VectorBufferBase() |
|
327 : m_buffer(0) |
|
328 , m_capacity(0) |
|
329 { |
|
330 } |
|
331 |
|
332 VectorBufferBase(T* buffer, size_t capacity) |
|
333 : m_buffer(buffer) |
|
334 , m_capacity(capacity) |
|
335 { |
|
336 } |
|
337 |
|
338 ~VectorBufferBase() |
|
339 { |
|
340 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here. |
|
341 } |
|
342 |
|
343 T* m_buffer; |
|
344 size_t m_capacity; |
|
345 }; |
|
346 |
|
347 template<typename T, size_t inlineCapacity> |
|
348 class VectorBuffer; |
|
349 |
|
350 template<typename T> |
|
351 class VectorBuffer<T, 0> : private VectorBufferBase<T> { |
|
352 private: |
|
353 typedef VectorBufferBase<T> Base; |
|
354 public: |
|
355 VectorBuffer() |
|
356 { |
|
357 } |
|
358 |
|
359 VectorBuffer(size_t capacity) |
|
360 { |
|
361 allocateBuffer(capacity); |
|
362 } |
|
363 |
|
364 ~VectorBuffer() |
|
365 { |
|
366 deallocateBuffer(buffer()); |
|
367 } |
|
368 |
|
369 void swap(VectorBuffer<T, 0>& other) |
|
370 { |
|
371 std::swap(m_buffer, other.m_buffer); |
|
372 std::swap(m_capacity, other.m_capacity); |
|
373 } |
|
374 |
|
375 void restoreInlineBufferIfNeeded() { } |
|
376 |
|
377 using Base::allocateBuffer; |
|
378 using Base::tryAllocateBuffer; |
|
379 using Base::deallocateBuffer; |
|
380 |
|
381 using Base::buffer; |
|
382 using Base::bufferSlot; |
|
383 using Base::capacity; |
|
384 |
|
385 using Base::releaseBuffer; |
|
386 private: |
|
387 using Base::m_buffer; |
|
388 using Base::m_capacity; |
|
389 }; |
|
390 |
|
391 template<typename T, size_t inlineCapacity> |
|
392 class VectorBuffer : private VectorBufferBase<T> { |
|
393 private: |
|
394 typedef VectorBufferBase<T> Base; |
|
395 public: |
|
396 VectorBuffer() |
|
397 : Base(inlineBuffer(), inlineCapacity) |
|
398 { |
|
399 } |
|
400 |
|
401 VectorBuffer(size_t capacity) |
|
402 : Base(inlineBuffer(), inlineCapacity) |
|
403 { |
|
404 if (capacity > inlineCapacity) |
|
405 Base::allocateBuffer(capacity); |
|
406 } |
|
407 |
|
408 ~VectorBuffer() |
|
409 { |
|
410 deallocateBuffer(buffer()); |
|
411 } |
|
412 |
|
413 void allocateBuffer(size_t newCapacity) |
|
414 { |
|
415 if (newCapacity > inlineCapacity) |
|
416 Base::allocateBuffer(newCapacity); |
|
417 else { |
|
418 m_buffer = inlineBuffer(); |
|
419 m_capacity = inlineCapacity; |
|
420 } |
|
421 } |
|
422 |
|
423 bool tryAllocateBuffer(size_t newCapacity) |
|
424 { |
|
425 if (newCapacity > inlineCapacity) |
|
426 return Base::tryAllocateBuffer(newCapacity); |
|
427 m_buffer = inlineBuffer(); |
|
428 m_capacity = inlineCapacity; |
|
429 return true; |
|
430 } |
|
431 |
|
432 void deallocateBuffer(T* bufferToDeallocate) |
|
433 { |
|
434 if (bufferToDeallocate == inlineBuffer()) |
|
435 return; |
|
436 Base::deallocateBuffer(bufferToDeallocate); |
|
437 } |
|
438 |
|
439 void swap(VectorBuffer<T, inlineCapacity>& other) |
|
440 { |
|
441 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) { |
|
442 WTF::swap(m_inlineBuffer, other.m_inlineBuffer); |
|
443 std::swap(m_capacity, other.m_capacity); |
|
444 } else if (buffer() == inlineBuffer()) { |
|
445 m_buffer = other.m_buffer; |
|
446 other.m_buffer = other.inlineBuffer(); |
|
447 WTF::swap(m_inlineBuffer, other.m_inlineBuffer); |
|
448 std::swap(m_capacity, other.m_capacity); |
|
449 } else if (other.buffer() == other.inlineBuffer()) { |
|
450 other.m_buffer = m_buffer; |
|
451 m_buffer = inlineBuffer(); |
|
452 WTF::swap(m_inlineBuffer, other.m_inlineBuffer); |
|
453 std::swap(m_capacity, other.m_capacity); |
|
454 } else { |
|
455 std::swap(m_buffer, other.m_buffer); |
|
456 std::swap(m_capacity, other.m_capacity); |
|
457 } |
|
458 } |
|
459 |
|
460 void restoreInlineBufferIfNeeded() |
|
461 { |
|
462 if (m_buffer) |
|
463 return; |
|
464 m_buffer = inlineBuffer(); |
|
465 m_capacity = inlineCapacity; |
|
466 } |
|
467 |
|
468 using Base::buffer; |
|
469 using Base::bufferSlot; |
|
470 using Base::capacity; |
|
471 |
|
472 T* releaseBuffer() |
|
473 { |
|
474 if (buffer() == inlineBuffer()) |
|
475 return 0; |
|
476 return Base::releaseBuffer(); |
|
477 } |
|
478 |
|
479 private: |
|
480 using Base::m_buffer; |
|
481 using Base::m_capacity; |
|
482 |
|
483 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
|
484 T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); } |
|
485 |
|
486 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
|
487 }; |
|
488 |
|
489 template<typename T, size_t inlineCapacity = 0> |
|
490 class Vector : public FastAllocBase { |
|
491 private: |
|
492 typedef VectorBuffer<T, inlineCapacity> Buffer; |
|
493 typedef VectorTypeOperations<T> TypeOperations; |
|
494 |
|
495 public: |
|
496 typedef T ValueType; |
|
497 |
|
498 typedef T* iterator; |
|
499 typedef const T* const_iterator; |
|
500 |
|
501 Vector() |
|
502 : m_size(0) |
|
503 { |
|
504 } |
|
505 |
|
506 explicit Vector(size_t size) |
|
507 : m_size(size) |
|
508 , m_buffer(size) |
|
509 { |
|
510 if (begin()) |
|
511 TypeOperations::initialize(begin(), end()); |
|
512 } |
|
513 |
|
514 ~Vector() |
|
515 { |
|
516 if (m_size) shrink(0); |
|
517 } |
|
518 |
|
519 Vector(const Vector&); |
|
520 template<size_t otherCapacity> |
|
521 Vector(const Vector<T, otherCapacity>&); |
|
522 |
|
523 Vector& operator=(const Vector&); |
|
524 template<size_t otherCapacity> |
|
525 Vector& operator=(const Vector<T, otherCapacity>&); |
|
526 |
|
527 size_t size() const { return m_size; } |
|
528 size_t capacity() const { return m_buffer.capacity(); } |
|
529 bool isEmpty() const { return !size(); } |
|
530 |
|
531 T& at(size_t i) |
|
532 { |
|
533 ASSERT(i < size()); |
|
534 return m_buffer.buffer()[i]; |
|
535 } |
|
536 const T& at(size_t i) const |
|
537 { |
|
538 ASSERT(i < size()); |
|
539 return m_buffer.buffer()[i]; |
|
540 } |
|
541 |
|
542 T& operator[](size_t i) { return at(i); } |
|
543 const T& operator[](size_t i) const { return at(i); } |
|
544 |
|
545 T* data() { return m_buffer.buffer(); } |
|
546 const T* data() const { return m_buffer.buffer(); } |
|
547 T** dataSlot() { return m_buffer.bufferSlot(); } |
|
548 |
|
549 iterator begin() { return data(); } |
|
550 iterator end() { return begin() + m_size; } |
|
551 const_iterator begin() const { return data(); } |
|
552 const_iterator end() const { return begin() + m_size; } |
|
553 |
|
554 T& first() { return at(0); } |
|
555 const T& first() const { return at(0); } |
|
556 T& last() { return at(size() - 1); } |
|
557 const T& last() const { return at(size() - 1); } |
|
558 |
|
559 template<typename U> size_t find(const U&) const; |
|
560 template<typename U> size_t reverseFind(const U&) const; |
|
561 |
|
562 void shrink(size_t size); |
|
563 void grow(size_t size); |
|
564 void resize(size_t size); |
|
565 void reserveCapacity(size_t newCapacity); |
|
566 bool tryReserveCapacity(size_t newCapacity); |
|
567 void reserveInitialCapacity(size_t initialCapacity); |
|
568 void shrinkCapacity(size_t newCapacity); |
|
569 void shrinkToFit() { shrinkCapacity(size()); } |
|
570 |
|
571 void clear() { shrinkCapacity(0); } |
|
572 |
|
573 template<typename U> void append(const U*, size_t); |
|
574 template<typename U> void append(const U&); |
|
575 template<typename U> void uncheckedAppend(const U& val); |
|
576 template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&); |
|
577 template<typename U> bool tryAppend(const U*, size_t); |
|
578 |
|
579 template<typename U> void insert(size_t position, const U*, size_t); |
|
580 template<typename U> void insert(size_t position, const U&); |
|
581 template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&); |
|
582 |
|
583 template<typename U> void prepend(const U*, size_t); |
|
584 template<typename U> void prepend(const U&); |
|
585 template<typename U, size_t c> void prepend(const Vector<U, c>&); |
|
586 |
|
587 void remove(size_t position); |
|
588 void remove(size_t position, size_t length); |
|
589 |
|
590 void removeLast() |
|
591 { |
|
592 ASSERT(!isEmpty()); |
|
593 shrink(size() - 1); |
|
594 } |
|
595 |
|
596 Vector(size_t size, const T& val) |
|
597 : m_size(size) |
|
598 , m_buffer(size) |
|
599 { |
|
600 if (begin()) |
|
601 TypeOperations::uninitializedFill(begin(), end(), val); |
|
602 } |
|
603 |
|
604 void fill(const T&, size_t); |
|
605 void fill(const T& val) { fill(val, size()); } |
|
606 |
|
607 template<typename Iterator> void appendRange(Iterator start, Iterator end); |
|
608 |
|
609 T* releaseBuffer(); |
|
610 |
|
611 void swap(Vector<T, inlineCapacity>& other) |
|
612 { |
|
613 std::swap(m_size, other.m_size); |
|
614 m_buffer.swap(other.m_buffer); |
|
615 } |
|
616 |
|
617 void checkConsistency(); |
|
618 |
|
619 private: |
|
620 void expandCapacity(size_t newMinCapacity); |
|
621 const T* expandCapacity(size_t newMinCapacity, const T*); |
|
622 bool tryExpandCapacity(size_t newMinCapacity); |
|
623 const T* tryExpandCapacity(size_t newMinCapacity, const T*); |
|
624 template<typename U> U* expandCapacity(size_t newMinCapacity, U*); |
|
625 |
|
626 size_t m_size; |
|
627 Buffer m_buffer; |
|
628 }; |
|
629 |
|
630 #if PLATFORM(QT) |
|
631 template<typename T> |
|
632 QDataStream& operator<<(QDataStream& stream, const Vector<T>& data) |
|
633 { |
|
634 stream << qint64(data.size()); |
|
635 foreach (const T& i, data) |
|
636 stream << i; |
|
637 return stream; |
|
638 } |
|
639 |
|
640 template<typename T> |
|
641 QDataStream& operator>>(QDataStream& stream, Vector<T>& data) |
|
642 { |
|
643 data.clear(); |
|
644 qint64 count; |
|
645 T item; |
|
646 stream >> count; |
|
647 data.reserveCapacity(count); |
|
648 for (qint64 i = 0; i < count; ++i) { |
|
649 stream >> item; |
|
650 data.append(item); |
|
651 } |
|
652 return stream; |
|
653 } |
|
654 #endif |
|
655 |
|
656 template<typename T, size_t inlineCapacity> |
|
657 Vector<T, inlineCapacity>::Vector(const Vector& other) |
|
658 : m_size(other.size()) |
|
659 , m_buffer(other.capacity()) |
|
660 { |
|
661 if (begin()) |
|
662 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
|
663 } |
|
664 |
|
665 template<typename T, size_t inlineCapacity> |
|
666 template<size_t otherCapacity> |
|
667 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other) |
|
668 : m_size(other.size()) |
|
669 , m_buffer(other.capacity()) |
|
670 { |
|
671 if (begin()) |
|
672 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
|
673 } |
|
674 |
|
675 template<typename T, size_t inlineCapacity> |
|
676 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other) |
|
677 { |
|
678 if (&other == this) |
|
679 return *this; |
|
680 |
|
681 if (size() > other.size()) |
|
682 shrink(other.size()); |
|
683 else if (other.size() > capacity()) { |
|
684 clear(); |
|
685 reserveCapacity(other.size()); |
|
686 if (!begin()) |
|
687 return *this; |
|
688 } |
|
689 |
|
690 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
|
691 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
|
692 if (!begin()) |
|
693 return *this; |
|
694 #endif |
|
695 |
|
696 std::copy(other.begin(), other.begin() + size(), begin()); |
|
697 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
|
698 m_size = other.size(); |
|
699 |
|
700 return *this; |
|
701 } |
|
702 |
|
703 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } |
|
704 |
|
705 template<typename T, size_t inlineCapacity> |
|
706 template<size_t otherCapacity> |
|
707 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other) |
|
708 { |
|
709 // If the inline capacities match, we should call the more specific |
|
710 // template. If the inline capacities don't match, the two objects |
|
711 // shouldn't be allocated the same address. |
|
712 ASSERT(!typelessPointersAreEqual(&other, this)); |
|
713 |
|
714 if (size() > other.size()) |
|
715 shrink(other.size()); |
|
716 else if (other.size() > capacity()) { |
|
717 clear(); |
|
718 reserveCapacity(other.size()); |
|
719 if (!begin()) |
|
720 return *this; |
|
721 } |
|
722 |
|
723 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last |
|
724 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL |
|
725 if (!begin()) |
|
726 return *this; |
|
727 #endif |
|
728 |
|
729 std::copy(other.begin(), other.begin() + size(), begin()); |
|
730 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); |
|
731 m_size = other.size(); |
|
732 |
|
733 return *this; |
|
734 } |
|
735 |
|
736 template<typename T, size_t inlineCapacity> |
|
737 template<typename U> |
|
738 size_t Vector<T, inlineCapacity>::find(const U& value) const |
|
739 { |
|
740 for (size_t i = 0; i < size(); ++i) { |
|
741 if (at(i) == value) |
|
742 return i; |
|
743 } |
|
744 return notFound; |
|
745 } |
|
746 |
|
747 template<typename T, size_t inlineCapacity> |
|
748 template<typename U> |
|
749 size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const |
|
750 { |
|
751 for (size_t i = 1; i <= size(); ++i) { |
|
752 const size_t index = size() - i; |
|
753 if (at(index) == value) |
|
754 return index; |
|
755 } |
|
756 return notFound; |
|
757 } |
|
758 |
|
759 template<typename T, size_t inlineCapacity> |
|
760 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize) |
|
761 { |
|
762 if (size() > newSize) |
|
763 shrink(newSize); |
|
764 else if (newSize > capacity()) { |
|
765 clear(); |
|
766 reserveCapacity(newSize); |
|
767 if (!begin()) |
|
768 return; |
|
769 } |
|
770 |
|
771 std::fill(begin(), end(), val); |
|
772 TypeOperations::uninitializedFill(end(), begin() + newSize, val); |
|
773 m_size = newSize; |
|
774 } |
|
775 |
|
776 template<typename T, size_t inlineCapacity> |
|
777 template<typename Iterator> |
|
778 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end) |
|
779 { |
|
780 for (Iterator it = start; it != end; ++it) |
|
781 append(*it); |
|
782 } |
|
783 |
|
784 template<typename T, size_t inlineCapacity> |
|
785 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity) |
|
786 { |
|
787 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); |
|
788 } |
|
789 |
|
790 template<typename T, size_t inlineCapacity> |
|
791 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr) |
|
792 { |
|
793 if (ptr < begin() || ptr >= end()) { |
|
794 expandCapacity(newMinCapacity); |
|
795 return ptr; |
|
796 } |
|
797 size_t index = ptr - begin(); |
|
798 expandCapacity(newMinCapacity); |
|
799 return begin() + index; |
|
800 } |
|
801 |
|
802 template<typename T, size_t inlineCapacity> |
|
803 bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity) |
|
804 { |
|
805 return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); |
|
806 } |
|
807 |
|
808 template<typename T, size_t inlineCapacity> |
|
809 const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr) |
|
810 { |
|
811 if (ptr < begin() || ptr >= end()) { |
|
812 if (!tryExpandCapacity(newMinCapacity)) |
|
813 return 0; |
|
814 return ptr; |
|
815 } |
|
816 size_t index = ptr - begin(); |
|
817 if (!tryExpandCapacity(newMinCapacity)) |
|
818 return 0; |
|
819 return begin() + index; |
|
820 } |
|
821 |
|
822 template<typename T, size_t inlineCapacity> template<typename U> |
|
823 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr) |
|
824 { |
|
825 expandCapacity(newMinCapacity); |
|
826 return ptr; |
|
827 } |
|
828 |
|
829 template<typename T, size_t inlineCapacity> |
|
830 inline void Vector<T, inlineCapacity>::resize(size_t size) |
|
831 { |
|
832 if (size <= m_size) |
|
833 TypeOperations::destruct(begin() + size, end()); |
|
834 else { |
|
835 if (size > capacity()) |
|
836 expandCapacity(size); |
|
837 if (begin()) |
|
838 TypeOperations::initialize(end(), begin() + size); |
|
839 } |
|
840 |
|
841 m_size = size; |
|
842 } |
|
843 |
|
844 template<typename T, size_t inlineCapacity> |
|
845 void Vector<T, inlineCapacity>::shrink(size_t size) |
|
846 { |
|
847 ASSERT(size <= m_size); |
|
848 TypeOperations::destruct(begin() + size, end()); |
|
849 m_size = size; |
|
850 } |
|
851 |
|
852 template<typename T, size_t inlineCapacity> |
|
853 void Vector<T, inlineCapacity>::grow(size_t size) |
|
854 { |
|
855 ASSERT(size >= m_size); |
|
856 if (size > capacity()) |
|
857 expandCapacity(size); |
|
858 if (begin()) |
|
859 TypeOperations::initialize(end(), begin() + size); |
|
860 m_size = size; |
|
861 } |
|
862 |
|
863 template<typename T, size_t inlineCapacity> |
|
864 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity) |
|
865 { |
|
866 if (newCapacity <= capacity()) |
|
867 return; |
|
868 T* oldBuffer = begin(); |
|
869 T* oldEnd = end(); |
|
870 m_buffer.allocateBuffer(newCapacity); |
|
871 if (begin()) |
|
872 TypeOperations::move(oldBuffer, oldEnd, begin()); |
|
873 m_buffer.deallocateBuffer(oldBuffer); |
|
874 } |
|
875 |
|
876 template<typename T, size_t inlineCapacity> |
|
877 bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity) |
|
878 { |
|
879 if (newCapacity <= capacity()) |
|
880 return true; |
|
881 T* oldBuffer = begin(); |
|
882 T* oldEnd = end(); |
|
883 if (!m_buffer.tryAllocateBuffer(newCapacity)) |
|
884 return false; |
|
885 ASSERT(begin()); |
|
886 TypeOperations::move(oldBuffer, oldEnd, begin()); |
|
887 m_buffer.deallocateBuffer(oldBuffer); |
|
888 return true; |
|
889 } |
|
890 |
|
891 template<typename T, size_t inlineCapacity> |
|
892 inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity) |
|
893 { |
|
894 ASSERT(!m_size); |
|
895 ASSERT(capacity() == inlineCapacity); |
|
896 if (initialCapacity > inlineCapacity) |
|
897 m_buffer.allocateBuffer(initialCapacity); |
|
898 } |
|
899 |
|
900 template<typename T, size_t inlineCapacity> |
|
901 void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity) |
|
902 { |
|
903 if (newCapacity >= capacity()) |
|
904 return; |
|
905 |
|
906 if (newCapacity < size()) |
|
907 shrink(newCapacity); |
|
908 |
|
909 T* oldBuffer = begin(); |
|
910 if (newCapacity > 0) { |
|
911 T* oldEnd = end(); |
|
912 m_buffer.allocateBuffer(newCapacity); |
|
913 if (begin() != oldBuffer) |
|
914 TypeOperations::move(oldBuffer, oldEnd, begin()); |
|
915 } |
|
916 |
|
917 m_buffer.deallocateBuffer(oldBuffer); |
|
918 m_buffer.restoreInlineBufferIfNeeded(); |
|
919 } |
|
920 |
|
921 // Templatizing these is better than just letting the conversion happen implicitly, |
|
922 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector |
|
923 // without refcount thrash. |
|
924 |
|
925 template<typename T, size_t inlineCapacity> template<typename U> |
|
926 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize) |
|
927 { |
|
928 size_t newSize = m_size + dataSize; |
|
929 if (newSize > capacity()) { |
|
930 data = expandCapacity(newSize, data); |
|
931 if (!begin()) |
|
932 return; |
|
933 } |
|
934 if (newSize < m_size) |
|
935 CRASH(); |
|
936 T* dest = end(); |
|
937 for (size_t i = 0; i < dataSize; ++i) |
|
938 new (&dest[i]) T(data[i]); |
|
939 m_size = newSize; |
|
940 } |
|
941 |
|
942 template<typename T, size_t inlineCapacity> template<typename U> |
|
943 bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize) |
|
944 { |
|
945 size_t newSize = m_size + dataSize; |
|
946 if (newSize > capacity()) { |
|
947 data = tryExpandCapacity(newSize, data); |
|
948 if (!data) |
|
949 return false; |
|
950 ASSERT(begin()); |
|
951 } |
|
952 if (newSize < m_size) |
|
953 return false; |
|
954 T* dest = end(); |
|
955 for (size_t i = 0; i < dataSize; ++i) |
|
956 new (&dest[i]) T(data[i]); |
|
957 m_size = newSize; |
|
958 return true; |
|
959 } |
|
960 |
|
961 template<typename T, size_t inlineCapacity> template<typename U> |
|
962 ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) |
|
963 { |
|
964 const U* ptr = &val; |
|
965 if (size() == capacity()) { |
|
966 ptr = expandCapacity(size() + 1, ptr); |
|
967 if (!begin()) |
|
968 return; |
|
969 } |
|
970 |
|
971 #if COMPILER(MSVC7_OR_LOWER) |
|
972 // FIXME: MSVC7 generates compilation errors when trying to assign |
|
973 // a pointer to a Vector of its base class (i.e. can't downcast). So far |
|
974 // I've been unable to determine any logical reason for this, so I can |
|
975 // only assume it is a bug with the compiler. Casting is a bad solution, |
|
976 // however, because it subverts implicit conversions, so a better |
|
977 // one is needed. |
|
978 new (end()) T(static_cast<T>(*ptr)); |
|
979 #else |
|
980 new (end()) T(*ptr); |
|
981 #endif |
|
982 ++m_size; |
|
983 } |
|
984 |
|
985 // This version of append saves a branch in the case where you know that the |
|
986 // vector's capacity is large enough for the append to succeed. |
|
987 |
|
988 template<typename T, size_t inlineCapacity> template<typename U> |
|
989 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val) |
|
990 { |
|
991 ASSERT(size() < capacity()); |
|
992 const U* ptr = &val; |
|
993 new (end()) T(*ptr); |
|
994 ++m_size; |
|
995 } |
|
996 |
|
997 // This method should not be called append, a better name would be appendElements. |
|
998 // It could also be eliminated entirely, and call sites could just use |
|
999 // appendRange(val.begin(), val.end()). |
|
1000 template<typename T, size_t inlineCapacity> template<size_t otherCapacity> |
|
1001 inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val) |
|
1002 { |
|
1003 append(val.begin(), val.size()); |
|
1004 } |
|
1005 |
|
1006 template<typename T, size_t inlineCapacity> template<typename U> |
|
1007 void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize) |
|
1008 { |
|
1009 ASSERT(position <= size()); |
|
1010 size_t newSize = m_size + dataSize; |
|
1011 if (newSize > capacity()) { |
|
1012 data = expandCapacity(newSize, data); |
|
1013 if (!begin()) |
|
1014 return; |
|
1015 } |
|
1016 if (newSize < m_size) |
|
1017 CRASH(); |
|
1018 T* spot = begin() + position; |
|
1019 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); |
|
1020 for (size_t i = 0; i < dataSize; ++i) |
|
1021 new (&spot[i]) T(data[i]); |
|
1022 m_size = newSize; |
|
1023 } |
|
1024 |
|
1025 template<typename T, size_t inlineCapacity> template<typename U> |
|
1026 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val) |
|
1027 { |
|
1028 ASSERT(position <= size()); |
|
1029 const U* data = &val; |
|
1030 if (size() == capacity()) { |
|
1031 data = expandCapacity(size() + 1, data); |
|
1032 if (!begin()) |
|
1033 return; |
|
1034 } |
|
1035 T* spot = begin() + position; |
|
1036 TypeOperations::moveOverlapping(spot, end(), spot + 1); |
|
1037 new (spot) T(*data); |
|
1038 ++m_size; |
|
1039 } |
|
1040 |
|
1041 template<typename T, size_t inlineCapacity> template<typename U, size_t c> |
|
1042 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val) |
|
1043 { |
|
1044 insert(position, val.begin(), val.size()); |
|
1045 } |
|
1046 |
|
1047 template<typename T, size_t inlineCapacity> template<typename U> |
|
1048 void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize) |
|
1049 { |
|
1050 insert(0, data, dataSize); |
|
1051 } |
|
1052 |
|
1053 template<typename T, size_t inlineCapacity> template<typename U> |
|
1054 inline void Vector<T, inlineCapacity>::prepend(const U& val) |
|
1055 { |
|
1056 insert(0, val); |
|
1057 } |
|
1058 |
|
1059 template<typename T, size_t inlineCapacity> template<typename U, size_t c> |
|
1060 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val) |
|
1061 { |
|
1062 insert(0, val.begin(), val.size()); |
|
1063 } |
|
1064 |
|
1065 template<typename T, size_t inlineCapacity> |
|
1066 inline void Vector<T, inlineCapacity>::remove(size_t position) |
|
1067 { |
|
1068 ASSERT(position < size()); |
|
1069 T* spot = begin() + position; |
|
1070 spot->~T(); |
|
1071 TypeOperations::moveOverlapping(spot + 1, end(), spot); |
|
1072 --m_size; |
|
1073 } |
|
1074 |
|
1075 template<typename T, size_t inlineCapacity> |
|
1076 inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length) |
|
1077 { |
|
1078 ASSERT(position < size()); |
|
1079 ASSERT(position + length <= size()); |
|
1080 T* beginSpot = begin() + position; |
|
1081 T* endSpot = beginSpot + length; |
|
1082 TypeOperations::destruct(beginSpot, endSpot); |
|
1083 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); |
|
1084 m_size -= length; |
|
1085 } |
|
1086 |
|
1087 template<typename T, size_t inlineCapacity> |
|
1088 inline T* Vector<T, inlineCapacity>::releaseBuffer() |
|
1089 { |
|
1090 T* buffer = m_buffer.releaseBuffer(); |
|
1091 if (inlineCapacity && !buffer && m_size) { |
|
1092 // If the vector had some data, but no buffer to release, |
|
1093 // that means it was using the inline buffer. In that case, |
|
1094 // we create a brand new buffer so the caller always gets one. |
|
1095 size_t bytes = m_size * sizeof(T); |
|
1096 buffer = static_cast<T*>(fastMalloc(bytes)); |
|
1097 memcpy(buffer, data(), bytes); |
|
1098 } |
|
1099 m_size = 0; |
|
1100 return buffer; |
|
1101 } |
|
1102 |
|
1103 template<typename T, size_t inlineCapacity> |
|
1104 inline void Vector<T, inlineCapacity>::checkConsistency() |
|
1105 { |
|
1106 #if !ASSERT_DISABLED |
|
1107 for (size_t i = 0; i < size(); ++i) |
|
1108 ValueCheck<T>::checkConsistency(at(i)); |
|
1109 #endif |
|
1110 } |
|
1111 |
|
1112 template<typename T, size_t inlineCapacity> |
|
1113 void deleteAllValues(const Vector<T, inlineCapacity>& collection) |
|
1114 { |
|
1115 typedef typename Vector<T, inlineCapacity>::const_iterator iterator; |
|
1116 iterator end = collection.end(); |
|
1117 for (iterator it = collection.begin(); it != end; ++it) |
|
1118 delete *it; |
|
1119 } |
|
1120 |
|
1121 template<typename T, size_t inlineCapacity> |
|
1122 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b) |
|
1123 { |
|
1124 a.swap(b); |
|
1125 } |
|
1126 |
|
1127 template<typename T, size_t inlineCapacity> |
|
1128 bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) |
|
1129 { |
|
1130 if (a.size() != b.size()) |
|
1131 return false; |
|
1132 |
|
1133 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); |
|
1134 } |
|
1135 |
|
1136 template<typename T, size_t inlineCapacity> |
|
1137 inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) |
|
1138 { |
|
1139 return !(a == b); |
|
1140 } |
|
1141 |
|
1142 #if !ASSERT_DISABLED |
|
1143 template<typename T> struct ValueCheck<Vector<T> > { |
|
1144 typedef Vector<T> TraitType; |
|
1145 static void checkConsistency(const Vector<T>& v) |
|
1146 { |
|
1147 v.checkConsistency(); |
|
1148 } |
|
1149 }; |
|
1150 #endif |
|
1151 |
|
1152 } // namespace WTF |
|
1153 |
|
1154 using WTF::Vector; |
|
1155 |
|
1156 #endif // WTF_Vector_h |