]>
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" |
f9bf01c6 | 27 | #include "ValueCheck.h" |
b37bf2e1 A |
28 | #include "VectorTraits.h" |
29 | #include <limits> | |
b37bf2e1 A |
30 | #include <utility> |
31 | ||
ba379fdc A |
32 | #if PLATFORM(QT) |
33 | #include <QDataStream> | |
34 | #endif | |
35 | ||
b37bf2e1 | 36 | namespace WTF { |
9dae56ea | 37 | |
b37bf2e1 A |
38 | using std::min; |
39 | using std::max; | |
9dae56ea | 40 | |
b5422865 | 41 | // WTF_ALIGN_OF / WTF_ALIGNED |
9dae56ea A |
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) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) | |
53 | typedef char __attribute__((__may_alias__)) AlignedBufferChar; | |
54 | #else | |
55 | typedef char AlignedBufferChar; | |
56 | #endif | |
57 | ||
b5422865 A |
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); }; | |
9dae56ea | 66 | |
f9bf01c6 A |
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 | ||
b37bf2e1 | 74 | template <bool needsDestruction, typename T> |
f9bf01c6 | 75 | struct VectorDestructor; |
9dae56ea | 76 | |
b37bf2e1 A |
77 | template<typename T> |
78 | struct VectorDestructor<false, T> | |
79 | { | |
80 | static void destruct(T*, T*) {} | |
81 | }; | |
9dae56ea | 82 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 92 | |
b37bf2e1 | 93 | template <bool needsInitialization, bool canInitializeWithMemset, typename T> |
f9bf01c6 | 94 | struct VectorInitializer; |
9dae56ea | 95 | |
b37bf2e1 A |
96 | template<bool ignore, typename T> |
97 | struct VectorInitializer<false, ignore, T> | |
98 | { | |
99 | static void initialize(T*, T*) {} | |
100 | }; | |
9dae56ea | 101 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 111 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 120 | |
b37bf2e1 | 121 | template <bool canMoveWithMemcpy, typename T> |
f9bf01c6 | 122 | struct VectorMover; |
9dae56ea | 123 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 151 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 164 | |
b37bf2e1 | 165 | template <bool canCopyWithMemcpy, typename T> |
f9bf01c6 | 166 | struct VectorCopier; |
9dae56ea | 167 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 180 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 189 | |
b37bf2e1 | 190 | template <bool canFillWithMemset, typename T> |
f9bf01c6 | 191 | struct VectorFiller; |
9dae56ea | 192 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 204 | |
b37bf2e1 A |
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> | |
f9bf01c6 | 216 | struct VectorComparer; |
b37bf2e1 A |
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 | }; | |
9dae56ea | 229 | |
b37bf2e1 A |
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 | } | |
9dae56ea | 246 | |
b37bf2e1 A |
247 | static void initialize(T* begin, T* end) |
248 | { | |
249 | VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end); | |
250 | } | |
9dae56ea | 251 | |
b37bf2e1 A |
252 | static void move(const T* src, const T* srcEnd, T* dst) |
253 | { | |
254 | VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst); | |
255 | } | |
9dae56ea | 256 | |
b37bf2e1 A |
257 | static void moveOverlapping(const T* src, const T* srcEnd, T* dst) |
258 | { | |
259 | VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst); | |
260 | } | |
9dae56ea | 261 | |
b37bf2e1 A |
262 | static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) |
263 | { | |
264 | VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst); | |
265 | } | |
9dae56ea | 266 | |
b37bf2e1 A |
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 | }; | |
9dae56ea | 277 | |
b37bf2e1 | 278 | template<typename T> |
f9bf01c6 | 279 | class VectorBufferBase : public Noncopyable { |
b37bf2e1 A |
280 | public: |
281 | void allocateBuffer(size_t newCapacity) | |
282 | { | |
b37bf2e1 A |
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 | } | |
9dae56ea | 288 | |
4e4e5a6f A |
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 | ||
b37bf2e1 A |
303 | void deallocateBuffer(T* bufferToDeallocate) |
304 | { | |
b5422865 A |
305 | if (m_buffer == bufferToDeallocate) { |
306 | m_buffer = 0; | |
307 | m_capacity = 0; | |
308 | } | |
b37bf2e1 A |
309 | fastFree(bufferToDeallocate); |
310 | } | |
9dae56ea | 311 | |
b37bf2e1 A |
312 | T* buffer() { return m_buffer; } |
313 | const T* buffer() const { return m_buffer; } | |
b5422865 | 314 | T** bufferSlot() { return &m_buffer; } |
b37bf2e1 | 315 | size_t capacity() const { return m_capacity; } |
9dae56ea | 316 | |
b37bf2e1 A |
317 | T* releaseBuffer() |
318 | { | |
319 | T* buffer = m_buffer; | |
320 | m_buffer = 0; | |
321 | m_capacity = 0; | |
322 | return buffer; | |
323 | } | |
9dae56ea | 324 | |
b37bf2e1 A |
325 | protected: |
326 | VectorBufferBase() | |
9dae56ea A |
327 | : m_buffer(0) |
328 | , m_capacity(0) | |
b37bf2e1 A |
329 | { |
330 | } | |
9dae56ea | 331 | |
b37bf2e1 | 332 | VectorBufferBase(T* buffer, size_t capacity) |
9dae56ea A |
333 | : m_buffer(buffer) |
334 | , m_capacity(capacity) | |
b37bf2e1 A |
335 | { |
336 | } | |
9dae56ea | 337 | |
b37bf2e1 A |
338 | ~VectorBufferBase() |
339 | { | |
340 | // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here. | |
341 | } | |
9dae56ea | 342 | |
b37bf2e1 A |
343 | T* m_buffer; |
344 | size_t m_capacity; | |
345 | }; | |
9dae56ea | 346 | |
b37bf2e1 A |
347 | template<typename T, size_t inlineCapacity> |
348 | class VectorBuffer; | |
9dae56ea | 349 | |
b37bf2e1 A |
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 | } | |
9dae56ea | 358 | |
b37bf2e1 A |
359 | VectorBuffer(size_t capacity) |
360 | { | |
361 | allocateBuffer(capacity); | |
362 | } | |
9dae56ea | 363 | |
b37bf2e1 A |
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 | } | |
b5422865 A |
374 | |
375 | void restoreInlineBufferIfNeeded() { } | |
9dae56ea | 376 | |
b37bf2e1 | 377 | using Base::allocateBuffer; |
4e4e5a6f | 378 | using Base::tryAllocateBuffer; |
b37bf2e1 | 379 | using Base::deallocateBuffer; |
9dae56ea | 380 | |
b37bf2e1 | 381 | using Base::buffer; |
b5422865 | 382 | using Base::bufferSlot; |
b37bf2e1 | 383 | using Base::capacity; |
9dae56ea | 384 | |
b37bf2e1 A |
385 | using Base::releaseBuffer; |
386 | private: | |
387 | using Base::m_buffer; | |
388 | using Base::m_capacity; | |
389 | }; | |
9dae56ea | 390 | |
b37bf2e1 A |
391 | template<typename T, size_t inlineCapacity> |
392 | class VectorBuffer : private VectorBufferBase<T> { | |
393 | private: | |
394 | typedef VectorBufferBase<T> Base; | |
395 | public: | |
396 | VectorBuffer() | |
9dae56ea | 397 | : Base(inlineBuffer(), inlineCapacity) |
b37bf2e1 A |
398 | { |
399 | } | |
9dae56ea | 400 | |
b37bf2e1 | 401 | VectorBuffer(size_t capacity) |
9dae56ea | 402 | : Base(inlineBuffer(), inlineCapacity) |
b37bf2e1 | 403 | { |
ba379fdc A |
404 | if (capacity > inlineCapacity) |
405 | Base::allocateBuffer(capacity); | |
b37bf2e1 | 406 | } |
9dae56ea | 407 | |
b37bf2e1 A |
408 | ~VectorBuffer() |
409 | { | |
410 | deallocateBuffer(buffer()); | |
411 | } | |
9dae56ea | 412 | |
b5422865 A |
413 | void allocateBuffer(size_t newCapacity) |
414 | { | |
415 | if (newCapacity > inlineCapacity) | |
416 | Base::allocateBuffer(newCapacity); | |
ba379fdc A |
417 | else { |
418 | m_buffer = inlineBuffer(); | |
419 | m_capacity = inlineCapacity; | |
420 | } | |
b5422865 | 421 | } |
9dae56ea | 422 | |
4e4e5a6f A |
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 | ||
b37bf2e1 A |
432 | void deallocateBuffer(T* bufferToDeallocate) |
433 | { | |
434 | if (bufferToDeallocate == inlineBuffer()) | |
435 | return; | |
436 | Base::deallocateBuffer(bufferToDeallocate); | |
437 | } | |
b5422865 | 438 | |
f9bf01c6 A |
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 | ||
b5422865 A |
460 | void restoreInlineBufferIfNeeded() |
461 | { | |
462 | if (m_buffer) | |
463 | return; | |
464 | m_buffer = inlineBuffer(); | |
465 | m_capacity = inlineCapacity; | |
466 | } | |
9dae56ea | 467 | |
b37bf2e1 | 468 | using Base::buffer; |
b5422865 | 469 | using Base::bufferSlot; |
b37bf2e1 | 470 | using Base::capacity; |
9dae56ea | 471 | |
b37bf2e1 A |
472 | T* releaseBuffer() |
473 | { | |
474 | if (buffer() == inlineBuffer()) | |
475 | return 0; | |
476 | return Base::releaseBuffer(); | |
477 | } | |
9dae56ea | 478 | |
b37bf2e1 A |
479 | private: |
480 | using Base::m_buffer; | |
481 | using Base::m_capacity; | |
9dae56ea | 482 | |
b37bf2e1 | 483 | static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); |
9dae56ea A |
484 | #if PLATFORM(ARM) |
485 | // FIXME: <rdar://problem/6546253&6546260> | |
486 | T* inlineBuffer() { return reinterpret_cast<T*>(static_cast<void*>(m_inlineBuffer.buffer)); } | |
487 | #else | |
b5422865 | 488 | T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); } |
9dae56ea A |
489 | #endif |
490 | ||
b5422865 | 491 | AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
b37bf2e1 | 492 | }; |
9dae56ea | 493 | |
b37bf2e1 | 494 | template<typename T, size_t inlineCapacity = 0> |
ba379fdc | 495 | class Vector : public FastAllocBase { |
9dae56ea A |
496 | private: |
497 | typedef VectorBuffer<T, inlineCapacity> Buffer; | |
498 | typedef VectorTypeOperations<T> TypeOperations; | |
499 | ||
500 | public: | |
501 | typedef T ValueType; | |
502 | ||
503 | typedef T* iterator; | |
504 | typedef const T* const_iterator; | |
505 | ||
506 | Vector() | |
507 | : m_size(0) | |
508 | { | |
509 | } | |
510 | ||
511 | explicit Vector(size_t size) | |
512 | : m_size(size) | |
513 | , m_buffer(size) | |
514 | { | |
515 | if (begin()) | |
516 | TypeOperations::initialize(begin(), end()); | |
517 | } | |
518 | ||
519 | ~Vector() | |
520 | { | |
521 | if (m_size) shrink(0); | |
522 | } | |
523 | ||
524 | Vector(const Vector&); | |
525 | template<size_t otherCapacity> | |
526 | Vector(const Vector<T, otherCapacity>&); | |
527 | ||
528 | Vector& operator=(const Vector&); | |
529 | template<size_t otherCapacity> | |
530 | Vector& operator=(const Vector<T, otherCapacity>&); | |
531 | ||
532 | size_t size() const { return m_size; } | |
533 | size_t capacity() const { return m_buffer.capacity(); } | |
534 | bool isEmpty() const { return !size(); } | |
535 | ||
536 | T& at(size_t i) | |
537 | { | |
538 | ASSERT(i < size()); | |
539 | return m_buffer.buffer()[i]; | |
540 | } | |
541 | const T& at(size_t i) const | |
542 | { | |
543 | ASSERT(i < size()); | |
544 | return m_buffer.buffer()[i]; | |
545 | } | |
546 | ||
547 | T& operator[](size_t i) { return at(i); } | |
548 | const T& operator[](size_t i) const { return at(i); } | |
549 | ||
550 | T* data() { return m_buffer.buffer(); } | |
551 | const T* data() const { return m_buffer.buffer(); } | |
552 | T** dataSlot() { return m_buffer.bufferSlot(); } | |
553 | ||
554 | iterator begin() { return data(); } | |
555 | iterator end() { return begin() + m_size; } | |
556 | const_iterator begin() const { return data(); } | |
557 | const_iterator end() const { return begin() + m_size; } | |
558 | ||
559 | T& first() { return at(0); } | |
560 | const T& first() const { return at(0); } | |
561 | T& last() { return at(size() - 1); } | |
562 | const T& last() const { return at(size() - 1); } | |
563 | ||
564 | template<typename U> size_t find(const U&) const; | |
565 | ||
566 | void shrink(size_t size); | |
567 | void grow(size_t size); | |
568 | void resize(size_t size); | |
569 | void reserveCapacity(size_t newCapacity); | |
4e4e5a6f | 570 | bool tryReserveCapacity(size_t newCapacity); |
9dae56ea A |
571 | void reserveInitialCapacity(size_t initialCapacity); |
572 | void shrinkCapacity(size_t newCapacity); | |
573 | void shrinkToFit() { shrinkCapacity(size()); } | |
574 | ||
575 | void clear() { shrinkCapacity(0); } | |
576 | ||
577 | template<typename U> void append(const U*, size_t); | |
578 | template<typename U> void append(const U&); | |
579 | template<typename U> void uncheckedAppend(const U& val); | |
580 | template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&); | |
4e4e5a6f | 581 | template<typename U> bool tryAppend(const U*, size_t); |
9dae56ea A |
582 | |
583 | template<typename U> void insert(size_t position, const U*, size_t); | |
584 | template<typename U> void insert(size_t position, const U&); | |
585 | template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&); | |
586 | ||
587 | template<typename U> void prepend(const U*, size_t); | |
588 | template<typename U> void prepend(const U&); | |
589 | template<typename U, size_t c> void prepend(const Vector<U, c>&); | |
590 | ||
591 | void remove(size_t position); | |
592 | void remove(size_t position, size_t length); | |
593 | ||
594 | void removeLast() | |
595 | { | |
596 | ASSERT(!isEmpty()); | |
597 | shrink(size() - 1); | |
598 | } | |
599 | ||
600 | Vector(size_t size, const T& val) | |
601 | : m_size(size) | |
602 | , m_buffer(size) | |
603 | { | |
604 | if (begin()) | |
605 | TypeOperations::uninitializedFill(begin(), end(), val); | |
606 | } | |
607 | ||
608 | void fill(const T&, size_t); | |
609 | void fill(const T& val) { fill(val, size()); } | |
610 | ||
611 | template<typename Iterator> void appendRange(Iterator start, Iterator end); | |
612 | ||
613 | T* releaseBuffer(); | |
614 | ||
615 | void swap(Vector<T, inlineCapacity>& other) | |
616 | { | |
617 | std::swap(m_size, other.m_size); | |
618 | m_buffer.swap(other.m_buffer); | |
619 | } | |
620 | ||
f9bf01c6 A |
621 | void checkConsistency(); |
622 | ||
9dae56ea A |
623 | private: |
624 | void expandCapacity(size_t newMinCapacity); | |
625 | const T* expandCapacity(size_t newMinCapacity, const T*); | |
4e4e5a6f A |
626 | bool tryExpandCapacity(size_t newMinCapacity); |
627 | const T* tryExpandCapacity(size_t newMinCapacity, const T*); | |
9dae56ea A |
628 | template<typename U> U* expandCapacity(size_t newMinCapacity, U*); |
629 | ||
630 | size_t m_size; | |
631 | Buffer m_buffer; | |
632 | }; | |
633 | ||
ba379fdc A |
634 | #if PLATFORM(QT) |
635 | template<typename T> | |
636 | QDataStream& operator<<(QDataStream& stream, const Vector<T>& data) | |
637 | { | |
638 | stream << qint64(data.size()); | |
639 | foreach (const T& i, data) | |
640 | stream << i; | |
641 | return stream; | |
642 | } | |
643 | ||
644 | template<typename T> | |
645 | QDataStream& operator>>(QDataStream& stream, Vector<T>& data) | |
646 | { | |
647 | data.clear(); | |
648 | qint64 count; | |
649 | T item; | |
650 | stream >> count; | |
651 | data.reserveCapacity(count); | |
652 | for (qint64 i = 0; i < count; ++i) { | |
653 | stream >> item; | |
654 | data.append(item); | |
655 | } | |
656 | return stream; | |
657 | } | |
658 | #endif | |
659 | ||
9dae56ea A |
660 | template<typename T, size_t inlineCapacity> |
661 | Vector<T, inlineCapacity>::Vector(const Vector& other) | |
662 | : m_size(other.size()) | |
663 | , m_buffer(other.capacity()) | |
b37bf2e1 | 664 | { |
9dae56ea A |
665 | if (begin()) |
666 | TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); | |
b37bf2e1 | 667 | } |
9dae56ea A |
668 | |
669 | template<typename T, size_t inlineCapacity> | |
670 | template<size_t otherCapacity> | |
671 | Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other) | |
672 | : m_size(other.size()) | |
673 | , m_buffer(other.capacity()) | |
b37bf2e1 | 674 | { |
b5422865 | 675 | if (begin()) |
9dae56ea | 676 | TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); |
b37bf2e1 | 677 | } |
9dae56ea A |
678 | |
679 | template<typename T, size_t inlineCapacity> | |
680 | Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other) | |
b37bf2e1 | 681 | { |
9dae56ea A |
682 | if (&other == this) |
683 | return *this; | |
684 | ||
685 | if (size() > other.size()) | |
686 | shrink(other.size()); | |
687 | else if (other.size() > capacity()) { | |
688 | clear(); | |
689 | reserveCapacity(other.size()); | |
690 | if (!begin()) | |
691 | return *this; | |
692 | } | |
693 | ||
694 | std::copy(other.begin(), other.begin() + size(), begin()); | |
695 | TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); | |
696 | m_size = other.size(); | |
697 | ||
698 | return *this; | |
b37bf2e1 | 699 | } |
9dae56ea A |
700 | |
701 | template<typename T, size_t inlineCapacity> | |
b5422865 | 702 | template<size_t otherCapacity> |
9dae56ea | 703 | Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other) |
b37bf2e1 | 704 | { |
9dae56ea A |
705 | if (&other == this) |
706 | return *this; | |
707 | ||
708 | if (size() > other.size()) | |
709 | shrink(other.size()); | |
710 | else if (other.size() > capacity()) { | |
711 | clear(); | |
712 | reserveCapacity(other.size()); | |
713 | if (!begin()) | |
714 | return *this; | |
715 | } | |
716 | ||
717 | std::copy(other.begin(), other.begin() + size(), begin()); | |
718 | TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); | |
719 | m_size = other.size(); | |
720 | ||
721 | return *this; | |
b37bf2e1 | 722 | } |
9dae56ea A |
723 | |
724 | template<typename T, size_t inlineCapacity> | |
725 | template<typename U> | |
726 | size_t Vector<T, inlineCapacity>::find(const U& value) const | |
b37bf2e1 | 727 | { |
9dae56ea A |
728 | for (size_t i = 0; i < size(); ++i) { |
729 | if (at(i) == value) | |
730 | return i; | |
731 | } | |
732 | return notFound; | |
b37bf2e1 | 733 | } |
9dae56ea A |
734 | |
735 | template<typename T, size_t inlineCapacity> | |
736 | void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize) | |
b37bf2e1 | 737 | { |
9dae56ea A |
738 | if (size() > newSize) |
739 | shrink(newSize); | |
740 | else if (newSize > capacity()) { | |
741 | clear(); | |
742 | reserveCapacity(newSize); | |
743 | if (!begin()) | |
744 | return; | |
745 | } | |
746 | ||
747 | std::fill(begin(), end(), val); | |
748 | TypeOperations::uninitializedFill(end(), begin() + newSize, val); | |
749 | m_size = newSize; | |
b37bf2e1 | 750 | } |
9dae56ea A |
751 | |
752 | template<typename T, size_t inlineCapacity> | |
753 | template<typename Iterator> | |
754 | void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end) | |
b37bf2e1 | 755 | { |
9dae56ea A |
756 | for (Iterator it = start; it != end; ++it) |
757 | append(*it); | |
b37bf2e1 | 758 | } |
9dae56ea A |
759 | |
760 | template<typename T, size_t inlineCapacity> | |
761 | void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity) | |
762 | { | |
763 | reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); | |
b5422865 A |
764 | } |
765 | ||
9dae56ea A |
766 | template<typename T, size_t inlineCapacity> |
767 | const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr) | |
768 | { | |
769 | if (ptr < begin() || ptr >= end()) { | |
770 | expandCapacity(newMinCapacity); | |
771 | return ptr; | |
772 | } | |
773 | size_t index = ptr - begin(); | |
774 | expandCapacity(newMinCapacity); | |
775 | return begin() + index; | |
b5422865 | 776 | } |
9dae56ea | 777 | |
4e4e5a6f A |
778 | template<typename T, size_t inlineCapacity> |
779 | bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity) | |
780 | { | |
781 | return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); | |
782 | } | |
783 | ||
784 | template<typename T, size_t inlineCapacity> | |
785 | const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr) | |
786 | { | |
787 | if (ptr < begin() || ptr >= end()) { | |
788 | if (!tryExpandCapacity(newMinCapacity)) | |
789 | return 0; | |
790 | return ptr; | |
791 | } | |
792 | size_t index = ptr - begin(); | |
793 | if (!tryExpandCapacity(newMinCapacity)) | |
794 | return 0; | |
795 | return begin() + index; | |
796 | } | |
797 | ||
9dae56ea A |
798 | template<typename T, size_t inlineCapacity> template<typename U> |
799 | inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr) | |
800 | { | |
b37bf2e1 A |
801 | expandCapacity(newMinCapacity); |
802 | return ptr; | |
803 | } | |
9dae56ea A |
804 | |
805 | template<typename T, size_t inlineCapacity> | |
ba379fdc | 806 | inline void Vector<T, inlineCapacity>::resize(size_t size) |
9dae56ea A |
807 | { |
808 | if (size <= m_size) | |
809 | TypeOperations::destruct(begin() + size, end()); | |
810 | else { | |
811 | if (size > capacity()) | |
812 | expandCapacity(size); | |
813 | if (begin()) | |
814 | TypeOperations::initialize(end(), begin() + size); | |
815 | } | |
816 | ||
817 | m_size = size; | |
818 | } | |
819 | ||
820 | template<typename T, size_t inlineCapacity> | |
821 | void Vector<T, inlineCapacity>::shrink(size_t size) | |
822 | { | |
823 | ASSERT(size <= m_size); | |
b37bf2e1 | 824 | TypeOperations::destruct(begin() + size, end()); |
9dae56ea A |
825 | m_size = size; |
826 | } | |
827 | ||
828 | template<typename T, size_t inlineCapacity> | |
829 | void Vector<T, inlineCapacity>::grow(size_t size) | |
830 | { | |
831 | ASSERT(size >= m_size); | |
b37bf2e1 A |
832 | if (size > capacity()) |
833 | expandCapacity(size); | |
b5422865 A |
834 | if (begin()) |
835 | TypeOperations::initialize(end(), begin() + size); | |
9dae56ea | 836 | m_size = size; |
b37bf2e1 | 837 | } |
9dae56ea A |
838 | |
839 | template<typename T, size_t inlineCapacity> | |
840 | void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity) | |
841 | { | |
842 | if (newCapacity <= capacity()) | |
843 | return; | |
844 | T* oldBuffer = begin(); | |
b37bf2e1 A |
845 | T* oldEnd = end(); |
846 | m_buffer.allocateBuffer(newCapacity); | |
9dae56ea | 847 | if (begin()) |
b5422865 | 848 | TypeOperations::move(oldBuffer, oldEnd, begin()); |
9dae56ea | 849 | m_buffer.deallocateBuffer(oldBuffer); |
b37bf2e1 | 850 | } |
b5422865 | 851 | |
4e4e5a6f A |
852 | template<typename T, size_t inlineCapacity> |
853 | bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity) | |
854 | { | |
855 | if (newCapacity <= capacity()) | |
856 | return true; | |
857 | T* oldBuffer = begin(); | |
858 | T* oldEnd = end(); | |
859 | if (!m_buffer.tryAllocateBuffer(newCapacity)) | |
860 | return false; | |
861 | ASSERT(begin()); | |
862 | TypeOperations::move(oldBuffer, oldEnd, begin()); | |
863 | m_buffer.deallocateBuffer(oldBuffer); | |
864 | return true; | |
865 | } | |
866 | ||
9dae56ea A |
867 | template<typename T, size_t inlineCapacity> |
868 | inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity) | |
869 | { | |
870 | ASSERT(!m_size); | |
871 | ASSERT(capacity() == inlineCapacity); | |
872 | if (initialCapacity > inlineCapacity) | |
873 | m_buffer.allocateBuffer(initialCapacity); | |
b37bf2e1 | 874 | } |
9dae56ea A |
875 | |
876 | template<typename T, size_t inlineCapacity> | |
877 | void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity) | |
878 | { | |
879 | if (newCapacity >= capacity()) | |
b5422865 | 880 | return; |
9dae56ea A |
881 | |
882 | if (newCapacity < size()) | |
883 | shrink(newCapacity); | |
884 | ||
885 | T* oldBuffer = begin(); | |
886 | if (newCapacity > 0) { | |
887 | T* oldEnd = end(); | |
888 | m_buffer.allocateBuffer(newCapacity); | |
889 | if (begin() != oldBuffer) | |
890 | TypeOperations::move(oldBuffer, oldEnd, begin()); | |
891 | } | |
892 | ||
893 | m_buffer.deallocateBuffer(oldBuffer); | |
894 | m_buffer.restoreInlineBufferIfNeeded(); | |
b5422865 | 895 | } |
9dae56ea A |
896 | |
897 | // Templatizing these is better than just letting the conversion happen implicitly, | |
898 | // because for instance it allows a PassRefPtr to be appended to a RefPtr vector | |
899 | // without refcount thrash. | |
900 | ||
901 | template<typename T, size_t inlineCapacity> template<typename U> | |
902 | void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize) | |
903 | { | |
904 | size_t newSize = m_size + dataSize; | |
905 | if (newSize > capacity()) { | |
906 | data = expandCapacity(newSize, data); | |
907 | if (!begin()) | |
908 | return; | |
909 | } | |
910 | if (newSize < m_size) | |
911 | CRASH(); | |
912 | T* dest = end(); | |
913 | for (size_t i = 0; i < dataSize; ++i) | |
914 | new (&dest[i]) T(data[i]); | |
915 | m_size = newSize; | |
916 | } | |
917 | ||
4e4e5a6f A |
918 | template<typename T, size_t inlineCapacity> template<typename U> |
919 | bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize) | |
920 | { | |
921 | size_t newSize = m_size + dataSize; | |
922 | if (newSize > capacity()) { | |
923 | data = tryExpandCapacity(newSize, data); | |
924 | if (!data) | |
925 | return false; | |
926 | ASSERT(begin()); | |
927 | } | |
928 | if (newSize < m_size) | |
929 | return false; | |
930 | T* dest = end(); | |
931 | for (size_t i = 0; i < dataSize; ++i) | |
932 | new (&dest[i]) T(data[i]); | |
933 | m_size = newSize; | |
934 | return true; | |
935 | } | |
936 | ||
9dae56ea | 937 | template<typename T, size_t inlineCapacity> template<typename U> |
ba379fdc | 938 | ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) |
9dae56ea A |
939 | { |
940 | const U* ptr = &val; | |
941 | if (size() == capacity()) { | |
942 | ptr = expandCapacity(size() + 1, ptr); | |
943 | if (!begin()) | |
944 | return; | |
945 | } | |
946 | ||
4e4e5a6f | 947 | #if COMPILER(MSVC7_OR_LOWER) |
9dae56ea A |
948 | // FIXME: MSVC7 generates compilation errors when trying to assign |
949 | // a pointer to a Vector of its base class (i.e. can't downcast). So far | |
950 | // I've been unable to determine any logical reason for this, so I can | |
951 | // only assume it is a bug with the compiler. Casting is a bad solution, | |
952 | // however, because it subverts implicit conversions, so a better | |
953 | // one is needed. | |
954 | new (end()) T(static_cast<T>(*ptr)); | |
b37bf2e1 | 955 | #else |
9dae56ea | 956 | new (end()) T(*ptr); |
b37bf2e1 | 957 | #endif |
9dae56ea | 958 | ++m_size; |
b37bf2e1 | 959 | } |
9dae56ea A |
960 | |
961 | // This version of append saves a branch in the case where you know that the | |
962 | // vector's capacity is large enough for the append to succeed. | |
963 | ||
964 | template<typename T, size_t inlineCapacity> template<typename U> | |
965 | inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val) | |
966 | { | |
967 | ASSERT(size() < capacity()); | |
968 | const U* ptr = &val; | |
969 | new (end()) T(*ptr); | |
970 | ++m_size; | |
971 | } | |
972 | ||
973 | // This method should not be called append, a better name would be appendElements. | |
974 | // It could also be eliminated entirely, and call sites could just use | |
975 | // appendRange(val.begin(), val.end()). | |
976 | template<typename T, size_t inlineCapacity> template<size_t otherCapacity> | |
977 | inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val) | |
978 | { | |
979 | append(val.begin(), val.size()); | |
980 | } | |
981 | ||
982 | template<typename T, size_t inlineCapacity> template<typename U> | |
983 | void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize) | |
984 | { | |
985 | ASSERT(position <= size()); | |
986 | size_t newSize = m_size + dataSize; | |
987 | if (newSize > capacity()) { | |
988 | data = expandCapacity(newSize, data); | |
989 | if (!begin()) | |
990 | return; | |
991 | } | |
992 | if (newSize < m_size) | |
993 | CRASH(); | |
994 | T* spot = begin() + position; | |
995 | TypeOperations::moveOverlapping(spot, end(), spot + dataSize); | |
996 | for (size_t i = 0; i < dataSize; ++i) | |
997 | new (&spot[i]) T(data[i]); | |
998 | m_size = newSize; | |
999 | } | |
1000 | ||
1001 | template<typename T, size_t inlineCapacity> template<typename U> | |
1002 | inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val) | |
1003 | { | |
1004 | ASSERT(position <= size()); | |
1005 | const U* data = &val; | |
1006 | if (size() == capacity()) { | |
1007 | data = expandCapacity(size() + 1, data); | |
1008 | if (!begin()) | |
1009 | return; | |
1010 | } | |
1011 | T* spot = begin() + position; | |
1012 | TypeOperations::moveOverlapping(spot, end(), spot + 1); | |
1013 | new (spot) T(*data); | |
1014 | ++m_size; | |
1015 | } | |
1016 | ||
1017 | template<typename T, size_t inlineCapacity> template<typename U, size_t c> | |
1018 | inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val) | |
1019 | { | |
1020 | insert(position, val.begin(), val.size()); | |
1021 | } | |
1022 | ||
1023 | template<typename T, size_t inlineCapacity> template<typename U> | |
1024 | void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize) | |
1025 | { | |
1026 | insert(0, data, dataSize); | |
1027 | } | |
1028 | ||
1029 | template<typename T, size_t inlineCapacity> template<typename U> | |
1030 | inline void Vector<T, inlineCapacity>::prepend(const U& val) | |
1031 | { | |
1032 | insert(0, val); | |
1033 | } | |
1034 | ||
1035 | template<typename T, size_t inlineCapacity> template<typename U, size_t c> | |
1036 | inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val) | |
1037 | { | |
1038 | insert(0, val.begin(), val.size()); | |
b37bf2e1 | 1039 | } |
b37bf2e1 | 1040 | |
9dae56ea A |
1041 | template<typename T, size_t inlineCapacity> |
1042 | inline void Vector<T, inlineCapacity>::remove(size_t position) | |
1043 | { | |
1044 | ASSERT(position < size()); | |
1045 | T* spot = begin() + position; | |
1046 | spot->~T(); | |
1047 | TypeOperations::moveOverlapping(spot + 1, end(), spot); | |
1048 | --m_size; | |
1049 | } | |
1050 | ||
1051 | template<typename T, size_t inlineCapacity> | |
1052 | inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length) | |
1053 | { | |
1054 | ASSERT(position < size()); | |
f9bf01c6 | 1055 | ASSERT(position + length <= size()); |
9dae56ea A |
1056 | T* beginSpot = begin() + position; |
1057 | T* endSpot = beginSpot + length; | |
1058 | TypeOperations::destruct(beginSpot, endSpot); | |
1059 | TypeOperations::moveOverlapping(endSpot, end(), beginSpot); | |
1060 | m_size -= length; | |
1061 | } | |
1062 | ||
1063 | template<typename T, size_t inlineCapacity> | |
1064 | inline T* Vector<T, inlineCapacity>::releaseBuffer() | |
1065 | { | |
1066 | T* buffer = m_buffer.releaseBuffer(); | |
1067 | if (inlineCapacity && !buffer && m_size) { | |
1068 | // If the vector had some data, but no buffer to release, | |
1069 | // that means it was using the inline buffer. In that case, | |
1070 | // we create a brand new buffer so the caller always gets one. | |
1071 | size_t bytes = m_size * sizeof(T); | |
1072 | buffer = static_cast<T*>(fastMalloc(bytes)); | |
1073 | memcpy(buffer, data(), bytes); | |
1074 | } | |
1075 | m_size = 0; | |
1076 | return buffer; | |
1077 | } | |
1078 | ||
f9bf01c6 A |
1079 | template<typename T, size_t inlineCapacity> |
1080 | inline void Vector<T, inlineCapacity>::checkConsistency() | |
1081 | { | |
1082 | #if !ASSERT_DISABLED | |
1083 | for (size_t i = 0; i < size(); ++i) | |
1084 | ValueCheck<T>::checkConsistency(at(i)); | |
1085 | #endif | |
1086 | } | |
1087 | ||
9dae56ea A |
1088 | template<typename T, size_t inlineCapacity> |
1089 | void deleteAllValues(const Vector<T, inlineCapacity>& collection) | |
1090 | { | |
1091 | typedef typename Vector<T, inlineCapacity>::const_iterator iterator; | |
1092 | iterator end = collection.end(); | |
1093 | for (iterator it = collection.begin(); it != end; ++it) | |
1094 | delete *it; | |
1095 | } | |
1096 | ||
1097 | template<typename T, size_t inlineCapacity> | |
1098 | inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b) | |
1099 | { | |
1100 | a.swap(b); | |
1101 | } | |
1102 | ||
1103 | template<typename T, size_t inlineCapacity> | |
1104 | bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) | |
1105 | { | |
1106 | if (a.size() != b.size()) | |
1107 | return false; | |
1108 | ||
1109 | return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); | |
1110 | } | |
1111 | ||
1112 | template<typename T, size_t inlineCapacity> | |
1113 | inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) | |
1114 | { | |
1115 | return !(a == b); | |
1116 | } | |
b37bf2e1 | 1117 | |
f9bf01c6 A |
1118 | #if !ASSERT_DISABLED |
1119 | template<typename T> struct ValueCheck<Vector<T> > { | |
1120 | typedef Vector<T> TraitType; | |
1121 | static void checkConsistency(const Vector<T>& v) | |
1122 | { | |
1123 | v.checkConsistency(); | |
1124 | } | |
1125 | }; | |
1126 | #endif | |
b37bf2e1 A |
1127 | |
1128 | } // namespace WTF | |
1129 | ||
1130 | using WTF::Vector; | |
1131 | ||
1132 | #endif // WTF_Vector_h |