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