]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/Vector.h
JavaScriptCore-584.tar.gz
[apple/javascriptcore.git] / wtf / Vector.h
1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #ifndef WTF_Vector_h
22 #define WTF_Vector_h
23
24 #include "FastAllocBase.h"
25 #include "Noncopyable.h"
26 #include "NotFound.h"
27 #include "ValueCheck.h"
28 #include "VectorTraits.h"
29 #include <limits>
30 #include <utility>
31
32 #if PLATFORM(QT)
33 #include <QDataStream>
34 #endif
35
36 namespace WTF {
37
38 using std::min;
39 using std::max;
40
41 // WTF_ALIGN_OF / WTF_ALIGNED
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
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); };
66
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
74 template <bool needsDestruction, typename T>
75 struct VectorDestructor;
76
77 template<typename T>
78 struct VectorDestructor<false, T>
79 {
80 static void destruct(T*, T*) {}
81 };
82
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 };
92
93 template <bool needsInitialization, bool canInitializeWithMemset, typename T>
94 struct VectorInitializer;
95
96 template<bool ignore, typename T>
97 struct VectorInitializer<false, ignore, T>
98 {
99 static void initialize(T*, T*) {}
100 };
101
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 };
111
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 };
120
121 template <bool canMoveWithMemcpy, typename T>
122 struct VectorMover;
123
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 };
151
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 };
164
165 template <bool canCopyWithMemcpy, typename T>
166 struct VectorCopier;
167
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 };
180
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 };
189
190 template <bool canFillWithMemset, typename T>
191 struct VectorFiller;
192
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 };
204
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>
216 struct VectorComparer;
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 };
229
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 }
246
247 static void initialize(T* begin, T* end)
248 {
249 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
250 }
251
252 static void move(const T* src, const T* srcEnd, T* dst)
253 {
254 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
255 }
256
257 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
258 {
259 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
260 }
261
262 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
263 {
264 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
265 }
266
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 };
277
278 template<typename T>
279 class VectorBufferBase : public Noncopyable {
280 public:
281 void allocateBuffer(size_t newCapacity)
282 {
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 }
288
289 void deallocateBuffer(T* bufferToDeallocate)
290 {
291 if (m_buffer == bufferToDeallocate) {
292 m_buffer = 0;
293 m_capacity = 0;
294 }
295 fastFree(bufferToDeallocate);
296 }
297
298 T* buffer() { return m_buffer; }
299 const T* buffer() const { return m_buffer; }
300 T** bufferSlot() { return &m_buffer; }
301 size_t capacity() const { return m_capacity; }
302
303 T* releaseBuffer()
304 {
305 T* buffer = m_buffer;
306 m_buffer = 0;
307 m_capacity = 0;
308 return buffer;
309 }
310
311 protected:
312 VectorBufferBase()
313 : m_buffer(0)
314 , m_capacity(0)
315 {
316 }
317
318 VectorBufferBase(T* buffer, size_t capacity)
319 : m_buffer(buffer)
320 , m_capacity(capacity)
321 {
322 }
323
324 ~VectorBufferBase()
325 {
326 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
327 }
328
329 T* m_buffer;
330 size_t m_capacity;
331 };
332
333 template<typename T, size_t inlineCapacity>
334 class VectorBuffer;
335
336 template<typename T>
337 class VectorBuffer<T, 0> : private VectorBufferBase<T> {
338 private:
339 typedef VectorBufferBase<T> Base;
340 public:
341 VectorBuffer()
342 {
343 }
344
345 VectorBuffer(size_t capacity)
346 {
347 allocateBuffer(capacity);
348 }
349
350 ~VectorBuffer()
351 {
352 deallocateBuffer(buffer());
353 }
354
355 void swap(VectorBuffer<T, 0>& other)
356 {
357 std::swap(m_buffer, other.m_buffer);
358 std::swap(m_capacity, other.m_capacity);
359 }
360
361 void restoreInlineBufferIfNeeded() { }
362
363 using Base::allocateBuffer;
364 using Base::deallocateBuffer;
365
366 using Base::buffer;
367 using Base::bufferSlot;
368 using Base::capacity;
369
370 using Base::releaseBuffer;
371 private:
372 using Base::m_buffer;
373 using Base::m_capacity;
374 };
375
376 template<typename T, size_t inlineCapacity>
377 class VectorBuffer : private VectorBufferBase<T> {
378 private:
379 typedef VectorBufferBase<T> Base;
380 public:
381 VectorBuffer()
382 : Base(inlineBuffer(), inlineCapacity)
383 {
384 }
385
386 VectorBuffer(size_t capacity)
387 : Base(inlineBuffer(), inlineCapacity)
388 {
389 if (capacity > inlineCapacity)
390 Base::allocateBuffer(capacity);
391 }
392
393 ~VectorBuffer()
394 {
395 deallocateBuffer(buffer());
396 }
397
398 void allocateBuffer(size_t newCapacity)
399 {
400 if (newCapacity > inlineCapacity)
401 Base::allocateBuffer(newCapacity);
402 else {
403 m_buffer = inlineBuffer();
404 m_capacity = inlineCapacity;
405 }
406 }
407
408 void deallocateBuffer(T* bufferToDeallocate)
409 {
410 if (bufferToDeallocate == inlineBuffer())
411 return;
412 Base::deallocateBuffer(bufferToDeallocate);
413 }
414
415 void swap(VectorBuffer<T, inlineCapacity>& other)
416 {
417 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
418 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
419 std::swap(m_capacity, other.m_capacity);
420 } else if (buffer() == inlineBuffer()) {
421 m_buffer = other.m_buffer;
422 other.m_buffer = other.inlineBuffer();
423 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
424 std::swap(m_capacity, other.m_capacity);
425 } else if (other.buffer() == other.inlineBuffer()) {
426 other.m_buffer = m_buffer;
427 m_buffer = inlineBuffer();
428 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
429 std::swap(m_capacity, other.m_capacity);
430 } else {
431 std::swap(m_buffer, other.m_buffer);
432 std::swap(m_capacity, other.m_capacity);
433 }
434 }
435
436 void restoreInlineBufferIfNeeded()
437 {
438 if (m_buffer)
439 return;
440 m_buffer = inlineBuffer();
441 m_capacity = inlineCapacity;
442 }
443
444 using Base::buffer;
445 using Base::bufferSlot;
446 using Base::capacity;
447
448 T* releaseBuffer()
449 {
450 if (buffer() == inlineBuffer())
451 return 0;
452 return Base::releaseBuffer();
453 }
454
455 private:
456 using Base::m_buffer;
457 using Base::m_capacity;
458
459 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
460 #if PLATFORM(ARM)
461 // FIXME: <rdar://problem/6546253&6546260>
462 T* inlineBuffer() { return reinterpret_cast<T*>(static_cast<void*>(m_inlineBuffer.buffer)); }
463 #else
464 T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); }
465 #endif
466
467 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
468 };
469
470 template<typename T, size_t inlineCapacity = 0>
471 class Vector : public FastAllocBase {
472 private:
473 typedef VectorBuffer<T, inlineCapacity> Buffer;
474 typedef VectorTypeOperations<T> TypeOperations;
475
476 public:
477 typedef T ValueType;
478
479 typedef T* iterator;
480 typedef const T* const_iterator;
481
482 Vector()
483 : m_size(0)
484 {
485 }
486
487 explicit Vector(size_t size)
488 : m_size(size)
489 , m_buffer(size)
490 {
491 if (begin())
492 TypeOperations::initialize(begin(), end());
493 }
494
495 ~Vector()
496 {
497 if (m_size) shrink(0);
498 }
499
500 Vector(const Vector&);
501 template<size_t otherCapacity>
502 Vector(const Vector<T, otherCapacity>&);
503
504 Vector& operator=(const Vector&);
505 template<size_t otherCapacity>
506 Vector& operator=(const Vector<T, otherCapacity>&);
507
508 size_t size() const { return m_size; }
509 size_t capacity() const { return m_buffer.capacity(); }
510 bool isEmpty() const { return !size(); }
511
512 T& at(size_t i)
513 {
514 ASSERT(i < size());
515 return m_buffer.buffer()[i];
516 }
517 const T& at(size_t i) const
518 {
519 ASSERT(i < size());
520 return m_buffer.buffer()[i];
521 }
522
523 T& operator[](size_t i) { return at(i); }
524 const T& operator[](size_t i) const { return at(i); }
525
526 T* data() { return m_buffer.buffer(); }
527 const T* data() const { return m_buffer.buffer(); }
528 T** dataSlot() { return m_buffer.bufferSlot(); }
529
530 iterator begin() { return data(); }
531 iterator end() { return begin() + m_size; }
532 const_iterator begin() const { return data(); }
533 const_iterator end() const { return begin() + m_size; }
534
535 T& first() { return at(0); }
536 const T& first() const { return at(0); }
537 T& last() { return at(size() - 1); }
538 const T& last() const { return at(size() - 1); }
539
540 template<typename U> size_t find(const U&) const;
541
542 void shrink(size_t size);
543 void grow(size_t size);
544 void resize(size_t size);
545 void reserveCapacity(size_t newCapacity);
546 void reserveInitialCapacity(size_t initialCapacity);
547 void shrinkCapacity(size_t newCapacity);
548 void shrinkToFit() { shrinkCapacity(size()); }
549
550 void clear() { shrinkCapacity(0); }
551
552 template<typename U> void append(const U*, size_t);
553 template<typename U> void append(const U&);
554 template<typename U> void uncheckedAppend(const U& val);
555 template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
556
557 template<typename U> void insert(size_t position, const U*, size_t);
558 template<typename U> void insert(size_t position, const U&);
559 template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
560
561 template<typename U> void prepend(const U*, size_t);
562 template<typename U> void prepend(const U&);
563 template<typename U, size_t c> void prepend(const Vector<U, c>&);
564
565 void remove(size_t position);
566 void remove(size_t position, size_t length);
567
568 void removeLast()
569 {
570 ASSERT(!isEmpty());
571 shrink(size() - 1);
572 }
573
574 Vector(size_t size, const T& val)
575 : m_size(size)
576 , m_buffer(size)
577 {
578 if (begin())
579 TypeOperations::uninitializedFill(begin(), end(), val);
580 }
581
582 void fill(const T&, size_t);
583 void fill(const T& val) { fill(val, size()); }
584
585 template<typename Iterator> void appendRange(Iterator start, Iterator end);
586
587 T* releaseBuffer();
588
589 void swap(Vector<T, inlineCapacity>& other)
590 {
591 std::swap(m_size, other.m_size);
592 m_buffer.swap(other.m_buffer);
593 }
594
595 void checkConsistency();
596
597 private:
598 void expandCapacity(size_t newMinCapacity);
599 const T* expandCapacity(size_t newMinCapacity, const T*);
600 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
601
602 size_t m_size;
603 Buffer m_buffer;
604 };
605
606 #if PLATFORM(QT)
607 template<typename T>
608 QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
609 {
610 stream << qint64(data.size());
611 foreach (const T& i, data)
612 stream << i;
613 return stream;
614 }
615
616 template<typename T>
617 QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
618 {
619 data.clear();
620 qint64 count;
621 T item;
622 stream >> count;
623 data.reserveCapacity(count);
624 for (qint64 i = 0; i < count; ++i) {
625 stream >> item;
626 data.append(item);
627 }
628 return stream;
629 }
630 #endif
631
632 template<typename T, size_t inlineCapacity>
633 Vector<T, inlineCapacity>::Vector(const Vector& other)
634 : m_size(other.size())
635 , m_buffer(other.capacity())
636 {
637 if (begin())
638 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
639 }
640
641 template<typename T, size_t inlineCapacity>
642 template<size_t otherCapacity>
643 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
644 : m_size(other.size())
645 , m_buffer(other.capacity())
646 {
647 if (begin())
648 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
649 }
650
651 template<typename T, size_t inlineCapacity>
652 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
653 {
654 if (&other == this)
655 return *this;
656
657 if (size() > other.size())
658 shrink(other.size());
659 else if (other.size() > capacity()) {
660 clear();
661 reserveCapacity(other.size());
662 if (!begin())
663 return *this;
664 }
665
666 std::copy(other.begin(), other.begin() + size(), begin());
667 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
668 m_size = other.size();
669
670 return *this;
671 }
672
673 template<typename T, size_t inlineCapacity>
674 template<size_t otherCapacity>
675 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
676 {
677 if (&other == this)
678 return *this;
679
680 if (size() > other.size())
681 shrink(other.size());
682 else if (other.size() > capacity()) {
683 clear();
684 reserveCapacity(other.size());
685 if (!begin())
686 return *this;
687 }
688
689 std::copy(other.begin(), other.begin() + size(), begin());
690 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
691 m_size = other.size();
692
693 return *this;
694 }
695
696 template<typename T, size_t inlineCapacity>
697 template<typename U>
698 size_t Vector<T, inlineCapacity>::find(const U& value) const
699 {
700 for (size_t i = 0; i < size(); ++i) {
701 if (at(i) == value)
702 return i;
703 }
704 return notFound;
705 }
706
707 template<typename T, size_t inlineCapacity>
708 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
709 {
710 if (size() > newSize)
711 shrink(newSize);
712 else if (newSize > capacity()) {
713 clear();
714 reserveCapacity(newSize);
715 if (!begin())
716 return;
717 }
718
719 std::fill(begin(), end(), val);
720 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
721 m_size = newSize;
722 }
723
724 template<typename T, size_t inlineCapacity>
725 template<typename Iterator>
726 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
727 {
728 for (Iterator it = start; it != end; ++it)
729 append(*it);
730 }
731
732 template<typename T, size_t inlineCapacity>
733 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
734 {
735 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
736 }
737
738 template<typename T, size_t inlineCapacity>
739 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
740 {
741 if (ptr < begin() || ptr >= end()) {
742 expandCapacity(newMinCapacity);
743 return ptr;
744 }
745 size_t index = ptr - begin();
746 expandCapacity(newMinCapacity);
747 return begin() + index;
748 }
749
750 template<typename T, size_t inlineCapacity> template<typename U>
751 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
752 {
753 expandCapacity(newMinCapacity);
754 return ptr;
755 }
756
757 template<typename T, size_t inlineCapacity>
758 inline void Vector<T, inlineCapacity>::resize(size_t size)
759 {
760 if (size <= m_size)
761 TypeOperations::destruct(begin() + size, end());
762 else {
763 if (size > capacity())
764 expandCapacity(size);
765 if (begin())
766 TypeOperations::initialize(end(), begin() + size);
767 }
768
769 m_size = size;
770 }
771
772 template<typename T, size_t inlineCapacity>
773 void Vector<T, inlineCapacity>::shrink(size_t size)
774 {
775 ASSERT(size <= m_size);
776 TypeOperations::destruct(begin() + size, end());
777 m_size = size;
778 }
779
780 template<typename T, size_t inlineCapacity>
781 void Vector<T, inlineCapacity>::grow(size_t size)
782 {
783 ASSERT(size >= m_size);
784 if (size > capacity())
785 expandCapacity(size);
786 if (begin())
787 TypeOperations::initialize(end(), begin() + size);
788 m_size = size;
789 }
790
791 template<typename T, size_t inlineCapacity>
792 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
793 {
794 if (newCapacity <= capacity())
795 return;
796 T* oldBuffer = begin();
797 T* oldEnd = end();
798 m_buffer.allocateBuffer(newCapacity);
799 if (begin())
800 TypeOperations::move(oldBuffer, oldEnd, begin());
801 m_buffer.deallocateBuffer(oldBuffer);
802 }
803
804 template<typename T, size_t inlineCapacity>
805 inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
806 {
807 ASSERT(!m_size);
808 ASSERT(capacity() == inlineCapacity);
809 if (initialCapacity > inlineCapacity)
810 m_buffer.allocateBuffer(initialCapacity);
811 }
812
813 template<typename T, size_t inlineCapacity>
814 void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
815 {
816 if (newCapacity >= capacity())
817 return;
818
819 if (newCapacity < size())
820 shrink(newCapacity);
821
822 T* oldBuffer = begin();
823 if (newCapacity > 0) {
824 T* oldEnd = end();
825 m_buffer.allocateBuffer(newCapacity);
826 if (begin() != oldBuffer)
827 TypeOperations::move(oldBuffer, oldEnd, begin());
828 }
829
830 m_buffer.deallocateBuffer(oldBuffer);
831 m_buffer.restoreInlineBufferIfNeeded();
832 }
833
834 // Templatizing these is better than just letting the conversion happen implicitly,
835 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
836 // without refcount thrash.
837
838 template<typename T, size_t inlineCapacity> template<typename U>
839 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
840 {
841 size_t newSize = m_size + dataSize;
842 if (newSize > capacity()) {
843 data = expandCapacity(newSize, data);
844 if (!begin())
845 return;
846 }
847 if (newSize < m_size)
848 CRASH();
849 T* dest = end();
850 for (size_t i = 0; i < dataSize; ++i)
851 new (&dest[i]) T(data[i]);
852 m_size = newSize;
853 }
854
855 template<typename T, size_t inlineCapacity> template<typename U>
856 ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
857 {
858 const U* ptr = &val;
859 if (size() == capacity()) {
860 ptr = expandCapacity(size() + 1, ptr);
861 if (!begin())
862 return;
863 }
864
865 #if COMPILER(MSVC7)
866 // FIXME: MSVC7 generates compilation errors when trying to assign
867 // a pointer to a Vector of its base class (i.e. can't downcast). So far
868 // I've been unable to determine any logical reason for this, so I can
869 // only assume it is a bug with the compiler. Casting is a bad solution,
870 // however, because it subverts implicit conversions, so a better
871 // one is needed.
872 new (end()) T(static_cast<T>(*ptr));
873 #else
874 new (end()) T(*ptr);
875 #endif
876 ++m_size;
877 }
878
879 // This version of append saves a branch in the case where you know that the
880 // vector's capacity is large enough for the append to succeed.
881
882 template<typename T, size_t inlineCapacity> template<typename U>
883 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
884 {
885 ASSERT(size() < capacity());
886 const U* ptr = &val;
887 new (end()) T(*ptr);
888 ++m_size;
889 }
890
891 // This method should not be called append, a better name would be appendElements.
892 // It could also be eliminated entirely, and call sites could just use
893 // appendRange(val.begin(), val.end()).
894 template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
895 inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
896 {
897 append(val.begin(), val.size());
898 }
899
900 template<typename T, size_t inlineCapacity> template<typename U>
901 void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
902 {
903 ASSERT(position <= size());
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* spot = begin() + position;
913 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
914 for (size_t i = 0; i < dataSize; ++i)
915 new (&spot[i]) T(data[i]);
916 m_size = newSize;
917 }
918
919 template<typename T, size_t inlineCapacity> template<typename U>
920 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
921 {
922 ASSERT(position <= size());
923 const U* data = &val;
924 if (size() == capacity()) {
925 data = expandCapacity(size() + 1, data);
926 if (!begin())
927 return;
928 }
929 T* spot = begin() + position;
930 TypeOperations::moveOverlapping(spot, end(), spot + 1);
931 new (spot) T(*data);
932 ++m_size;
933 }
934
935 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
936 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
937 {
938 insert(position, val.begin(), val.size());
939 }
940
941 template<typename T, size_t inlineCapacity> template<typename U>
942 void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
943 {
944 insert(0, data, dataSize);
945 }
946
947 template<typename T, size_t inlineCapacity> template<typename U>
948 inline void Vector<T, inlineCapacity>::prepend(const U& val)
949 {
950 insert(0, val);
951 }
952
953 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
954 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
955 {
956 insert(0, val.begin(), val.size());
957 }
958
959 template<typename T, size_t inlineCapacity>
960 inline void Vector<T, inlineCapacity>::remove(size_t position)
961 {
962 ASSERT(position < size());
963 T* spot = begin() + position;
964 spot->~T();
965 TypeOperations::moveOverlapping(spot + 1, end(), spot);
966 --m_size;
967 }
968
969 template<typename T, size_t inlineCapacity>
970 inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
971 {
972 ASSERT(position < size());
973 ASSERT(position + length <= size());
974 T* beginSpot = begin() + position;
975 T* endSpot = beginSpot + length;
976 TypeOperations::destruct(beginSpot, endSpot);
977 TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
978 m_size -= length;
979 }
980
981 template<typename T, size_t inlineCapacity>
982 inline T* Vector<T, inlineCapacity>::releaseBuffer()
983 {
984 T* buffer = m_buffer.releaseBuffer();
985 if (inlineCapacity && !buffer && m_size) {
986 // If the vector had some data, but no buffer to release,
987 // that means it was using the inline buffer. In that case,
988 // we create a brand new buffer so the caller always gets one.
989 size_t bytes = m_size * sizeof(T);
990 buffer = static_cast<T*>(fastMalloc(bytes));
991 memcpy(buffer, data(), bytes);
992 }
993 m_size = 0;
994 return buffer;
995 }
996
997 template<typename T, size_t inlineCapacity>
998 inline void Vector<T, inlineCapacity>::checkConsistency()
999 {
1000 #if !ASSERT_DISABLED
1001 for (size_t i = 0; i < size(); ++i)
1002 ValueCheck<T>::checkConsistency(at(i));
1003 #endif
1004 }
1005
1006 template<typename T, size_t inlineCapacity>
1007 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
1008 {
1009 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
1010 iterator end = collection.end();
1011 for (iterator it = collection.begin(); it != end; ++it)
1012 delete *it;
1013 }
1014
1015 template<typename T, size_t inlineCapacity>
1016 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
1017 {
1018 a.swap(b);
1019 }
1020
1021 template<typename T, size_t inlineCapacity>
1022 bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1023 {
1024 if (a.size() != b.size())
1025 return false;
1026
1027 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
1028 }
1029
1030 template<typename T, size_t inlineCapacity>
1031 inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1032 {
1033 return !(a == b);
1034 }
1035
1036 #if !ASSERT_DISABLED
1037 template<typename T> struct ValueCheck<Vector<T> > {
1038 typedef Vector<T> TraitType;
1039 static void checkConsistency(const Vector<T>& v)
1040 {
1041 v.checkConsistency();
1042 }
1043 };
1044 #endif
1045
1046 } // namespace WTF
1047
1048 using WTF::Vector;
1049
1050 #endif // WTF_Vector_h