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