2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
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.
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.
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.
24 #include "FastAllocBase.h"
25 #include "Noncopyable.h"
27 #include "StdLibExtras.h"
28 #include "ValueCheck.h"
29 #include "VectorTraits.h"
32 #include <wtf/Alignment.h>
35 #include <QDataStream>
43 #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
44 typedef char __attribute__((__may_alias__)) AlignedBufferChar;
46 typedef char AlignedBufferChar;
49 template <size_t size, size_t alignment> struct AlignedBuffer;
50 template <size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; };
51 template <size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); };
52 template <size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); };
53 template <size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); };
54 template <size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); };
55 template <size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); };
56 template <size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); };
58 template <size_t size, size_t alignment>
59 void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
61 for (size_t i = 0; i < size; ++i)
62 std::swap(a.buffer[i], b.buffer[i]);
65 template <bool needsDestruction, typename T>
66 struct VectorDestructor;
69 struct VectorDestructor<false, T>
71 static void destruct(T*, T*) {}
75 struct VectorDestructor<true, T>
77 static void destruct(T* begin, T* end)
79 for (T* cur = begin; cur != end; ++cur)
84 template <bool needsInitialization, bool canInitializeWithMemset, typename T>
85 struct VectorInitializer;
87 template<bool ignore, typename T>
88 struct VectorInitializer<false, ignore, T>
90 static void initialize(T*, T*) {}
94 struct VectorInitializer<true, false, T>
96 static void initialize(T* begin, T* end)
98 for (T* cur = begin; cur != end; ++cur)
104 struct VectorInitializer<true, true, T>
106 static void initialize(T* begin, T* end)
108 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
112 template <bool canMoveWithMemcpy, typename T>
116 struct VectorMover<false, T>
118 static void move(const T* src, const T* srcEnd, T* dst)
120 while (src != srcEnd) {
122 #if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
123 const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug.
131 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
134 move(src, srcEnd, dst);
136 T* dstEnd = dst + (srcEnd - src);
137 while (src != srcEnd) {
140 new (dstEnd) T(*srcEnd);
148 struct VectorMover<true, T>
150 static void move(const T* src, const T* srcEnd, T* dst)
152 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
154 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
156 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
160 template <bool canCopyWithMemcpy, typename T>
164 struct VectorCopier<false, T>
166 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
168 while (src != srcEnd) {
177 struct VectorCopier<true, T>
179 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
181 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
185 template <bool canFillWithMemset, typename T>
189 struct VectorFiller<false, T>
191 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
193 while (dst != dstEnd) {
201 struct VectorFiller<true, T>
203 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
205 ASSERT(sizeof(T) == sizeof(char));
206 memset(dst, val, dstEnd - dst);
210 template<bool canCompareWithMemcmp, typename T>
211 struct VectorComparer;
214 struct VectorComparer<false, T>
216 static bool compare(const T* a, const T* b, size_t size)
218 for (size_t i = 0; i < size; ++i)
226 struct VectorComparer<true, T>
228 static bool compare(const T* a, const T* b, size_t size)
230 return memcmp(a, b, sizeof(T) * size) == 0;
235 struct VectorTypeOperations
237 static void destruct(T* begin, T* end)
239 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
242 static void initialize(T* begin, T* end)
244 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
247 static void move(const T* src, const T* srcEnd, T* dst)
249 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
252 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
254 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
257 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
259 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
262 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
264 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
267 static bool compare(const T* a, const T* b, size_t size)
269 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
274 class VectorBufferBase {
275 WTF_MAKE_NONCOPYABLE(VectorBufferBase);
277 void allocateBuffer(size_t newCapacity)
280 m_capacity = newCapacity;
281 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
283 m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
286 bool tryAllocateBuffer(size_t newCapacity)
289 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
293 if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) {
294 m_capacity = newCapacity;
295 m_buffer = newBuffer;
301 void deallocateBuffer(T* bufferToDeallocate)
303 if (m_buffer == bufferToDeallocate) {
307 fastFree(bufferToDeallocate);
310 T* buffer() { return m_buffer; }
311 const T* buffer() const { return m_buffer; }
312 T** bufferSlot() { return &m_buffer; }
313 size_t capacity() const { return m_capacity; }
317 T* buffer = m_buffer;
330 VectorBufferBase(T* buffer, size_t capacity)
332 , m_capacity(capacity)
338 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
345 template<typename T, size_t inlineCapacity>
349 class VectorBuffer<T, 0> : private VectorBufferBase<T> {
351 typedef VectorBufferBase<T> Base;
357 VectorBuffer(size_t capacity)
359 // Calling malloc(0) might take a lock and may actually do an
360 // allocation on some systems (e.g. Brew).
362 allocateBuffer(capacity);
367 deallocateBuffer(buffer());
370 void swap(VectorBuffer<T, 0>& other)
372 std::swap(m_buffer, other.m_buffer);
373 std::swap(m_capacity, other.m_capacity);
376 void restoreInlineBufferIfNeeded() { }
378 using Base::allocateBuffer;
379 using Base::tryAllocateBuffer;
380 using Base::deallocateBuffer;
383 using Base::bufferSlot;
384 using Base::capacity;
386 using Base::releaseBuffer;
388 using Base::m_buffer;
389 using Base::m_capacity;
392 template<typename T, size_t inlineCapacity>
393 class VectorBuffer : private VectorBufferBase<T> {
394 WTF_MAKE_NONCOPYABLE(VectorBuffer);
396 typedef VectorBufferBase<T> Base;
399 : Base(inlineBuffer(), inlineCapacity)
403 VectorBuffer(size_t capacity)
404 : Base(inlineBuffer(), inlineCapacity)
406 if (capacity > inlineCapacity)
407 Base::allocateBuffer(capacity);
412 deallocateBuffer(buffer());
415 void allocateBuffer(size_t newCapacity)
417 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
418 if (newCapacity > inlineCapacity)
419 Base::allocateBuffer(newCapacity);
421 m_buffer = inlineBuffer();
422 m_capacity = inlineCapacity;
426 bool tryAllocateBuffer(size_t newCapacity)
428 if (newCapacity > inlineCapacity)
429 return Base::tryAllocateBuffer(newCapacity);
430 m_buffer = inlineBuffer();
431 m_capacity = inlineCapacity;
435 void deallocateBuffer(T* bufferToDeallocate)
437 if (bufferToDeallocate == inlineBuffer())
439 Base::deallocateBuffer(bufferToDeallocate);
442 void swap(VectorBuffer<T, inlineCapacity>& other)
444 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
445 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
446 std::swap(m_capacity, other.m_capacity);
447 } else if (buffer() == inlineBuffer()) {
448 m_buffer = other.m_buffer;
449 other.m_buffer = other.inlineBuffer();
450 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
451 std::swap(m_capacity, other.m_capacity);
452 } else if (other.buffer() == other.inlineBuffer()) {
453 other.m_buffer = m_buffer;
454 m_buffer = inlineBuffer();
455 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
456 std::swap(m_capacity, other.m_capacity);
458 std::swap(m_buffer, other.m_buffer);
459 std::swap(m_capacity, other.m_capacity);
463 void restoreInlineBufferIfNeeded()
467 m_buffer = inlineBuffer();
468 m_capacity = inlineCapacity;
472 using Base::bufferSlot;
473 using Base::capacity;
477 if (buffer() == inlineBuffer())
479 return Base::releaseBuffer();
483 using Base::m_buffer;
484 using Base::m_capacity;
486 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
487 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
489 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
492 template<typename T, size_t inlineCapacity = 0>
494 WTF_MAKE_FAST_ALLOCATED;
496 typedef VectorBuffer<T, inlineCapacity> Buffer;
497 typedef VectorTypeOperations<T> TypeOperations;
503 typedef const T* const_iterator;
510 explicit Vector(size_t size)
515 TypeOperations::initialize(begin(), end());
520 if (m_size) shrink(0);
523 Vector(const Vector&);
524 template<size_t otherCapacity>
525 Vector(const Vector<T, otherCapacity>&);
527 Vector& operator=(const Vector&);
528 template<size_t otherCapacity>
529 Vector& operator=(const Vector<T, otherCapacity>&);
531 size_t size() const { return m_size; }
532 size_t capacity() const { return m_buffer.capacity(); }
533 bool isEmpty() const { return !size(); }
538 return m_buffer.buffer()[i];
540 const T& at(size_t i) const
543 return m_buffer.buffer()[i];
546 T& operator[](size_t i) { return at(i); }
547 const T& operator[](size_t i) const { return at(i); }
549 T* data() { return m_buffer.buffer(); }
550 const T* data() const { return m_buffer.buffer(); }
551 T** dataSlot() { return m_buffer.bufferSlot(); }
553 iterator begin() { return data(); }
554 iterator end() { return begin() + m_size; }
555 const_iterator begin() const { return data(); }
556 const_iterator end() const { return begin() + m_size; }
558 T& first() { return at(0); }
559 const T& first() const { return at(0); }
560 T& last() { return at(size() - 1); }
561 const T& last() const { return at(size() - 1); }
563 template<typename U> bool contains(const U&) const;
564 template<typename U> size_t find(const U&) const;
565 template<typename U> size_t reverseFind(const U&) const;
567 void shrink(size_t size);
568 void grow(size_t size);
569 void resize(size_t size);
570 void reserveCapacity(size_t newCapacity);
571 bool tryReserveCapacity(size_t newCapacity);
572 void reserveInitialCapacity(size_t initialCapacity);
573 void shrinkCapacity(size_t newCapacity);
574 void shrinkToFit() { shrinkCapacity(size()); }
576 void clear() { shrinkCapacity(0); }
578 template<typename U> void append(const U*, size_t);
579 template<typename U> void append(const U&);
580 template<typename U> void uncheckedAppend(const U& val);
581 template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&);
582 template<typename U> bool tryAppend(const U*, size_t);
584 template<typename U> void insert(size_t position, const U*, size_t);
585 template<typename U> void insert(size_t position, const U&);
586 template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
588 template<typename U> void prepend(const U*, size_t);
589 template<typename U> void prepend(const U&);
590 template<typename U, size_t c> void prepend(const Vector<U, c>&);
592 void remove(size_t position);
593 void remove(size_t position, size_t length);
601 Vector(size_t size, const T& val)
606 TypeOperations::uninitializedFill(begin(), end(), val);
609 void fill(const T&, size_t);
610 void fill(const T& val) { fill(val, size()); }
612 template<typename Iterator> void appendRange(Iterator start, Iterator end);
616 void swap(Vector<T, inlineCapacity>& other)
618 std::swap(m_size, other.m_size);
619 m_buffer.swap(other.m_buffer);
624 void checkConsistency();
627 void expandCapacity(size_t newMinCapacity);
628 const T* expandCapacity(size_t newMinCapacity, const T*);
629 bool tryExpandCapacity(size_t newMinCapacity);
630 const T* tryExpandCapacity(size_t newMinCapacity, const T*);
631 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
639 QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
641 stream << qint64(data.size());
642 foreach (const T& i, data)
648 QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
654 data.reserveCapacity(count);
655 for (qint64 i = 0; i < count; ++i) {
663 template<typename T, size_t inlineCapacity>
664 Vector<T, inlineCapacity>::Vector(const Vector& other)
665 : m_size(other.size())
666 , m_buffer(other.capacity())
669 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
672 template<typename T, size_t inlineCapacity>
673 template<size_t otherCapacity>
674 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
675 : m_size(other.size())
676 , m_buffer(other.capacity())
679 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
682 template<typename T, size_t inlineCapacity>
683 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
688 if (size() > other.size())
689 shrink(other.size());
690 else if (other.size() > capacity()) {
692 reserveCapacity(other.size());
697 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
698 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
703 std::copy(other.begin(), other.begin() + size(), begin());
704 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
705 m_size = other.size();
710 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
712 template<typename T, size_t inlineCapacity>
713 template<size_t otherCapacity>
714 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
716 // If the inline capacities match, we should call the more specific
717 // template. If the inline capacities don't match, the two objects
718 // shouldn't be allocated the same address.
719 ASSERT(!typelessPointersAreEqual(&other, this));
721 if (size() > other.size())
722 shrink(other.size());
723 else if (other.size() > capacity()) {
725 reserveCapacity(other.size());
730 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
731 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
736 std::copy(other.begin(), other.begin() + size(), begin());
737 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
738 m_size = other.size();
743 template<typename T, size_t inlineCapacity>
745 bool Vector<T, inlineCapacity>::contains(const U& value) const
747 return find(value) != notFound;
750 template<typename T, size_t inlineCapacity>
752 size_t Vector<T, inlineCapacity>::find(const U& value) const
754 for (size_t i = 0; i < size(); ++i) {
761 template<typename T, size_t inlineCapacity>
763 size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const
765 for (size_t i = 1; i <= size(); ++i) {
766 const size_t index = size() - i;
767 if (at(index) == value)
773 template<typename T, size_t inlineCapacity>
774 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
776 if (size() > newSize)
778 else if (newSize > capacity()) {
780 reserveCapacity(newSize);
785 std::fill(begin(), end(), val);
786 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
790 template<typename T, size_t inlineCapacity>
791 template<typename Iterator>
792 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
794 for (Iterator it = start; it != end; ++it)
798 template<typename T, size_t inlineCapacity>
799 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
801 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
804 template<typename T, size_t inlineCapacity>
805 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
807 if (ptr < begin() || ptr >= end()) {
808 expandCapacity(newMinCapacity);
811 size_t index = ptr - begin();
812 expandCapacity(newMinCapacity);
813 return begin() + index;
816 template<typename T, size_t inlineCapacity>
817 bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity)
819 return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
822 template<typename T, size_t inlineCapacity>
823 const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr)
825 if (ptr < begin() || ptr >= end()) {
826 if (!tryExpandCapacity(newMinCapacity))
830 size_t index = ptr - begin();
831 if (!tryExpandCapacity(newMinCapacity))
833 return begin() + index;
836 template<typename T, size_t inlineCapacity> template<typename U>
837 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
839 expandCapacity(newMinCapacity);
843 template<typename T, size_t inlineCapacity>
844 inline void Vector<T, inlineCapacity>::resize(size_t size)
847 TypeOperations::destruct(begin() + size, end());
849 if (size > capacity())
850 expandCapacity(size);
852 TypeOperations::initialize(end(), begin() + size);
858 template<typename T, size_t inlineCapacity>
859 void Vector<T, inlineCapacity>::shrink(size_t size)
861 ASSERT(size <= m_size);
862 TypeOperations::destruct(begin() + size, end());
866 template<typename T, size_t inlineCapacity>
867 void Vector<T, inlineCapacity>::grow(size_t size)
869 ASSERT(size >= m_size);
870 if (size > capacity())
871 expandCapacity(size);
873 TypeOperations::initialize(end(), begin() + size);
877 template<typename T, size_t inlineCapacity>
878 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
880 if (newCapacity <= capacity())
882 T* oldBuffer = begin();
884 m_buffer.allocateBuffer(newCapacity);
886 TypeOperations::move(oldBuffer, oldEnd, begin());
887 m_buffer.deallocateBuffer(oldBuffer);
890 template<typename T, size_t inlineCapacity>
891 bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity)
893 if (newCapacity <= capacity())
895 T* oldBuffer = begin();
897 if (!m_buffer.tryAllocateBuffer(newCapacity))
900 TypeOperations::move(oldBuffer, oldEnd, begin());
901 m_buffer.deallocateBuffer(oldBuffer);
905 template<typename T, size_t inlineCapacity>
906 inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
909 ASSERT(capacity() == inlineCapacity);
910 if (initialCapacity > inlineCapacity)
911 m_buffer.allocateBuffer(initialCapacity);
914 template<typename T, size_t inlineCapacity>
915 void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
917 if (newCapacity >= capacity())
920 if (newCapacity < size())
923 T* oldBuffer = begin();
924 if (newCapacity > 0) {
926 m_buffer.allocateBuffer(newCapacity);
927 if (begin() != oldBuffer)
928 TypeOperations::move(oldBuffer, oldEnd, begin());
931 m_buffer.deallocateBuffer(oldBuffer);
932 m_buffer.restoreInlineBufferIfNeeded();
935 // Templatizing these is better than just letting the conversion happen implicitly,
936 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
937 // without refcount thrash.
939 template<typename T, size_t inlineCapacity> template<typename U>
940 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
942 size_t newSize = m_size + dataSize;
943 if (newSize > capacity()) {
944 data = expandCapacity(newSize, data);
948 if (newSize < m_size)
951 for (size_t i = 0; i < dataSize; ++i)
952 new (&dest[i]) T(data[i]);
956 template<typename T, size_t inlineCapacity> template<typename U>
957 bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize)
959 size_t newSize = m_size + dataSize;
960 if (newSize > capacity()) {
961 data = tryExpandCapacity(newSize, data);
966 if (newSize < m_size)
969 for (size_t i = 0; i < dataSize; ++i)
970 new (&dest[i]) T(data[i]);
975 template<typename T, size_t inlineCapacity> template<typename U>
976 ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
979 if (size() == capacity()) {
980 ptr = expandCapacity(size() + 1, ptr);
985 #if COMPILER(MSVC7_OR_LOWER)
986 // FIXME: MSVC7 generates compilation errors when trying to assign
987 // a pointer to a Vector of its base class (i.e. can't downcast). So far
988 // I've been unable to determine any logical reason for this, so I can
989 // only assume it is a bug with the compiler. Casting is a bad solution,
990 // however, because it subverts implicit conversions, so a better
992 new (end()) T(static_cast<T>(*ptr));
999 // This version of append saves a branch in the case where you know that the
1000 // vector's capacity is large enough for the append to succeed.
1002 template<typename T, size_t inlineCapacity> template<typename U>
1003 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
1005 ASSERT(size() < capacity());
1006 const U* ptr = &val;
1007 new (end()) T(*ptr);
1011 // This method should not be called append, a better name would be appendElements.
1012 // It could also be eliminated entirely, and call sites could just use
1013 // appendRange(val.begin(), val.end()).
1014 template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
1015 inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
1017 append(val.begin(), val.size());
1020 template<typename T, size_t inlineCapacity> template<typename U>
1021 void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
1023 ASSERT(position <= size());
1024 size_t newSize = m_size + dataSize;
1025 if (newSize > capacity()) {
1026 data = expandCapacity(newSize, data);
1030 if (newSize < m_size)
1032 T* spot = begin() + position;
1033 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1034 for (size_t i = 0; i < dataSize; ++i)
1035 new (&spot[i]) T(data[i]);
1039 template<typename T, size_t inlineCapacity> template<typename U>
1040 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
1042 ASSERT(position <= size());
1043 const U* data = &val;
1044 if (size() == capacity()) {
1045 data = expandCapacity(size() + 1, data);
1049 T* spot = begin() + position;
1050 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1051 new (spot) T(*data);
1055 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1056 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
1058 insert(position, val.begin(), val.size());
1061 template<typename T, size_t inlineCapacity> template<typename U>
1062 void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
1064 insert(0, data, dataSize);
1067 template<typename T, size_t inlineCapacity> template<typename U>
1068 inline void Vector<T, inlineCapacity>::prepend(const U& val)
1073 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1074 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
1076 insert(0, val.begin(), val.size());
1079 template<typename T, size_t inlineCapacity>
1080 inline void Vector<T, inlineCapacity>::remove(size_t position)
1082 ASSERT(position < size());
1083 T* spot = begin() + position;
1085 TypeOperations::moveOverlapping(spot + 1, end(), spot);
1089 template<typename T, size_t inlineCapacity>
1090 inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
1092 ASSERT(position < size());
1093 ASSERT(position + length <= size());
1094 T* beginSpot = begin() + position;
1095 T* endSpot = beginSpot + length;
1096 TypeOperations::destruct(beginSpot, endSpot);
1097 TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
1101 template<typename T, size_t inlineCapacity>
1102 inline void Vector<T, inlineCapacity>::reverse()
1104 for (size_t i = 0; i < m_size / 2; ++i)
1105 std::swap(at(i), at(m_size - 1 - i));
1108 template<typename T, size_t inlineCapacity>
1109 inline T* Vector<T, inlineCapacity>::releaseBuffer()
1111 T* buffer = m_buffer.releaseBuffer();
1112 if (inlineCapacity && !buffer && m_size) {
1113 // If the vector had some data, but no buffer to release,
1114 // that means it was using the inline buffer. In that case,
1115 // we create a brand new buffer so the caller always gets one.
1116 size_t bytes = m_size * sizeof(T);
1117 buffer = static_cast<T*>(fastMalloc(bytes));
1118 memcpy(buffer, data(), bytes);
1124 template<typename T, size_t inlineCapacity>
1125 inline void Vector<T, inlineCapacity>::checkConsistency()
1127 #if !ASSERT_DISABLED
1128 for (size_t i = 0; i < size(); ++i)
1129 ValueCheck<T>::checkConsistency(at(i));
1133 template<typename T, size_t inlineCapacity>
1134 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
1136 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
1137 iterator end = collection.end();
1138 for (iterator it = collection.begin(); it != end; ++it)
1142 template<typename T, size_t inlineCapacity>
1143 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
1148 template<typename T, size_t inlineCapacity>
1149 bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1151 if (a.size() != b.size())
1154 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
1157 template<typename T, size_t inlineCapacity>
1158 inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1163 #if !ASSERT_DISABLED
1164 template<typename T> struct ValueCheck<Vector<T> > {
1165 typedef Vector<T> TraitType;
1166 static void checkConsistency(const Vector<T>& v)
1168 v.checkConsistency();
1177 #endif // WTF_Vector_h