]>
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 bool tryAllocateBuffer(size_t newCapacity
)
291 if (newCapacity
> std::numeric_limits
<size_t>::max() / sizeof(T
))
295 if (tryFastMalloc(newCapacity
* sizeof(T
)).getValue(newBuffer
)) {
296 m_capacity
= newCapacity
;
297 m_buffer
= newBuffer
;
303 void deallocateBuffer(T
* bufferToDeallocate
)
305 if (m_buffer
== bufferToDeallocate
) {
309 fastFree(bufferToDeallocate
);
312 T
* buffer() { return m_buffer
; }
313 const T
* buffer() const { return m_buffer
; }
314 T
** bufferSlot() { return &m_buffer
; }
315 size_t capacity() const { return m_capacity
; }
319 T
* buffer
= m_buffer
;
332 VectorBufferBase(T
* buffer
, size_t capacity
)
334 , m_capacity(capacity
)
340 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
347 template<typename T
, size_t inlineCapacity
>
351 class VectorBuffer
<T
, 0> : private VectorBufferBase
<T
> {
353 typedef VectorBufferBase
<T
> Base
;
359 VectorBuffer(size_t capacity
)
361 allocateBuffer(capacity
);
366 deallocateBuffer(buffer());
369 void swap(VectorBuffer
<T
, 0>& other
)
371 std::swap(m_buffer
, other
.m_buffer
);
372 std::swap(m_capacity
, other
.m_capacity
);
375 void restoreInlineBufferIfNeeded() { }
377 using Base::allocateBuffer
;
378 using Base::tryAllocateBuffer
;
379 using Base::deallocateBuffer
;
382 using Base::bufferSlot
;
383 using Base::capacity
;
385 using Base::releaseBuffer
;
387 using Base::m_buffer
;
388 using Base::m_capacity
;
391 template<typename T
, size_t inlineCapacity
>
392 class VectorBuffer
: private VectorBufferBase
<T
> {
394 typedef VectorBufferBase
<T
> Base
;
397 : Base(inlineBuffer(), inlineCapacity
)
401 VectorBuffer(size_t capacity
)
402 : Base(inlineBuffer(), inlineCapacity
)
404 if (capacity
> inlineCapacity
)
405 Base::allocateBuffer(capacity
);
410 deallocateBuffer(buffer());
413 void allocateBuffer(size_t newCapacity
)
415 if (newCapacity
> inlineCapacity
)
416 Base::allocateBuffer(newCapacity
);
418 m_buffer
= inlineBuffer();
419 m_capacity
= inlineCapacity
;
423 bool tryAllocateBuffer(size_t newCapacity
)
425 if (newCapacity
> inlineCapacity
)
426 return Base::tryAllocateBuffer(newCapacity
);
427 m_buffer
= inlineBuffer();
428 m_capacity
= inlineCapacity
;
432 void deallocateBuffer(T
* bufferToDeallocate
)
434 if (bufferToDeallocate
== inlineBuffer())
436 Base::deallocateBuffer(bufferToDeallocate
);
439 void swap(VectorBuffer
<T
, inlineCapacity
>& other
)
441 if (buffer() == inlineBuffer() && other
.buffer() == other
.inlineBuffer()) {
442 WTF::swap(m_inlineBuffer
, other
.m_inlineBuffer
);
443 std::swap(m_capacity
, other
.m_capacity
);
444 } else if (buffer() == inlineBuffer()) {
445 m_buffer
= other
.m_buffer
;
446 other
.m_buffer
= other
.inlineBuffer();
447 WTF::swap(m_inlineBuffer
, other
.m_inlineBuffer
);
448 std::swap(m_capacity
, other
.m_capacity
);
449 } else if (other
.buffer() == other
.inlineBuffer()) {
450 other
.m_buffer
= m_buffer
;
451 m_buffer
= inlineBuffer();
452 WTF::swap(m_inlineBuffer
, other
.m_inlineBuffer
);
453 std::swap(m_capacity
, other
.m_capacity
);
455 std::swap(m_buffer
, other
.m_buffer
);
456 std::swap(m_capacity
, other
.m_capacity
);
460 void restoreInlineBufferIfNeeded()
464 m_buffer
= inlineBuffer();
465 m_capacity
= inlineCapacity
;
469 using Base::bufferSlot
;
470 using Base::capacity
;
474 if (buffer() == inlineBuffer())
476 return Base::releaseBuffer();
480 using Base::m_buffer
;
481 using Base::m_capacity
;
483 static const size_t m_inlineBufferSize
= inlineCapacity
* sizeof(T
);
485 // FIXME: <rdar://problem/6546253&6546260>
486 T
* inlineBuffer() { return reinterpret_cast<T
*>(static_cast<void*>(m_inlineBuffer
.buffer
)); }
488 T
* inlineBuffer() { return reinterpret_cast<T
*>(m_inlineBuffer
.buffer
); }
491 AlignedBuffer
<m_inlineBufferSize
, WTF_ALIGN_OF(T
)> m_inlineBuffer
;
494 template<typename T
, size_t inlineCapacity
= 0>
495 class Vector
: public FastAllocBase
{
497 typedef VectorBuffer
<T
, inlineCapacity
> Buffer
;
498 typedef VectorTypeOperations
<T
> TypeOperations
;
504 typedef const T
* const_iterator
;
511 explicit Vector(size_t size
)
516 TypeOperations::initialize(begin(), end());
521 if (m_size
) shrink(0);
524 Vector(const Vector
&);
525 template<size_t otherCapacity
>
526 Vector(const Vector
<T
, otherCapacity
>&);
528 Vector
& operator=(const Vector
&);
529 template<size_t otherCapacity
>
530 Vector
& operator=(const Vector
<T
, otherCapacity
>&);
532 size_t size() const { return m_size
; }
533 size_t capacity() const { return m_buffer
.capacity(); }
534 bool isEmpty() const { return !size(); }
539 return m_buffer
.buffer()[i
];
541 const T
& at(size_t i
) const
544 return m_buffer
.buffer()[i
];
547 T
& operator[](size_t i
) { return at(i
); }
548 const T
& operator[](size_t i
) const { return at(i
); }
550 T
* data() { return m_buffer
.buffer(); }
551 const T
* data() const { return m_buffer
.buffer(); }
552 T
** dataSlot() { return m_buffer
.bufferSlot(); }
554 iterator
begin() { return data(); }
555 iterator
end() { return begin() + m_size
; }
556 const_iterator
begin() const { return data(); }
557 const_iterator
end() const { return begin() + m_size
; }
559 T
& first() { return at(0); }
560 const T
& first() const { return at(0); }
561 T
& last() { return at(size() - 1); }
562 const T
& last() const { return at(size() - 1); }
564 template<typename U
> size_t find(const U
&) const;
566 void shrink(size_t size
);
567 void grow(size_t size
);
568 void resize(size_t size
);
569 void reserveCapacity(size_t newCapacity
);
570 bool tryReserveCapacity(size_t newCapacity
);
571 void reserveInitialCapacity(size_t initialCapacity
);
572 void shrinkCapacity(size_t newCapacity
);
573 void shrinkToFit() { shrinkCapacity(size()); }
575 void clear() { shrinkCapacity(0); }
577 template<typename U
> void append(const U
*, size_t);
578 template<typename U
> void append(const U
&);
579 template<typename U
> void uncheckedAppend(const U
& val
);
580 template<size_t otherCapacity
> void append(const Vector
<T
, otherCapacity
>&);
581 template<typename U
> bool tryAppend(const U
*, size_t);
583 template<typename U
> void insert(size_t position
, const U
*, size_t);
584 template<typename U
> void insert(size_t position
, const U
&);
585 template<typename U
, size_t c
> void insert(size_t position
, const Vector
<U
, c
>&);
587 template<typename U
> void prepend(const U
*, size_t);
588 template<typename U
> void prepend(const U
&);
589 template<typename U
, size_t c
> void prepend(const Vector
<U
, c
>&);
591 void remove(size_t position
);
592 void remove(size_t position
, size_t length
);
600 Vector(size_t size
, const T
& val
)
605 TypeOperations::uninitializedFill(begin(), end(), val
);
608 void fill(const T
&, size_t);
609 void fill(const T
& val
) { fill(val
, size()); }
611 template<typename Iterator
> void appendRange(Iterator start
, Iterator end
);
615 void swap(Vector
<T
, inlineCapacity
>& other
)
617 std::swap(m_size
, other
.m_size
);
618 m_buffer
.swap(other
.m_buffer
);
621 void checkConsistency();
624 void expandCapacity(size_t newMinCapacity
);
625 const T
* expandCapacity(size_t newMinCapacity
, const T
*);
626 bool tryExpandCapacity(size_t newMinCapacity
);
627 const T
* tryExpandCapacity(size_t newMinCapacity
, const T
*);
628 template<typename U
> U
* expandCapacity(size_t newMinCapacity
, U
*);
636 QDataStream
& operator<<(QDataStream
& stream
, const Vector
<T
>& data
)
638 stream
<< qint64(data
.size());
639 foreach (const T
& i
, data
)
645 QDataStream
& operator>>(QDataStream
& stream
, Vector
<T
>& data
)
651 data
.reserveCapacity(count
);
652 for (qint64 i
= 0; i
< count
; ++i
) {
660 template<typename T
, size_t inlineCapacity
>
661 Vector
<T
, inlineCapacity
>::Vector(const Vector
& other
)
662 : m_size(other
.size())
663 , m_buffer(other
.capacity())
666 TypeOperations::uninitializedCopy(other
.begin(), other
.end(), begin());
669 template<typename T
, size_t inlineCapacity
>
670 template<size_t otherCapacity
>
671 Vector
<T
, inlineCapacity
>::Vector(const Vector
<T
, otherCapacity
>& other
)
672 : m_size(other
.size())
673 , m_buffer(other
.capacity())
676 TypeOperations::uninitializedCopy(other
.begin(), other
.end(), begin());
679 template<typename T
, size_t inlineCapacity
>
680 Vector
<T
, inlineCapacity
>& Vector
<T
, inlineCapacity
>::operator=(const Vector
<T
, inlineCapacity
>& other
)
685 if (size() > other
.size())
686 shrink(other
.size());
687 else if (other
.size() > capacity()) {
689 reserveCapacity(other
.size());
694 std::copy(other
.begin(), other
.begin() + size(), begin());
695 TypeOperations::uninitializedCopy(other
.begin() + size(), other
.end(), end());
696 m_size
= other
.size();
701 template<typename T
, size_t inlineCapacity
>
702 template<size_t otherCapacity
>
703 Vector
<T
, inlineCapacity
>& Vector
<T
, inlineCapacity
>::operator=(const Vector
<T
, otherCapacity
>& other
)
708 if (size() > other
.size())
709 shrink(other
.size());
710 else if (other
.size() > capacity()) {
712 reserveCapacity(other
.size());
717 std::copy(other
.begin(), other
.begin() + size(), begin());
718 TypeOperations::uninitializedCopy(other
.begin() + size(), other
.end(), end());
719 m_size
= other
.size();
724 template<typename T
, size_t inlineCapacity
>
726 size_t Vector
<T
, inlineCapacity
>::find(const U
& value
) const
728 for (size_t i
= 0; i
< size(); ++i
) {
735 template<typename T
, size_t inlineCapacity
>
736 void Vector
<T
, inlineCapacity
>::fill(const T
& val
, size_t newSize
)
738 if (size() > newSize
)
740 else if (newSize
> capacity()) {
742 reserveCapacity(newSize
);
747 std::fill(begin(), end(), val
);
748 TypeOperations::uninitializedFill(end(), begin() + newSize
, val
);
752 template<typename T
, size_t inlineCapacity
>
753 template<typename Iterator
>
754 void Vector
<T
, inlineCapacity
>::appendRange(Iterator start
, Iterator end
)
756 for (Iterator it
= start
; it
!= end
; ++it
)
760 template<typename T
, size_t inlineCapacity
>
761 void Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
)
763 reserveCapacity(max(newMinCapacity
, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
766 template<typename T
, size_t inlineCapacity
>
767 const T
* Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
, const T
* ptr
)
769 if (ptr
< begin() || ptr
>= end()) {
770 expandCapacity(newMinCapacity
);
773 size_t index
= ptr
- begin();
774 expandCapacity(newMinCapacity
);
775 return begin() + index
;
778 template<typename T
, size_t inlineCapacity
>
779 bool Vector
<T
, inlineCapacity
>::tryExpandCapacity(size_t newMinCapacity
)
781 return tryReserveCapacity(max(newMinCapacity
, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
784 template<typename T
, size_t inlineCapacity
>
785 const T
* Vector
<T
, inlineCapacity
>::tryExpandCapacity(size_t newMinCapacity
, const T
* ptr
)
787 if (ptr
< begin() || ptr
>= end()) {
788 if (!tryExpandCapacity(newMinCapacity
))
792 size_t index
= ptr
- begin();
793 if (!tryExpandCapacity(newMinCapacity
))
795 return begin() + index
;
798 template<typename T
, size_t inlineCapacity
> template<typename U
>
799 inline U
* Vector
<T
, inlineCapacity
>::expandCapacity(size_t newMinCapacity
, U
* ptr
)
801 expandCapacity(newMinCapacity
);
805 template<typename T
, size_t inlineCapacity
>
806 inline void Vector
<T
, inlineCapacity
>::resize(size_t size
)
809 TypeOperations::destruct(begin() + size
, end());
811 if (size
> capacity())
812 expandCapacity(size
);
814 TypeOperations::initialize(end(), begin() + size
);
820 template<typename T
, size_t inlineCapacity
>
821 void Vector
<T
, inlineCapacity
>::shrink(size_t size
)
823 ASSERT(size
<= m_size
);
824 TypeOperations::destruct(begin() + size
, end());
828 template<typename T
, size_t inlineCapacity
>
829 void Vector
<T
, inlineCapacity
>::grow(size_t size
)
831 ASSERT(size
>= m_size
);
832 if (size
> capacity())
833 expandCapacity(size
);
835 TypeOperations::initialize(end(), begin() + size
);
839 template<typename T
, size_t inlineCapacity
>
840 void Vector
<T
, inlineCapacity
>::reserveCapacity(size_t newCapacity
)
842 if (newCapacity
<= capacity())
844 T
* oldBuffer
= begin();
846 m_buffer
.allocateBuffer(newCapacity
);
848 TypeOperations::move(oldBuffer
, oldEnd
, begin());
849 m_buffer
.deallocateBuffer(oldBuffer
);
852 template<typename T
, size_t inlineCapacity
>
853 bool Vector
<T
, inlineCapacity
>::tryReserveCapacity(size_t newCapacity
)
855 if (newCapacity
<= capacity())
857 T
* oldBuffer
= begin();
859 if (!m_buffer
.tryAllocateBuffer(newCapacity
))
862 TypeOperations::move(oldBuffer
, oldEnd
, begin());
863 m_buffer
.deallocateBuffer(oldBuffer
);
867 template<typename T
, size_t inlineCapacity
>
868 inline void Vector
<T
, inlineCapacity
>::reserveInitialCapacity(size_t initialCapacity
)
871 ASSERT(capacity() == inlineCapacity
);
872 if (initialCapacity
> inlineCapacity
)
873 m_buffer
.allocateBuffer(initialCapacity
);
876 template<typename T
, size_t inlineCapacity
>
877 void Vector
<T
, inlineCapacity
>::shrinkCapacity(size_t newCapacity
)
879 if (newCapacity
>= capacity())
882 if (newCapacity
< size())
885 T
* oldBuffer
= begin();
886 if (newCapacity
> 0) {
888 m_buffer
.allocateBuffer(newCapacity
);
889 if (begin() != oldBuffer
)
890 TypeOperations::move(oldBuffer
, oldEnd
, begin());
893 m_buffer
.deallocateBuffer(oldBuffer
);
894 m_buffer
.restoreInlineBufferIfNeeded();
897 // Templatizing these is better than just letting the conversion happen implicitly,
898 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
899 // without refcount thrash.
901 template<typename T
, size_t inlineCapacity
> template<typename U
>
902 void Vector
<T
, inlineCapacity
>::append(const U
* data
, size_t dataSize
)
904 size_t newSize
= m_size
+ dataSize
;
905 if (newSize
> capacity()) {
906 data
= expandCapacity(newSize
, data
);
910 if (newSize
< m_size
)
913 for (size_t i
= 0; i
< dataSize
; ++i
)
914 new (&dest
[i
]) T(data
[i
]);
918 template<typename T
, size_t inlineCapacity
> template<typename U
>
919 bool Vector
<T
, inlineCapacity
>::tryAppend(const U
* data
, size_t dataSize
)
921 size_t newSize
= m_size
+ dataSize
;
922 if (newSize
> capacity()) {
923 data
= tryExpandCapacity(newSize
, data
);
928 if (newSize
< m_size
)
931 for (size_t i
= 0; i
< dataSize
; ++i
)
932 new (&dest
[i
]) T(data
[i
]);
937 template<typename T
, size_t inlineCapacity
> template<typename U
>
938 ALWAYS_INLINE
void Vector
<T
, inlineCapacity
>::append(const U
& val
)
941 if (size() == capacity()) {
942 ptr
= expandCapacity(size() + 1, ptr
);
947 #if COMPILER(MSVC7_OR_LOWER)
948 // FIXME: MSVC7 generates compilation errors when trying to assign
949 // a pointer to a Vector of its base class (i.e. can't downcast). So far
950 // I've been unable to determine any logical reason for this, so I can
951 // only assume it is a bug with the compiler. Casting is a bad solution,
952 // however, because it subverts implicit conversions, so a better
954 new (end()) T(static_cast<T
>(*ptr
));
961 // This version of append saves a branch in the case where you know that the
962 // vector's capacity is large enough for the append to succeed.
964 template<typename T
, size_t inlineCapacity
> template<typename U
>
965 inline void Vector
<T
, inlineCapacity
>::uncheckedAppend(const U
& val
)
967 ASSERT(size() < capacity());
973 // This method should not be called append, a better name would be appendElements.
974 // It could also be eliminated entirely, and call sites could just use
975 // appendRange(val.begin(), val.end()).
976 template<typename T
, size_t inlineCapacity
> template<size_t otherCapacity
>
977 inline void Vector
<T
, inlineCapacity
>::append(const Vector
<T
, otherCapacity
>& val
)
979 append(val
.begin(), val
.size());
982 template<typename T
, size_t inlineCapacity
> template<typename U
>
983 void Vector
<T
, inlineCapacity
>::insert(size_t position
, const U
* data
, size_t dataSize
)
985 ASSERT(position
<= size());
986 size_t newSize
= m_size
+ dataSize
;
987 if (newSize
> capacity()) {
988 data
= expandCapacity(newSize
, data
);
992 if (newSize
< m_size
)
994 T
* spot
= begin() + position
;
995 TypeOperations::moveOverlapping(spot
, end(), spot
+ dataSize
);
996 for (size_t i
= 0; i
< dataSize
; ++i
)
997 new (&spot
[i
]) T(data
[i
]);
1001 template<typename T
, size_t inlineCapacity
> template<typename U
>
1002 inline void Vector
<T
, inlineCapacity
>::insert(size_t position
, const U
& val
)
1004 ASSERT(position
<= size());
1005 const U
* data
= &val
;
1006 if (size() == capacity()) {
1007 data
= expandCapacity(size() + 1, data
);
1011 T
* spot
= begin() + position
;
1012 TypeOperations::moveOverlapping(spot
, end(), spot
+ 1);
1013 new (spot
) T(*data
);
1017 template<typename T
, size_t inlineCapacity
> template<typename U
, size_t c
>
1018 inline void Vector
<T
, inlineCapacity
>::insert(size_t position
, const Vector
<U
, c
>& val
)
1020 insert(position
, val
.begin(), val
.size());
1023 template<typename T
, size_t inlineCapacity
> template<typename U
>
1024 void Vector
<T
, inlineCapacity
>::prepend(const U
* data
, size_t dataSize
)
1026 insert(0, data
, dataSize
);
1029 template<typename T
, size_t inlineCapacity
> template<typename U
>
1030 inline void Vector
<T
, inlineCapacity
>::prepend(const U
& val
)
1035 template<typename T
, size_t inlineCapacity
> template<typename U
, size_t c
>
1036 inline void Vector
<T
, inlineCapacity
>::prepend(const Vector
<U
, c
>& val
)
1038 insert(0, val
.begin(), val
.size());
1041 template<typename T
, size_t inlineCapacity
>
1042 inline void Vector
<T
, inlineCapacity
>::remove(size_t position
)
1044 ASSERT(position
< size());
1045 T
* spot
= begin() + position
;
1047 TypeOperations::moveOverlapping(spot
+ 1, end(), spot
);
1051 template<typename T
, size_t inlineCapacity
>
1052 inline void Vector
<T
, inlineCapacity
>::remove(size_t position
, size_t length
)
1054 ASSERT(position
< size());
1055 ASSERT(position
+ length
<= size());
1056 T
* beginSpot
= begin() + position
;
1057 T
* endSpot
= beginSpot
+ length
;
1058 TypeOperations::destruct(beginSpot
, endSpot
);
1059 TypeOperations::moveOverlapping(endSpot
, end(), beginSpot
);
1063 template<typename T
, size_t inlineCapacity
>
1064 inline T
* Vector
<T
, inlineCapacity
>::releaseBuffer()
1066 T
* buffer
= m_buffer
.releaseBuffer();
1067 if (inlineCapacity
&& !buffer
&& m_size
) {
1068 // If the vector had some data, but no buffer to release,
1069 // that means it was using the inline buffer. In that case,
1070 // we create a brand new buffer so the caller always gets one.
1071 size_t bytes
= m_size
* sizeof(T
);
1072 buffer
= static_cast<T
*>(fastMalloc(bytes
));
1073 memcpy(buffer
, data(), bytes
);
1079 template<typename T
, size_t inlineCapacity
>
1080 inline void Vector
<T
, inlineCapacity
>::checkConsistency()
1082 #if !ASSERT_DISABLED
1083 for (size_t i
= 0; i
< size(); ++i
)
1084 ValueCheck
<T
>::checkConsistency(at(i
));
1088 template<typename T
, size_t inlineCapacity
>
1089 void deleteAllValues(const Vector
<T
, inlineCapacity
>& collection
)
1091 typedef typename Vector
<T
, inlineCapacity
>::const_iterator iterator
;
1092 iterator end
= collection
.end();
1093 for (iterator it
= collection
.begin(); it
!= end
; ++it
)
1097 template<typename T
, size_t inlineCapacity
>
1098 inline void swap(Vector
<T
, inlineCapacity
>& a
, Vector
<T
, inlineCapacity
>& b
)
1103 template<typename T
, size_t inlineCapacity
>
1104 bool operator==(const Vector
<T
, inlineCapacity
>& a
, const Vector
<T
, inlineCapacity
>& b
)
1106 if (a
.size() != b
.size())
1109 return VectorTypeOperations
<T
>::compare(a
.data(), b
.data(), a
.size());
1112 template<typename T
, size_t inlineCapacity
>
1113 inline bool operator!=(const Vector
<T
, inlineCapacity
>& a
, const Vector
<T
, inlineCapacity
>& b
)
1118 #if !ASSERT_DISABLED
1119 template<typename T
> struct ValueCheck
<Vector
<T
> > {
1120 typedef Vector
<T
> TraitType
;
1121 static void checkConsistency(const Vector
<T
>& v
)
1123 v
.checkConsistency();
1132 #endif // WTF_Vector_h