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 <wtf/Alignment.h>
25 #include <wtf/CheckedArithmetic.h>
26 #include <wtf/FastMalloc.h>
27 #include <wtf/MallocPtr.h>
28 #include <wtf/Noncopyable.h>
29 #include <wtf/NotFound.h>
30 #include <wtf/OwnPtr.h>
31 #include <wtf/StdLibExtras.h>
32 #include <wtf/ValueCheck.h>
33 #include <wtf/VectorTraits.h>
40 template <bool needsDestruction, typename T>
41 struct VectorDestructor;
44 struct VectorDestructor<false, T>
46 static void destruct(T*, T*) {}
50 struct VectorDestructor<true, T>
52 static void destruct(T* begin, T* end)
54 for (T* cur = begin; cur != end; ++cur)
59 template <bool needsInitialization, bool canInitializeWithMemset, typename T>
60 struct VectorInitializer;
62 template<bool ignore, typename T>
63 struct VectorInitializer<false, ignore, T>
65 static void initialize(T*, T*) {}
69 struct VectorInitializer<true, false, T>
71 static void initialize(T* begin, T* end)
73 for (T* cur = begin; cur != end; ++cur)
79 struct VectorInitializer<true, true, T>
81 static void initialize(T* begin, T* end)
83 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
87 template <bool canMoveWithMemcpy, typename T>
91 struct VectorMover<false, T>
93 static void move(const T* src, const T* srcEnd, T* dst)
95 while (src != srcEnd) {
96 new (NotNull, dst) T(*src);
97 #if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
98 const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug.
106 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
109 move(src, srcEnd, dst);
111 T* dstEnd = dst + (srcEnd - src);
112 while (src != srcEnd) {
115 new (NotNull, dstEnd) T(*srcEnd);
123 struct VectorMover<true, T>
125 static void move(const T* src, const T* srcEnd, T* dst)
127 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
129 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
131 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
135 template <bool canCopyWithMemcpy, typename T>
139 struct VectorCopier<false, T>
141 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
143 while (src != srcEnd) {
144 new (NotNull, dst) T(*src);
152 struct VectorCopier<true, T>
154 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
156 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
160 template <bool canFillWithMemset, typename T>
164 struct VectorFiller<false, T>
166 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
168 while (dst != dstEnd) {
169 new (NotNull, dst) T(val);
176 struct VectorFiller<true, T>
178 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
180 COMPILE_ASSERT(sizeof(T) == sizeof(char), Size_of_type_should_be_equal_to_one);
181 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE)
182 if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst)))
184 memset(dst, val, dstEnd - dst);
188 template<bool canCompareWithMemcmp, typename T>
189 struct VectorComparer;
192 struct VectorComparer<false, T>
194 static bool compare(const T* a, const T* b, size_t size)
196 for (size_t i = 0; i < size; ++i)
204 struct VectorComparer<true, T>
206 static bool compare(const T* a, const T* b, size_t size)
208 return memcmp(a, b, sizeof(T) * size) == 0;
213 struct VectorTypeOperations
215 static void destruct(T* begin, T* end)
217 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
220 static void initialize(T* begin, T* end)
222 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
225 static void move(const T* src, const T* srcEnd, T* dst)
227 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
230 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
232 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
235 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
237 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
240 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
242 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
245 static bool compare(const T* a, const T* b, size_t size)
247 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
252 class VectorBufferBase {
253 WTF_MAKE_NONCOPYABLE(VectorBufferBase);
255 void allocateBuffer(size_t newCapacity)
258 if (newCapacity > std::numeric_limits<unsigned>::max() / sizeof(T))
260 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
261 m_capacity = sizeToAllocate / sizeof(T);
262 m_buffer = static_cast<T*>(fastMalloc(sizeToAllocate));
265 bool tryAllocateBuffer(size_t newCapacity)
268 if (newCapacity > std::numeric_limits<unsigned>::max() / sizeof(T))
271 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
273 if (tryFastMalloc(sizeToAllocate).getValue(newBuffer)) {
274 m_capacity = sizeToAllocate / sizeof(T);
275 m_buffer = newBuffer;
281 bool shouldReallocateBuffer(size_t newCapacity) const
283 return VectorTraits<T>::canMoveWithMemcpy && m_capacity && newCapacity;
286 void reallocateBuffer(size_t newCapacity)
288 ASSERT(shouldReallocateBuffer(newCapacity));
289 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
291 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
292 m_capacity = sizeToAllocate / sizeof(T);
293 m_buffer = static_cast<T*>(fastRealloc(m_buffer, sizeToAllocate));
296 void deallocateBuffer(T* bufferToDeallocate)
298 if (!bufferToDeallocate)
301 if (m_buffer == bufferToDeallocate) {
306 fastFree(bufferToDeallocate);
309 T* buffer() { return m_buffer; }
310 const T* buffer() const { return m_buffer; }
311 size_t capacity() const { return m_capacity; }
313 MallocPtr<T> releaseBuffer()
315 T* buffer = m_buffer;
318 return adoptMallocPtr(buffer);
329 VectorBufferBase(T* buffer, size_t capacity, size_t size)
331 , m_capacity(capacity)
338 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
343 unsigned m_size; // Only used by the Vector subclass, but placed here to avoid padding the struct.
346 template<typename T, size_t inlineCapacity>
350 class VectorBuffer<T, 0> : private VectorBufferBase<T> {
352 typedef VectorBufferBase<T> Base;
358 VectorBuffer(size_t capacity, size_t size = 0)
361 // Calling malloc(0) might take a lock and may actually do an
362 // allocation on some systems.
364 allocateBuffer(capacity);
369 deallocateBuffer(buffer());
372 void swap(VectorBuffer<T, 0>& other)
374 std::swap(m_buffer, other.m_buffer);
375 std::swap(m_capacity, other.m_capacity);
378 void restoreInlineBufferIfNeeded() { }
380 using Base::allocateBuffer;
381 using Base::tryAllocateBuffer;
382 using Base::shouldReallocateBuffer;
383 using Base::reallocateBuffer;
384 using Base::deallocateBuffer;
387 using Base::capacity;
389 using Base::releaseBuffer;
395 using Base::m_buffer;
396 using Base::m_capacity;
399 template<typename T, size_t inlineCapacity>
400 class VectorBuffer : private VectorBufferBase<T> {
401 WTF_MAKE_NONCOPYABLE(VectorBuffer);
403 typedef VectorBufferBase<T> Base;
406 : Base(inlineBuffer(), inlineCapacity, 0)
410 VectorBuffer(size_t capacity, size_t size = 0)
411 : Base(inlineBuffer(), inlineCapacity, size)
413 if (capacity > inlineCapacity)
414 Base::allocateBuffer(capacity);
419 deallocateBuffer(buffer());
422 void allocateBuffer(size_t newCapacity)
424 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
425 if (newCapacity > inlineCapacity)
426 Base::allocateBuffer(newCapacity);
428 m_buffer = inlineBuffer();
429 m_capacity = inlineCapacity;
433 bool tryAllocateBuffer(size_t newCapacity)
435 if (newCapacity > inlineCapacity)
436 return Base::tryAllocateBuffer(newCapacity);
437 m_buffer = inlineBuffer();
438 m_capacity = inlineCapacity;
442 void deallocateBuffer(T* bufferToDeallocate)
444 if (bufferToDeallocate == inlineBuffer())
446 Base::deallocateBuffer(bufferToDeallocate);
449 bool shouldReallocateBuffer(size_t newCapacity) const
451 // We cannot reallocate the inline buffer.
452 return Base::shouldReallocateBuffer(newCapacity) && std::min(static_cast<size_t>(m_capacity), newCapacity) > inlineCapacity;
455 void reallocateBuffer(size_t newCapacity)
457 ASSERT(shouldReallocateBuffer(newCapacity));
458 Base::reallocateBuffer(newCapacity);
461 void swap(VectorBuffer<T, inlineCapacity>& other)
463 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
464 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
465 std::swap(m_capacity, other.m_capacity);
466 } else if (buffer() == inlineBuffer()) {
467 m_buffer = other.m_buffer;
468 other.m_buffer = other.inlineBuffer();
469 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
470 std::swap(m_capacity, other.m_capacity);
471 } else if (other.buffer() == other.inlineBuffer()) {
472 other.m_buffer = m_buffer;
473 m_buffer = inlineBuffer();
474 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
475 std::swap(m_capacity, other.m_capacity);
477 std::swap(m_buffer, other.m_buffer);
478 std::swap(m_capacity, other.m_capacity);
482 void restoreInlineBufferIfNeeded()
486 m_buffer = inlineBuffer();
487 m_capacity = inlineCapacity;
491 using Base::capacity;
493 MallocPtr<T> releaseBuffer()
495 if (buffer() == inlineBuffer())
497 return Base::releaseBuffer();
504 using Base::m_buffer;
505 using Base::m_capacity;
507 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
508 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
509 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inlineBuffer.buffer); }
511 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
514 struct UnsafeVectorOverflow {
515 static NO_RETURN_DUE_TO_ASSERT void overflowed()
517 ASSERT_NOT_REACHED();
521 template<typename T, size_t inlineCapacity = 0, typename OverflowHandler = CrashOnOverflow>
522 class Vector : private VectorBuffer<T, inlineCapacity> {
523 WTF_MAKE_FAST_ALLOCATED;
525 typedef VectorBuffer<T, inlineCapacity> Base;
526 typedef VectorTypeOperations<T> TypeOperations;
532 typedef const T* const_iterator;
533 typedef std::reverse_iterator<iterator> reverse_iterator;
534 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
540 explicit Vector(size_t size)
544 TypeOperations::initialize(begin(), end());
547 Vector(size_t size, const T& val)
551 TypeOperations::uninitializedFill(begin(), end(), val);
560 Vector(const Vector&);
561 template<size_t otherCapacity, typename otherOverflowBehaviour>
562 Vector(const Vector<T, otherCapacity, otherOverflowBehaviour>&);
564 Vector& operator=(const Vector&);
565 template<size_t otherCapacity, typename otherOverflowBehaviour>
566 Vector& operator=(const Vector<T, otherCapacity, otherOverflowBehaviour>&);
568 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
570 Vector& operator=(Vector&&);
573 size_t size() const { return m_size; }
574 size_t capacity() const { return Base::capacity(); }
575 bool isEmpty() const { return !size(); }
579 if (UNLIKELY(i >= size()))
580 OverflowHandler::overflowed();
581 return Base::buffer()[i];
583 const T& at(size_t i) const
585 if (UNLIKELY(i >= size()))
586 OverflowHandler::overflowed();
587 return Base::buffer()[i];
589 T& at(Checked<size_t> i)
591 RELEASE_ASSERT(i < size());
592 return Base::buffer()[i];
594 const T& at(Checked<size_t> i) const
596 RELEASE_ASSERT(i < size());
597 return Base::buffer()[i];
600 T& operator[](size_t i) { return at(i); }
601 const T& operator[](size_t i) const { return at(i); }
602 T& operator[](Checked<size_t> i) { return at(i); }
603 const T& operator[](Checked<size_t> i) const { return at(i); }
605 T* data() { return Base::buffer(); }
606 const T* data() const { return Base::buffer(); }
608 iterator begin() { return data(); }
609 iterator end() { return begin() + m_size; }
610 const_iterator begin() const { return data(); }
611 const_iterator end() const { return begin() + m_size; }
613 reverse_iterator rbegin() { return reverse_iterator(end()); }
614 reverse_iterator rend() { return reverse_iterator(begin()); }
615 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
616 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
618 T& first() { return at(0); }
619 const T& first() const { return at(0); }
620 T& last() { return at(size() - 1); }
621 const T& last() const { return at(size() - 1); }
630 template<typename U> bool contains(const U&) const;
631 template<typename U> size_t find(const U&) const;
632 template<typename U> size_t reverseFind(const U&) const;
634 void shrink(size_t size);
635 void grow(size_t size);
636 void resize(size_t size);
637 void resizeToFit(size_t size);
638 void reserveCapacity(size_t newCapacity);
639 bool tryReserveCapacity(size_t newCapacity);
640 void reserveInitialCapacity(size_t initialCapacity);
641 void shrinkCapacity(size_t newCapacity);
642 void shrinkToFit() { shrinkCapacity(size()); }
644 void clear() { shrinkCapacity(0); }
646 template<typename U> void append(const U*, size_t);
647 template<typename U> void append(const U&);
648 template<typename U> void uncheckedAppend(U&& val);
649 template<typename U, size_t otherCapacity> void appendVector(const Vector<U, otherCapacity>&);
650 template<typename U> bool tryAppend(const U*, size_t);
652 template<typename U> void insert(size_t position, const U*, size_t);
653 template<typename U> void insert(size_t position, const U&);
654 template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
656 void remove(size_t position);
657 void remove(size_t position, size_t length);
661 if (UNLIKELY(isEmpty()))
662 OverflowHandler::overflowed();
666 void fill(const T&, size_t);
667 void fill(const T& val) { fill(val, size()); }
669 template<typename Iterator> void appendRange(Iterator start, Iterator end);
671 MallocPtr<T> releaseBuffer();
673 void swap(Vector<T, inlineCapacity, OverflowHandler>& other)
675 std::swap(m_size, other.m_size);
681 void checkConsistency();
684 void expandCapacity(size_t newMinCapacity);
685 const T* expandCapacity(size_t newMinCapacity, const T*);
686 bool tryExpandCapacity(size_t newMinCapacity);
687 const T* tryExpandCapacity(size_t newMinCapacity, const T*);
688 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
689 template<typename U> void appendSlowCase(const U&);
693 using Base::capacity;
695 using Base::allocateBuffer;
696 using Base::deallocateBuffer;
697 using Base::tryAllocateBuffer;
698 using Base::shouldReallocateBuffer;
699 using Base::reallocateBuffer;
700 using Base::restoreInlineBufferIfNeeded;
701 using Base::releaseBuffer;
704 template<typename T, size_t inlineCapacity, typename OverflowHandler>
705 Vector<T, inlineCapacity, OverflowHandler>::Vector(const Vector& other)
706 : Base(other.capacity(), other.size())
709 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
712 template<typename T, size_t inlineCapacity, typename OverflowHandler>
713 template<size_t otherCapacity, typename otherOverflowBehaviour>
714 Vector<T, inlineCapacity, OverflowHandler>::Vector(const Vector<T, otherCapacity, otherOverflowBehaviour>& other)
715 : Base(other.capacity(), other.size())
718 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
721 template<typename T, size_t inlineCapacity, typename OverflowHandler>
722 Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(const Vector<T, inlineCapacity, OverflowHandler>& other)
727 if (size() > other.size())
728 shrink(other.size());
729 else if (other.size() > capacity()) {
731 reserveCapacity(other.size());
736 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
737 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
742 std::copy(other.begin(), other.begin() + size(), begin());
743 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
744 m_size = other.size();
749 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
751 template<typename T, size_t inlineCapacity, typename OverflowHandler>
752 template<size_t otherCapacity, typename otherOverflowBehaviour>
753 Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(const Vector<T, otherCapacity, otherOverflowBehaviour>& other)
755 // If the inline capacities match, we should call the more specific
756 // template. If the inline capacities don't match, the two objects
757 // shouldn't be allocated the same address.
758 ASSERT(!typelessPointersAreEqual(&other, this));
760 if (size() > other.size())
761 shrink(other.size());
762 else if (other.size() > capacity()) {
764 reserveCapacity(other.size());
769 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
770 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
775 std::copy(other.begin(), other.begin() + size(), begin());
776 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
777 m_size = other.size();
782 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
783 template<typename T, size_t inlineCapacity, typename OverflowHandler>
784 Vector<T, inlineCapacity, OverflowHandler>::Vector(Vector<T, inlineCapacity, OverflowHandler>&& other)
786 // It's a little weird to implement a move constructor using swap but this way we
787 // don't have to add a move constructor to VectorBuffer.
791 template<typename T, size_t inlineCapacity, typename OverflowHandler>
792 Vector<T, inlineCapacity, OverflowHandler>& Vector<T, inlineCapacity, OverflowHandler>::operator=(Vector<T, inlineCapacity, OverflowHandler>&& other)
799 template<typename T, size_t inlineCapacity, typename OverflowHandler>
801 bool Vector<T, inlineCapacity, OverflowHandler>::contains(const U& value) const
803 return find(value) != notFound;
806 template<typename T, size_t inlineCapacity, typename OverflowHandler>
808 size_t Vector<T, inlineCapacity, OverflowHandler>::find(const U& value) const
810 for (size_t i = 0; i < size(); ++i) {
817 template<typename T, size_t inlineCapacity, typename OverflowHandler>
819 size_t Vector<T, inlineCapacity, OverflowHandler>::reverseFind(const U& value) const
821 for (size_t i = 1; i <= size(); ++i) {
822 const size_t index = size() - i;
823 if (at(index) == value)
829 template<typename T, size_t inlineCapacity, typename OverflowHandler>
830 void Vector<T, inlineCapacity, OverflowHandler>::fill(const T& val, size_t newSize)
832 if (size() > newSize)
834 else if (newSize > capacity()) {
836 reserveCapacity(newSize);
841 std::fill(begin(), end(), val);
842 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
846 template<typename T, size_t inlineCapacity, typename OverflowHandler>
847 template<typename Iterator>
848 void Vector<T, inlineCapacity, OverflowHandler>::appendRange(Iterator start, Iterator end)
850 for (Iterator it = start; it != end; ++it)
854 template<typename T, size_t inlineCapacity, typename OverflowHandler>
855 void Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity)
857 reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
860 template<typename T, size_t inlineCapacity, typename OverflowHandler>
861 const T* Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity, const T* ptr)
863 if (ptr < begin() || ptr >= end()) {
864 expandCapacity(newMinCapacity);
867 size_t index = ptr - begin();
868 expandCapacity(newMinCapacity);
869 return begin() + index;
872 template<typename T, size_t inlineCapacity, typename OverflowHandler>
873 bool Vector<T, inlineCapacity, OverflowHandler>::tryExpandCapacity(size_t newMinCapacity)
875 return tryReserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
878 template<typename T, size_t inlineCapacity, typename OverflowHandler>
879 const T* Vector<T, inlineCapacity, OverflowHandler>::tryExpandCapacity(size_t newMinCapacity, const T* ptr)
881 if (ptr < begin() || ptr >= end()) {
882 if (!tryExpandCapacity(newMinCapacity))
886 size_t index = ptr - begin();
887 if (!tryExpandCapacity(newMinCapacity))
889 return begin() + index;
892 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
893 inline U* Vector<T, inlineCapacity, OverflowHandler>::expandCapacity(size_t newMinCapacity, U* ptr)
895 expandCapacity(newMinCapacity);
899 template<typename T, size_t inlineCapacity, typename OverflowHandler>
900 inline void Vector<T, inlineCapacity, OverflowHandler>::resize(size_t size)
903 TypeOperations::destruct(begin() + size, end());
905 if (size > capacity())
906 expandCapacity(size);
908 TypeOperations::initialize(end(), begin() + size);
914 template<typename T, size_t inlineCapacity, typename OverflowHandler>
915 void Vector<T, inlineCapacity, OverflowHandler>::resizeToFit(size_t size)
917 reserveCapacity(size);
921 template<typename T, size_t inlineCapacity, typename OverflowHandler>
922 void Vector<T, inlineCapacity, OverflowHandler>::shrink(size_t size)
924 ASSERT(size <= m_size);
925 TypeOperations::destruct(begin() + size, end());
929 template<typename T, size_t inlineCapacity, typename OverflowHandler>
930 void Vector<T, inlineCapacity, OverflowHandler>::grow(size_t size)
932 ASSERT(size >= m_size);
933 if (size > capacity())
934 expandCapacity(size);
936 TypeOperations::initialize(end(), begin() + size);
940 template<typename T, size_t inlineCapacity, typename OverflowHandler>
941 void Vector<T, inlineCapacity, OverflowHandler>::reserveCapacity(size_t newCapacity)
943 if (newCapacity <= capacity())
945 T* oldBuffer = begin();
947 Base::allocateBuffer(newCapacity);
949 TypeOperations::move(oldBuffer, oldEnd, begin());
950 Base::deallocateBuffer(oldBuffer);
953 template<typename T, size_t inlineCapacity, typename OverflowHandler>
954 bool Vector<T, inlineCapacity, OverflowHandler>::tryReserveCapacity(size_t newCapacity)
956 if (newCapacity <= capacity())
958 T* oldBuffer = begin();
960 if (!Base::tryAllocateBuffer(newCapacity))
963 TypeOperations::move(oldBuffer, oldEnd, begin());
964 Base::deallocateBuffer(oldBuffer);
968 template<typename T, size_t inlineCapacity, typename OverflowHandler>
969 inline void Vector<T, inlineCapacity, OverflowHandler>::reserveInitialCapacity(size_t initialCapacity)
972 ASSERT(capacity() == inlineCapacity);
973 if (initialCapacity > inlineCapacity)
974 Base::allocateBuffer(initialCapacity);
977 template<typename T, size_t inlineCapacity, typename OverflowHandler>
978 void Vector<T, inlineCapacity, OverflowHandler>::shrinkCapacity(size_t newCapacity)
980 if (newCapacity >= capacity())
983 if (newCapacity < size())
986 T* oldBuffer = begin();
987 if (newCapacity > 0) {
988 if (Base::shouldReallocateBuffer(newCapacity)) {
989 Base::reallocateBuffer(newCapacity);
994 Base::allocateBuffer(newCapacity);
995 if (begin() != oldBuffer)
996 TypeOperations::move(oldBuffer, oldEnd, begin());
999 Base::deallocateBuffer(oldBuffer);
1000 Base::restoreInlineBufferIfNeeded();
1003 // Templatizing these is better than just letting the conversion happen implicitly,
1004 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
1005 // without refcount thrash.
1007 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1008 void Vector<T, inlineCapacity, OverflowHandler>::append(const U* data, size_t dataSize)
1010 size_t newSize = m_size + dataSize;
1011 if (newSize > capacity()) {
1012 data = expandCapacity(newSize, data);
1016 if (newSize < m_size)
1019 for (size_t i = 0; i < dataSize; ++i)
1020 new (NotNull, &dest[i]) T(data[i]);
1024 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1025 bool Vector<T, inlineCapacity, OverflowHandler>::tryAppend(const U* data, size_t dataSize)
1027 size_t newSize = m_size + dataSize;
1028 if (newSize > capacity()) {
1029 data = tryExpandCapacity(newSize, data);
1034 if (newSize < m_size)
1037 for (size_t i = 0; i < dataSize; ++i)
1038 new (NotNull, &dest[i]) T(data[i]);
1043 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1044 ALWAYS_INLINE void Vector<T, inlineCapacity, OverflowHandler>::append(const U& val)
1046 if (size() != capacity()) {
1047 new (NotNull, end()) T(val);
1052 appendSlowCase(val);
1055 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1056 void Vector<T, inlineCapacity, OverflowHandler>::appendSlowCase(const U& val)
1058 ASSERT(size() == capacity());
1060 const U* ptr = &val;
1061 ptr = expandCapacity(size() + 1, ptr);
1065 new (NotNull, end()) T(*ptr);
1069 // This version of append saves a branch in the case where you know that the
1070 // vector's capacity is large enough for the append to succeed.
1072 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1073 inline void Vector<T, inlineCapacity, OverflowHandler>::uncheckedAppend(U&& val)
1075 ASSERT(size() < capacity());
1076 typename std::remove_reference<U>::type* ptr = &val;
1077 new (NotNull, end()) T(std::forward<U>(*ptr));
1081 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U, size_t otherCapacity>
1082 inline void Vector<T, inlineCapacity, OverflowHandler>::appendVector(const Vector<U, otherCapacity>& val)
1084 append(val.begin(), val.size());
1087 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1088 void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const U* data, size_t dataSize)
1090 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1091 size_t newSize = m_size + dataSize;
1092 if (newSize > capacity()) {
1093 data = expandCapacity(newSize, data);
1097 if (newSize < m_size)
1099 T* spot = begin() + position;
1100 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1101 for (size_t i = 0; i < dataSize; ++i)
1102 new (NotNull, &spot[i]) T(data[i]);
1106 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U>
1107 inline void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const U& val)
1109 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1110 const U* data = &val;
1111 if (size() == capacity()) {
1112 data = expandCapacity(size() + 1, data);
1116 T* spot = begin() + position;
1117 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1118 new (NotNull, spot) T(*data);
1122 template<typename T, size_t inlineCapacity, typename OverflowHandler> template<typename U, size_t c>
1123 inline void Vector<T, inlineCapacity, OverflowHandler>::insert(size_t position, const Vector<U, c>& val)
1125 insert(position, val.begin(), val.size());
1128 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1129 inline void Vector<T, inlineCapacity, OverflowHandler>::remove(size_t position)
1131 ASSERT_WITH_SECURITY_IMPLICATION(position < size());
1132 T* spot = begin() + position;
1134 TypeOperations::moveOverlapping(spot + 1, end(), spot);
1138 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1139 inline void Vector<T, inlineCapacity, OverflowHandler>::remove(size_t position, size_t length)
1141 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1142 ASSERT_WITH_SECURITY_IMPLICATION(position + length <= size());
1143 T* beginSpot = begin() + position;
1144 T* endSpot = beginSpot + length;
1145 TypeOperations::destruct(beginSpot, endSpot);
1146 TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
1150 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1151 inline void Vector<T, inlineCapacity, OverflowHandler>::reverse()
1153 for (size_t i = 0; i < m_size / 2; ++i)
1154 std::swap(at(i), at(m_size - 1 - i));
1157 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1158 inline MallocPtr<T> Vector<T, inlineCapacity, OverflowHandler>::releaseBuffer()
1160 auto buffer = Base::releaseBuffer();
1161 if (inlineCapacity && !buffer && m_size) {
1162 // If the vector had some data, but no buffer to release,
1163 // that means it was using the inline buffer. In that case,
1164 // we create a brand new buffer so the caller always gets one.
1165 size_t bytes = m_size * sizeof(T);
1166 buffer = adoptMallocPtr(static_cast<T*>(fastMalloc(bytes)));
1167 memcpy(buffer.get(), data(), bytes);
1173 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1174 inline void Vector<T, inlineCapacity, OverflowHandler>::checkConsistency()
1176 #if !ASSERT_DISABLED
1177 for (size_t i = 0; i < size(); ++i)
1178 ValueCheck<T>::checkConsistency(at(i));
1182 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1183 void deleteAllValues(const Vector<T, inlineCapacity, OverflowHandler>& collection)
1185 typedef typename Vector<T, inlineCapacity, OverflowHandler>::const_iterator iterator;
1186 iterator end = collection.end();
1187 for (iterator it = collection.begin(); it != end; ++it)
1191 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1192 inline void swap(Vector<T, inlineCapacity, OverflowHandler>& a, Vector<T, inlineCapacity, OverflowHandler>& b)
1197 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1198 bool operator==(const Vector<T, inlineCapacity, OverflowHandler>& a, const Vector<T, inlineCapacity, OverflowHandler>& b)
1200 if (a.size() != b.size())
1203 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
1206 template<typename T, size_t inlineCapacity, typename OverflowHandler>
1207 inline bool operator!=(const Vector<T, inlineCapacity, OverflowHandler>& a, const Vector<T, inlineCapacity, OverflowHandler>& b)
1212 #if !ASSERT_DISABLED
1213 template<typename T> struct ValueCheck<Vector<T> > {
1214 typedef Vector<T> TraitType;
1215 static void checkConsistency(const Vector<T>& v)
1217 v.checkConsistency();
1225 using WTF::UnsafeVectorOverflow;
1227 #endif // WTF_Vector_h