]>
git.saurik.com Git - apple/javascriptcore.git/blob - wtf/Vector.h
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 "ValueCheck.h"
28 #include "VectorTraits.h"
33 #include <QDataStream>
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)))
46 #define WTF_ALIGN_OF(type) __alignof(type)
47 #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
49 #error WTF_ALIGN macros need alignment control.
52 #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
53 typedef char __attribute__((__may_alias__
)) AlignedBufferChar
;
55 typedef char AlignedBufferChar
;
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); };
67 template <size_t size
, size_t alignment
>
68 void swap(AlignedBuffer
<size
, alignment
>& a
, AlignedBuffer
<size
, alignment
>& b
)
70 for (size_t i
= 0; i
< size
; ++i
)
71 std::swap(a
.buffer
[i
], b
.buffer
[i
]);
74 template <bool needsDestruction
, typename T
>
75 struct VectorDestructor
;
78 struct VectorDestructor
<false, T
>
80 static void destruct(T
*, T
*) {}
84 struct VectorDestructor
<true, T
>
86 static void destruct(T
* begin
, T
* end
)
88 for (T
* cur
= begin
; cur
!= end
; ++cur
)
93 template <bool needsInitialization
, bool canInitializeWithMemset
, typename T
>
94 struct VectorInitializer
;
96 template<bool ignore
, typename T
>
97 struct VectorInitializer
<false, ignore
, T
>
99 static void initialize(T
*, T
*) {}
103 struct VectorInitializer
<true, false, T
>
105 static void initialize(T
* begin
, T
* end
)
107 for (T
* cur
= begin
; cur
!= end
; ++cur
)
113 struct VectorInitializer
<true, true, T
>
115 static void initialize(T
* begin
, T
* end
)
117 memset(begin
, 0, reinterpret_cast<char*>(end
) - reinterpret_cast<char*>(begin
));
121 template <bool canMoveWithMemcpy
, typename T
>
125 struct VectorMover
<false, T
>
127 static void move(const T
* src
, const T
* srcEnd
, T
* dst
)
129 while (src
!= srcEnd
) {
136 static void moveOverlapping(const T
* src
, const T
* srcEnd
, T
* dst
)
139 move(src
, srcEnd
, dst
);
141 T
* dstEnd
= dst
+ (srcEnd
- src
);
142 while (src
!= srcEnd
) {
145 new (dstEnd
) T(*srcEnd
);
153 struct VectorMover
<true, T
>
155 static void move(const T
* src
, const T
* srcEnd
, T
* dst
)
157 memcpy(dst
, src
, reinterpret_cast<const char*>(srcEnd
) - reinterpret_cast<const char*>(src
));
159 static void moveOverlapping(const T
* src
, const T
* srcEnd
, T
* dst
)
161 memmove(dst
, src
, reinterpret_cast<const char*>(srcEnd
) - reinterpret_cast<const char*>(src
));
165 template <bool canCopyWithMemcpy
, typename T
>
169 struct VectorCopier
<false, T
>
171 static void uninitializedCopy(const T
* src
, const T
* srcEnd
, T
* dst
)
173 while (src
!= srcEnd
) {
182 struct VectorCopier
<true, T
>
184 static void uninitializedCopy(const T
* src
, const T
* srcEnd
, T
* dst
)
186 memcpy(dst
, src
, reinterpret_cast<const char*>(srcEnd
) - reinterpret_cast<const char*>(src
));
190 template <bool canFillWithMemset
, typename T
>
194 struct VectorFiller
<false, T
>
196 static void uninitializedFill(T
* dst
, T
* dstEnd
, const T
& val
)
198 while (dst
!= dstEnd
) {
206 struct VectorFiller
<true, T
>
208 static void uninitializedFill(T
* dst
, T
* dstEnd
, const T
& val
)
210 ASSERT(sizeof(T
) == sizeof(char));
211 memset(dst
, val
, dstEnd
- dst
);
215 template<bool canCompareWithMemcmp
, typename T
>
216 struct VectorComparer
;
219 struct VectorComparer
<false, T
>
221 static bool compare(const T
* a
, const T
* b
, size_t size
)
223 for (size_t i
= 0; i
< size
; ++i
)
231 struct VectorComparer
<true, T
>
233 static bool compare(const T
* a
, const T
* b
, size_t size
)
235 return memcmp(a
, b
, sizeof(T
) * size
) == 0;
240 struct VectorTypeOperations
242 static void destruct(T
* begin
, T
* end
)
244 VectorDestructor
<VectorTraits
<T
>::needsDestruction
, T
>::destruct(begin
, end
);
247 static void initialize(T
* begin
, T
* end
)
249 VectorInitializer
<VectorTraits
<T
>::needsInitialization
, VectorTraits
<T
>::canInitializeWithMemset
, T
>::initialize(begin
, end
);
252 static void move(const T
* src
, const T
* srcEnd
, T
* dst
)
254 VectorMover
<VectorTraits
<T
>::canMoveWithMemcpy
, T
>::move(src
, srcEnd
, dst
);
257 static void moveOverlapping(const T
* src
, const T
* srcEnd
, T
* dst
)
259 VectorMover
<VectorTraits
<T
>::canMoveWithMemcpy
, T
>::moveOverlapping(src
, srcEnd
, dst
);
262 static void uninitializedCopy(const T
* src
, const T
* srcEnd
, T
* dst
)
264 VectorCopier
<VectorTraits
<T
>::canCopyWithMemcpy
, T
>::uninitializedCopy(src
, srcEnd
, dst
);
267 static void uninitializedFill(T
* dst
, T
* dstEnd
, const T
& val
)
269 VectorFiller
<VectorTraits
<T
>::canFillWithMemset
, T
>::uninitializedFill(dst
, dstEnd
, val
);
272 static bool compare(const T
* a
, const T
* b
, size_t size
)
274 return VectorComparer
<VectorTraits
<T
>::canCompareWithMemcmp
, T
>::compare(a
, b
, size
);
279 class VectorBufferBase
: public Noncopyable
{
281 void allocateBuffer(size_t newCapacity
)
283 m_capacity
= newCapacity
;
284 if (newCapacity
> std::numeric_limits
<size_t>::max() / sizeof(T
))
286 m_buffer
= static_cast<T
*>(fastMalloc(newCapacity
* sizeof(T
)));
289 void deallocateBuffer(T
* bufferToDeallocate
)
291 if (m_buffer
== bufferToDeallocate
) {
295 fastFree(bufferToDeallocate
);
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
; }
305 T
* buffer
= m_buffer
;
318 VectorBufferBase(T
* buffer
, size_t capacity
)
320 , m_capacity(capacity
)
326 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
333 template<typename T
, size_t inlineCapacity
>
337 class VectorBuffer
<T
, 0> : private VectorBufferBase
<T
> {
339 typedef VectorBufferBase
<T
> Base
;
345 VectorBuffer(size_t capacity
)
347 allocateBuffer(capacity
);
352 deallocateBuffer(buffer());
355 void swap(VectorBuffer
<T
, 0>& other
)
357 std::swap(m_buffer
, other
.m_buffer
);
358 std::swap(m_capacity
, other
.m_capacity
);
361 void restoreInlineBufferIfNeeded() { }
363 using Base::allocateBuffer
;
364 using Base::deallocateBuffer
;
367 using Base::bufferSlot
;
368 using Base::capacity
;
370 using Base::releaseBuffer
;
372 using Base::m_buffer
;
373 using Base::m_capacity
;
376 template<typename T
, size_t inlineCapacity
>
377 class VectorBuffer
: private VectorBufferBase
<T
> {
379 typedef VectorBufferBase
<T
> Base
;
382 : Base(inlineBuffer(), inlineCapacity
)
386 VectorBuffer(size_t capacity
)
387 : Base(inlineBuffer(), inlineCapacity
)
389 if (capacity
> inlineCapacity
)
390 Base::allocateBuffer(capacity
);
395 deallocateBuffer(buffer());
398 void allocateBuffer(size_t newCapacity
)
400 if (newCapacity
> inlineCapacity
)
401 Base::allocateBuffer(newCapacity
);
403 m_buffer
= inlineBuffer();
404 m_capacity
= inlineCapacity
;
408 void deallocateBuffer(T
* bufferToDeallocate
)
410 if (bufferToDeallocate
== inlineBuffer())
412 Base::deallocateBuffer(bufferToDeallocate
);
415 void swap(VectorBuffer
<T
, inlineCapacity
>& other
)
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
);
431 std::swap(m_buffer
, other
.m_buffer
);
432 std::swap(m_capacity
, other
.m_capacity
);
436 void restoreInlineBufferIfNeeded()
440 m_buffer
= inlineBuffer();
441 m_capacity
= inlineCapacity
;
445 using Base::bufferSlot
;
446 using Base::capacity
;
450 if (buffer() == inlineBuffer())
452 return Base::releaseBuffer();
456 using Base::m_buffer
;
457 using Base::m_capacity
;
459 static const size_t m_inlineBufferSize
= inlineCapacity
* sizeof(T
);
461 // FIXME: <rdar://problem/6546253&6546260>
462 T
* inlineBuffer() { return reinterpret_cast<T
*>(static_cast<void*>(m_inlineBuffer
.buffer
)); }
464 T
* inlineBuffer() { return reinterpret_cast<T
*>(m_inlineBuffer
.buffer
); }
467 AlignedBuffer
<m_inlineBufferSize
, WTF_ALIGN_OF(T
)> m_inlineBuffer
;
470 template<typename T
, size_t inlineCapacity
= 0>
471 class Vector
: public FastAllocBase
{
473 typedef VectorBuffer
<T
, inlineCapacity
> Buffer
;
474 typedef VectorTypeOperations
<T
> TypeOperations
;
480 typedef const T
* const_iterator
;
487 explicit Vector(size_t size
)
492 TypeOperations::initialize(begin(), end());
497 if (m_size
) shrink(0);
500 Vector(const Vector
&);
501 template<size_t otherCapacity
>
502 Vector(const Vector
<T
, otherCapacity
>&);
504 Vector
& operator=(const Vector
&);
505 template<size_t otherCapacity
>
506 Vector
& operator=(const Vector
<T
, otherCapacity
>&);
508 size_t size() const { return m_size
; }
509 size_t capacity() const { return m_buffer
.capacity(); }
510 bool isEmpty() const { return !size(); }
515 return m_buffer
.buffer()[i
];
517 const T
& at(size_t i
) const
520 return m_buffer
.buffer()[i
];
523 T
& operator[](size_t i
) { return at(i
); }
524 const T
& operator[](size_t i
) const { return at(i
); }
526 T
* data() { return m_buffer
.buffer(); }
527 const T
* data() const { return m_buffer
.buffer(); }
528 T
** dataSlot() { return m_buffer
.bufferSlot(); }
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
; }
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); }
540 template<typename U
> size_t find(const U
&) const;
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()); }
550 void clear() { shrinkCapacity(0); }
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
>&);
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
>&);
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
>&);
565 void remove(size_t position
);
566 void remove(size_t position
, size_t length
);
574 Vector(size_t size
, const T
& val
)
579 TypeOperations::uninitializedFill(begin(), end(), val
);
582 void fill(const T
&, size_t);
583 void fill(const T
& val
) { fill(val
, size()); }
585 template<typename Iterator
> void appendRange(Iterator start
, Iterator end
);
589 void swap(Vector
<T
, inlineCapacity
>& other
)
591 std::swap(m_size
, other
.m_size
);
592 m_buffer
.swap(other
.m_buffer
);
595 void checkConsistency();
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
*);
608 QDataStream
& operator<<(QDataStream
& stream
, const Vector
<T
>& data
)
610 stream
<< qint64(data
.size());
611 foreach (const T
& i
, data
)
617 QDataStream
& operator>>(QDataStream
& stream
, Vector
<T
>& data
)
623 data
.reserveCapacity(count
);
624 for (qint64 i
= 0; i
< count
; ++i
) {
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())
638 TypeOperations::uninitializedCopy(other
.begin(), other
.end(), begin());
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())
648 TypeOperations::uninitializedCopy(other
.begin(), other
.end(), begin());
651 template<typename T
, size_t inlineCapacity
>
652 Vector
<T
, inlineCapacity
>& Vector
<T
, inlineCapacity
>::operator=(const Vector
<T
, inlineCapacity
>& other
)
657 if (size() > other
.size())
658 shrink(other
.size());
659 else if (other
.size() > capacity()) {
661 reserveCapacity(other
.size());
666 std::copy(other
.begin(), other
.begin() + size(), begin());
667 TypeOperations::uninitializedCopy(other
.begin() + size(), other
.end(), end());
668 m_size
= other
.size();
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
)
680 if (size() > other
.size())
681 shrink(other
.size());
682 else if (other
.size() > capacity()) {
684 reserveCapacity(other
.size());
689 std::copy(other
.begin(), other
.begin() + size(), begin());
690 TypeOperations::uninitializedCopy(other
.begin() + size(), other
.end(), end());
691 m_size
= other
.size();
696 template<typename T
, size_t inlineCapacity
>
698 size_t Vector
<T
, inlineCapacity
>::find(const U
& value
) const
700 for (size_t i
= 0; i
< size(); ++i
) {
707 template<typename T
, size_t inlineCapacity
>
708 void Vector
<T
, inlineCapacity
>::fill(const T
& val
, size_t newSize
)
710 if (size() > newSize
)
712 else if (newSize
> capacity()) {
714 reserveCapacity(newSize
);
719 std::fill(begin(), end(), val
);
720 TypeOperations::uninitializedFill(end(), begin() + newSize
, val
);
724 template<typename T
, size_t inlineCapacity
>
725 template<typename Iterator
>
726 void Vector
<T
, inlineCapacity
>::appendRange(Iterator start
, Iterator end
)
728 for (Iterator it
= start
; it
!= end
; ++it
)
732 template<typename T
, size_t inlineCapacity
>
733 void Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
)
735 reserveCapacity(max(newMinCapacity
, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
738 template<typename T
, size_t inlineCapacity
>
739 const T
* Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
, const T
* ptr
)
741 if (ptr
< begin() || ptr
>= end()) {
742 expandCapacity(newMinCapacity
);
745 size_t index
= ptr
- begin();
746 expandCapacity(newMinCapacity
);
747 return begin() + index
;
750 template<typename T
, size_t inlineCapacity
> template<typename U
>
751 inline U
* Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
, U
* ptr
)
753 expandCapacity(newMinCapacity
);
757 template<typename T
, size_t inlineCapacity
>
758 inline void Vector
<T
, inlineCapacity
>::resize(size_t size
)
761 TypeOperations::destruct(begin() + size
, end());
763 if (size
> capacity())
764 expandCapacity(size
);
766 TypeOperations::initialize(end(), begin() + size
);
772 template<typename T
, size_t inlineCapacity
>
773 void Vector
<T
, inlineCapacity
>::shrink(size_t size
)
775 ASSERT(size
<= m_size
);
776 TypeOperations::destruct(begin() + size
, end());
780 template<typename T
, size_t inlineCapacity
>
781 void Vector
<T
, inlineCapacity
>::grow(size_t size
)
783 ASSERT(size
>= m_size
);
784 if (size
> capacity())
785 expandCapacity(size
);
787 TypeOperations::initialize(end(), begin() + size
);
791 template<typename T
, size_t inlineCapacity
>
792 void Vector
<T
, inlineCapacity
>::reserveCapacity(size_t newCapacity
)
794 if (newCapacity
<= capacity())
796 T
* oldBuffer
= begin();
798 m_buffer
.allocateBuffer(newCapacity
);
800 TypeOperations::move(oldBuffer
, oldEnd
, begin());
801 m_buffer
.deallocateBuffer(oldBuffer
);
804 template<typename T
, size_t inlineCapacity
>
805 inline void Vector
<T
, inlineCapacity
>::reserveInitialCapacity(size_t initialCapacity
)
808 ASSERT(capacity() == inlineCapacity
);
809 if (initialCapacity
> inlineCapacity
)
810 m_buffer
.allocateBuffer(initialCapacity
);
813 template<typename T
, size_t inlineCapacity
>
814 void Vector
<T
, inlineCapacity
>::shrinkCapacity(size_t newCapacity
)
816 if (newCapacity
>= capacity())
819 if (newCapacity
< size())
822 T
* oldBuffer
= begin();
823 if (newCapacity
> 0) {
825 m_buffer
.allocateBuffer(newCapacity
);
826 if (begin() != oldBuffer
)
827 TypeOperations::move(oldBuffer
, oldEnd
, begin());
830 m_buffer
.deallocateBuffer(oldBuffer
);
831 m_buffer
.restoreInlineBufferIfNeeded();
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.
838 template<typename T
, size_t inlineCapacity
> template<typename U
>
839 void Vector
<T
, inlineCapacity
>::append(const U
* data
, size_t dataSize
)
841 size_t newSize
= m_size
+ dataSize
;
842 if (newSize
> capacity()) {
843 data
= expandCapacity(newSize
, data
);
847 if (newSize
< m_size
)
850 for (size_t i
= 0; i
< dataSize
; ++i
)
851 new (&dest
[i
]) T(data
[i
]);
855 template<typename T
, size_t inlineCapacity
> template<typename U
>
856 ALWAYS_INLINE
void Vector
<T
, inlineCapacity
>::append(const U
& val
)
859 if (size() == capacity()) {
860 ptr
= expandCapacity(size() + 1, ptr
);
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
872 new (end()) T(static_cast<T
>(*ptr
));
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.
882 template<typename T
, size_t inlineCapacity
> template<typename U
>
883 inline void Vector
<T
, inlineCapacity
>::uncheckedAppend(const U
& val
)
885 ASSERT(size() < capacity());
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
)
897 append(val
.begin(), val
.size());
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
)
903 ASSERT(position
<= size());
904 size_t newSize
= m_size
+ dataSize
;
905 if (newSize
> capacity()) {
906 data
= expandCapacity(newSize
, data
);
910 if (newSize
< m_size
)
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
]);
919 template<typename T
, size_t inlineCapacity
> template<typename U
>
920 inline void Vector
<T
, inlineCapacity
>::insert(size_t position
, const U
& val
)
922 ASSERT(position
<= size());
923 const U
* data
= &val
;
924 if (size() == capacity()) {
925 data
= expandCapacity(size() + 1, data
);
929 T
* spot
= begin() + position
;
930 TypeOperations::moveOverlapping(spot
, end(), spot
+ 1);
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
)
938 insert(position
, val
.begin(), val
.size());
941 template<typename T
, size_t inlineCapacity
> template<typename U
>
942 void Vector
<T
, inlineCapacity
>::prepend(const U
* data
, size_t dataSize
)
944 insert(0, data
, dataSize
);
947 template<typename T
, size_t inlineCapacity
> template<typename U
>
948 inline void Vector
<T
, inlineCapacity
>::prepend(const U
& val
)
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
)
956 insert(0, val
.begin(), val
.size());
959 template<typename T
, size_t inlineCapacity
>
960 inline void Vector
<T
, inlineCapacity
>::remove(size_t position
)
962 ASSERT(position
< size());
963 T
* spot
= begin() + position
;
965 TypeOperations::moveOverlapping(spot
+ 1, end(), spot
);
969 template<typename T
, size_t inlineCapacity
>
970 inline void Vector
<T
, inlineCapacity
>::remove(size_t position
, size_t length
)
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
);
981 template<typename T
, size_t inlineCapacity
>
982 inline T
* Vector
<T
, inlineCapacity
>::releaseBuffer()
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
);
997 template<typename T
, size_t inlineCapacity
>
998 inline void Vector
<T
, inlineCapacity
>::checkConsistency()
1000 #if !ASSERT_DISABLED
1001 for (size_t i
= 0; i
< size(); ++i
)
1002 ValueCheck
<T
>::checkConsistency(at(i
));
1006 template<typename T
, size_t inlineCapacity
>
1007 void deleteAllValues(const Vector
<T
, inlineCapacity
>& collection
)
1009 typedef typename Vector
<T
, inlineCapacity
>::const_iterator iterator
;
1010 iterator end
= collection
.end();
1011 for (iterator it
= collection
.begin(); it
!= end
; ++it
)
1015 template<typename T
, size_t inlineCapacity
>
1016 inline void swap(Vector
<T
, inlineCapacity
>& a
, Vector
<T
, inlineCapacity
>& b
)
1021 template<typename T
, size_t inlineCapacity
>
1022 bool operator==(const Vector
<T
, inlineCapacity
>& a
, const Vector
<T
, inlineCapacity
>& b
)
1024 if (a
.size() != b
.size())
1027 return VectorTypeOperations
<T
>::compare(a
.data(), b
.data(), a
.size());
1030 template<typename T
, size_t inlineCapacity
>
1031 inline bool operator!=(const Vector
<T
, inlineCapacity
>& a
, const Vector
<T
, inlineCapacity
>& b
)
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
)
1041 v
.checkConsistency();
1050 #endif // WTF_Vector_h