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