]> git.saurik.com Git - apple/javascriptcore.git/blame - wtf/Vector.h
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / wtf / Vector.h
CommitLineData
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 36namespace 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
1130using WTF::Vector;
1131
1132#endif // WTF_Vector_h