• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  *
19  */
20 
21 #ifndef WTF_Vector_h
22 #define WTF_Vector_h
23 
24 #include "FastAllocBase.h"
25 #include "Noncopyable.h"
26 #include "NotFound.h"
27 #include "StdLibExtras.h"
28 #include "ValueCheck.h"
29 #include "VectorTraits.h"
30 #include <limits>
31 #include <utility>
32 #include <wtf/Alignment.h>
33 
34 #if PLATFORM(QT)
35 #include <QDataStream>
36 #endif
37 
38 namespace WTF {
39 
40     using std::min;
41     using std::max;
42 
43     #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
44         typedef char __attribute__((__may_alias__)) AlignedBufferChar;
45     #else
46         typedef char AlignedBufferChar;
47     #endif
48 
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); };
57 
58     template <size_t size, size_t alignment>
59     void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b)
60     {
61         for (size_t i = 0; i < size; ++i)
62             std::swap(a.buffer[i], b.buffer[i]);
63     }
64 
65     template <bool needsDestruction, typename T>
66     struct VectorDestructor;
67 
68     template<typename T>
69     struct VectorDestructor<false, T>
70     {
71         static void destruct(T*, T*) {}
72     };
73 
74     template<typename T>
75     struct VectorDestructor<true, T>
76     {
77         static void destruct(T* begin, T* end)
78         {
79             for (T* cur = begin; cur != end; ++cur)
80                 cur->~T();
81         }
82     };
83 
84     template <bool needsInitialization, bool canInitializeWithMemset, typename T>
85     struct VectorInitializer;
86 
87     template<bool ignore, typename T>
88     struct VectorInitializer<false, ignore, T>
89     {
90         static void initialize(T*, T*) {}
91     };
92 
93     template<typename T>
94     struct VectorInitializer<true, false, T>
95     {
96         static void initialize(T* begin, T* end)
97         {
98             for (T* cur = begin; cur != end; ++cur)
99                 new (cur) T;
100         }
101     };
102 
103     template<typename T>
104     struct VectorInitializer<true, true, T>
105     {
106         static void initialize(T* begin, T* end)
107         {
108             memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
109         }
110     };
111 
112     template <bool canMoveWithMemcpy, typename T>
113     struct VectorMover;
114 
115     template<typename T>
116     struct VectorMover<false, T>
117     {
118         static void move(const T* src, const T* srcEnd, T* dst)
119         {
120             while (src != srcEnd) {
121                 new (dst) T(*src);
122 #if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
123                 const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug.
124 #else
125                 src->~T();
126 #endif
127                 ++dst;
128                 ++src;
129             }
130         }
131         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
132         {
133             if (src > dst)
134                 move(src, srcEnd, dst);
135             else {
136                 T* dstEnd = dst + (srcEnd - src);
137                 while (src != srcEnd) {
138                     --srcEnd;
139                     --dstEnd;
140                     new (dstEnd) T(*srcEnd);
141                     srcEnd->~T();
142                 }
143             }
144         }
145     };
146 
147     template<typename T>
148     struct VectorMover<true, T>
149     {
150         static void move(const T* src, const T* srcEnd, T* dst)
151         {
152             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
153         }
154         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
155         {
156             memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
157         }
158     };
159 
160     template <bool canCopyWithMemcpy, typename T>
161     struct VectorCopier;
162 
163     template<typename T>
164     struct VectorCopier<false, T>
165     {
166         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
167         {
168             while (src != srcEnd) {
169                 new (dst) T(*src);
170                 ++dst;
171                 ++src;
172             }
173         }
174     };
175 
176     template<typename T>
177     struct VectorCopier<true, T>
178     {
179         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
180         {
181             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
182         }
183     };
184 
185     template <bool canFillWithMemset, typename T>
186     struct VectorFiller;
187 
188     template<typename T>
189     struct VectorFiller<false, T>
190     {
191         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
192         {
193             while (dst != dstEnd) {
194                 new (dst) T(val);
195                 ++dst;
196             }
197         }
198     };
199 
200     template<typename T>
201     struct VectorFiller<true, T>
202     {
203         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
204         {
205             ASSERT(sizeof(T) == sizeof(char));
206             memset(dst, val, dstEnd - dst);
207         }
208     };
209 
210     template<bool canCompareWithMemcmp, typename T>
211     struct VectorComparer;
212 
213     template<typename T>
214     struct VectorComparer<false, T>
215     {
216         static bool compare(const T* a, const T* b, size_t size)
217         {
218             for (size_t i = 0; i < size; ++i)
219                 if (a[i] != b[i])
220                     return false;
221             return true;
222         }
223     };
224 
225     template<typename T>
226     struct VectorComparer<true, T>
227     {
228         static bool compare(const T* a, const T* b, size_t size)
229         {
230             return memcmp(a, b, sizeof(T) * size) == 0;
231         }
232     };
233 
234     template<typename T>
235     struct VectorTypeOperations
236     {
237         static void destruct(T* begin, T* end)
238         {
239             VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
240         }
241 
242         static void initialize(T* begin, T* end)
243         {
244             VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
245         }
246 
247         static void move(const T* src, const T* srcEnd, T* dst)
248         {
249             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
250         }
251 
252         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
253         {
254             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
255         }
256 
257         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
258         {
259             VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
260         }
261 
262         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
263         {
264             VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
265         }
266 
267         static bool compare(const T* a, const T* b, size_t size)
268         {
269             return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
270         }
271     };
272 
273     template<typename T>
274     class VectorBufferBase {
275         WTF_MAKE_NONCOPYABLE(VectorBufferBase);
276     public:
277         void allocateBuffer(size_t newCapacity)
278         {
279             ASSERT(newCapacity);
280             m_capacity = newCapacity;
281             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
282                 CRASH();
283             m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
284         }
285 
286         bool tryAllocateBuffer(size_t newCapacity)
287         {
288             ASSERT(newCapacity);
289             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
290                 return false;
291 
292             T* newBuffer;
293             if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) {
294                 m_capacity = newCapacity;
295                 m_buffer = newBuffer;
296                 return true;
297             }
298             return false;
299         }
300 
301         void deallocateBuffer(T* bufferToDeallocate)
302         {
303             if (m_buffer == bufferToDeallocate) {
304                 m_buffer = 0;
305                 m_capacity = 0;
306             }
307             fastFree(bufferToDeallocate);
308         }
309 
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; }
314 
315         T* releaseBuffer()
316         {
317             T* buffer = m_buffer;
318             m_buffer = 0;
319             m_capacity = 0;
320             return buffer;
321         }
322 
323     protected:
324         VectorBufferBase()
325             : m_buffer(0)
326             , m_capacity(0)
327         {
328         }
329 
330         VectorBufferBase(T* buffer, size_t capacity)
331             : m_buffer(buffer)
332             , m_capacity(capacity)
333         {
334         }
335 
336         ~VectorBufferBase()
337         {
338             // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
339         }
340 
341         T* m_buffer;
342         size_t m_capacity;
343     };
344 
345     template<typename T, size_t inlineCapacity>
346     class VectorBuffer;
347 
348     template<typename T>
349     class VectorBuffer<T, 0> : private VectorBufferBase<T> {
350     private:
351         typedef VectorBufferBase<T> Base;
352     public:
353         VectorBuffer()
354         {
355         }
356 
357         VectorBuffer(size_t capacity)
358         {
359             // Calling malloc(0) might take a lock and may actually do an
360             // allocation on some systems (e.g. Brew).
361             if (capacity)
362                 allocateBuffer(capacity);
363         }
364 
365         ~VectorBuffer()
366         {
367             deallocateBuffer(buffer());
368         }
369 
370         void swap(VectorBuffer<T, 0>& other)
371         {
372             std::swap(m_buffer, other.m_buffer);
373             std::swap(m_capacity, other.m_capacity);
374         }
375 
376         void restoreInlineBufferIfNeeded() { }
377 
378         using Base::allocateBuffer;
379         using Base::tryAllocateBuffer;
380         using Base::deallocateBuffer;
381 
382         using Base::buffer;
383         using Base::bufferSlot;
384         using Base::capacity;
385 
386         using Base::releaseBuffer;
387     private:
388         using Base::m_buffer;
389         using Base::m_capacity;
390     };
391 
392     template<typename T, size_t inlineCapacity>
393     class VectorBuffer : private VectorBufferBase<T> {
394         WTF_MAKE_NONCOPYABLE(VectorBuffer);
395     private:
396         typedef VectorBufferBase<T> Base;
397     public:
398         VectorBuffer()
399             : Base(inlineBuffer(), inlineCapacity)
400         {
401         }
402 
403         VectorBuffer(size_t capacity)
404             : Base(inlineBuffer(), inlineCapacity)
405         {
406             if (capacity > inlineCapacity)
407                 Base::allocateBuffer(capacity);
408         }
409 
410         ~VectorBuffer()
411         {
412             deallocateBuffer(buffer());
413         }
414 
415         void allocateBuffer(size_t newCapacity)
416         {
417             // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
418             if (newCapacity > inlineCapacity)
419                 Base::allocateBuffer(newCapacity);
420             else {
421                 m_buffer = inlineBuffer();
422                 m_capacity = inlineCapacity;
423             }
424         }
425 
426         bool tryAllocateBuffer(size_t newCapacity)
427         {
428             if (newCapacity > inlineCapacity)
429                 return Base::tryAllocateBuffer(newCapacity);
430             m_buffer = inlineBuffer();
431             m_capacity = inlineCapacity;
432             return true;
433         }
434 
435         void deallocateBuffer(T* bufferToDeallocate)
436         {
437             if (bufferToDeallocate == inlineBuffer())
438                 return;
439             Base::deallocateBuffer(bufferToDeallocate);
440         }
441 
442         void swap(VectorBuffer<T, inlineCapacity>& other)
443         {
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);
457             } else {
458                 std::swap(m_buffer, other.m_buffer);
459                 std::swap(m_capacity, other.m_capacity);
460             }
461         }
462 
463         void restoreInlineBufferIfNeeded()
464         {
465             if (m_buffer)
466                 return;
467             m_buffer = inlineBuffer();
468             m_capacity = inlineCapacity;
469         }
470 
471         using Base::buffer;
472         using Base::bufferSlot;
473         using Base::capacity;
474 
475         T* releaseBuffer()
476         {
477             if (buffer() == inlineBuffer())
478                 return 0;
479             return Base::releaseBuffer();
480         }
481 
482     private:
483         using Base::m_buffer;
484         using Base::m_capacity;
485 
486         static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
487         T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
488 
489         AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
490     };
491 
492     template<typename T, size_t inlineCapacity = 0>
493     class Vector {
494         WTF_MAKE_FAST_ALLOCATED;
495     private:
496         typedef VectorBuffer<T, inlineCapacity> Buffer;
497         typedef VectorTypeOperations<T> TypeOperations;
498 
499     public:
500         typedef T ValueType;
501 
502         typedef T* iterator;
503         typedef const T* const_iterator;
504 
505         Vector()
506             : m_size(0)
507         {
508         }
509 
510         explicit Vector(size_t size)
511             : m_size(size)
512             , m_buffer(size)
513         {
514             if (begin())
515                 TypeOperations::initialize(begin(), end());
516         }
517 
518         ~Vector()
519         {
520             if (m_size) shrink(0);
521         }
522 
523         Vector(const Vector&);
524         template<size_t otherCapacity>
525         Vector(const Vector<T, otherCapacity>&);
526 
527         Vector& operator=(const Vector&);
528         template<size_t otherCapacity>
529         Vector& operator=(const Vector<T, otherCapacity>&);
530 
531         size_t size() const { return m_size; }
532         size_t capacity() const { return m_buffer.capacity(); }
533         bool isEmpty() const { return !size(); }
534 
535         T& at(size_t i)
536         {
537             ASSERT(i < size());
538             return m_buffer.buffer()[i];
539         }
540         const T& at(size_t i) const
541         {
542             ASSERT(i < size());
543             return m_buffer.buffer()[i];
544         }
545 
546         T& operator[](size_t i) { return at(i); }
547         const T& operator[](size_t i) const { return at(i); }
548 
549         T* data() { return m_buffer.buffer(); }
550         const T* data() const { return m_buffer.buffer(); }
551         T** dataSlot() { return m_buffer.bufferSlot(); }
552 
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; }
557 
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); }
562 
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;
566 
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()); }
575 
576         void clear() { shrinkCapacity(0); }
577 
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);
583 
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>&);
587 
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>&);
591 
592         void remove(size_t position);
593         void remove(size_t position, size_t length);
594 
595         void removeLast()
596         {
597             ASSERT(!isEmpty());
598             shrink(size() - 1);
599         }
600 
601         Vector(size_t size, const T& val)
602             : m_size(size)
603             , m_buffer(size)
604         {
605             if (begin())
606                 TypeOperations::uninitializedFill(begin(), end(), val);
607         }
608 
609         void fill(const T&, size_t);
610         void fill(const T& val) { fill(val, size()); }
611 
612         template<typename Iterator> void appendRange(Iterator start, Iterator end);
613 
614         T* releaseBuffer();
615 
616         void swap(Vector<T, inlineCapacity>& other)
617         {
618             std::swap(m_size, other.m_size);
619             m_buffer.swap(other.m_buffer);
620         }
621 
622         void checkConsistency();
623 
624     private:
625         void expandCapacity(size_t newMinCapacity);
626         const T* expandCapacity(size_t newMinCapacity, const T*);
627         bool tryExpandCapacity(size_t newMinCapacity);
628         const T* tryExpandCapacity(size_t newMinCapacity, const T*);
629         template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
630 
631         size_t m_size;
632         Buffer m_buffer;
633     };
634 
635 #if PLATFORM(QT)
636     template<typename T>
637     QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
638     {
639         stream << qint64(data.size());
640         foreach (const T& i, data)
641             stream << i;
642         return stream;
643     }
644 
645     template<typename T>
646     QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
647     {
648         data.clear();
649         qint64 count;
650         T item;
651         stream >> count;
652         data.reserveCapacity(count);
653         for (qint64 i = 0; i < count; ++i) {
654             stream >> item;
655             data.append(item);
656         }
657         return stream;
658     }
659 #endif
660 
661     template<typename T, size_t inlineCapacity>
662     Vector<T, inlineCapacity>::Vector(const Vector& other)
663         : m_size(other.size())
664         , m_buffer(other.capacity())
665     {
666         if (begin())
667             TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
668     }
669 
670     template<typename T, size_t inlineCapacity>
671     template<size_t otherCapacity>
672     Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
673         : m_size(other.size())
674         , m_buffer(other.capacity())
675     {
676         if (begin())
677             TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
678     }
679 
680     template<typename T, size_t inlineCapacity>
681     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
682     {
683         if (&other == this)
684             return *this;
685 
686         if (size() > other.size())
687             shrink(other.size());
688         else if (other.size() > capacity()) {
689             clear();
690             reserveCapacity(other.size());
691             if (!begin())
692                 return *this;
693         }
694 
695 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
696 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
697         if (!begin())
698             return *this;
699 #endif
700 
701         std::copy(other.begin(), other.begin() + size(), begin());
702         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
703         m_size = other.size();
704 
705         return *this;
706     }
707 
708     inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
709 
710     template<typename T, size_t inlineCapacity>
711     template<size_t otherCapacity>
712     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
713     {
714         // If the inline capacities match, we should call the more specific
715         // template.  If the inline capacities don't match, the two objects
716         // shouldn't be allocated the same address.
717         ASSERT(!typelessPointersAreEqual(&other, this));
718 
719         if (size() > other.size())
720             shrink(other.size());
721         else if (other.size() > capacity()) {
722             clear();
723             reserveCapacity(other.size());
724             if (!begin())
725                 return *this;
726         }
727 
728 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
729 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
730         if (!begin())
731             return *this;
732 #endif
733 
734         std::copy(other.begin(), other.begin() + size(), begin());
735         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
736         m_size = other.size();
737 
738         return *this;
739     }
740 
741     template<typename T, size_t inlineCapacity>
742     template<typename U>
743     bool Vector<T, inlineCapacity>::contains(const U& value) const
744     {
745         return find(value) != notFound;
746     }
747 
748     template<typename T, size_t inlineCapacity>
749     template<typename U>
750     size_t Vector<T, inlineCapacity>::find(const U& value) const
751     {
752         for (size_t i = 0; i < size(); ++i) {
753             if (at(i) == value)
754                 return i;
755         }
756         return notFound;
757     }
758 
759     template<typename T, size_t inlineCapacity>
760     template<typename U>
761     size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const
762     {
763         for (size_t i = 1; i <= size(); ++i) {
764             const size_t index = size() - i;
765             if (at(index) == value)
766                 return index;
767         }
768         return notFound;
769     }
770 
771     template<typename T, size_t inlineCapacity>
772     void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
773     {
774         if (size() > newSize)
775             shrink(newSize);
776         else if (newSize > capacity()) {
777             clear();
778             reserveCapacity(newSize);
779             if (!begin())
780                 return;
781         }
782 
783         std::fill(begin(), end(), val);
784         TypeOperations::uninitializedFill(end(), begin() + newSize, val);
785         m_size = newSize;
786     }
787 
788     template<typename T, size_t inlineCapacity>
789     template<typename Iterator>
790     void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
791     {
792         for (Iterator it = start; it != end; ++it)
793             append(*it);
794     }
795 
796     template<typename T, size_t inlineCapacity>
797     void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
798     {
799         reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
800     }
801 
802     template<typename T, size_t inlineCapacity>
803     const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
804     {
805         if (ptr < begin() || ptr >= end()) {
806             expandCapacity(newMinCapacity);
807             return ptr;
808         }
809         size_t index = ptr - begin();
810         expandCapacity(newMinCapacity);
811         return begin() + index;
812     }
813 
814     template<typename T, size_t inlineCapacity>
815     bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity)
816     {
817         return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
818     }
819 
820     template<typename T, size_t inlineCapacity>
821     const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr)
822     {
823         if (ptr < begin() || ptr >= end()) {
824             if (!tryExpandCapacity(newMinCapacity))
825                 return 0;
826             return ptr;
827         }
828         size_t index = ptr - begin();
829         if (!tryExpandCapacity(newMinCapacity))
830             return 0;
831         return begin() + index;
832     }
833 
834     template<typename T, size_t inlineCapacity> template<typename U>
835     inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
836     {
837         expandCapacity(newMinCapacity);
838         return ptr;
839     }
840 
841     template<typename T, size_t inlineCapacity>
842     inline void Vector<T, inlineCapacity>::resize(size_t size)
843     {
844         if (size <= m_size)
845             TypeOperations::destruct(begin() + size, end());
846         else {
847             if (size > capacity())
848                 expandCapacity(size);
849             if (begin())
850                 TypeOperations::initialize(end(), begin() + size);
851         }
852 
853         m_size = size;
854     }
855 
856     template<typename T, size_t inlineCapacity>
857     void Vector<T, inlineCapacity>::shrink(size_t size)
858     {
859         ASSERT(size <= m_size);
860         TypeOperations::destruct(begin() + size, end());
861         m_size = size;
862     }
863 
864     template<typename T, size_t inlineCapacity>
865     void Vector<T, inlineCapacity>::grow(size_t size)
866     {
867         ASSERT(size >= m_size);
868         if (size > capacity())
869             expandCapacity(size);
870         if (begin())
871             TypeOperations::initialize(end(), begin() + size);
872         m_size = size;
873     }
874 
875     template<typename T, size_t inlineCapacity>
876     void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
877     {
878         if (newCapacity <= capacity())
879             return;
880         T* oldBuffer = begin();
881         T* oldEnd = end();
882         m_buffer.allocateBuffer(newCapacity);
883         if (begin())
884             TypeOperations::move(oldBuffer, oldEnd, begin());
885         m_buffer.deallocateBuffer(oldBuffer);
886     }
887 
888     template<typename T, size_t inlineCapacity>
889     bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity)
890     {
891         if (newCapacity <= capacity())
892             return true;
893         T* oldBuffer = begin();
894         T* oldEnd = end();
895         if (!m_buffer.tryAllocateBuffer(newCapacity))
896             return false;
897         ASSERT(begin());
898         TypeOperations::move(oldBuffer, oldEnd, begin());
899         m_buffer.deallocateBuffer(oldBuffer);
900         return true;
901     }
902 
903     template<typename T, size_t inlineCapacity>
904     inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity)
905     {
906         ASSERT(!m_size);
907         ASSERT(capacity() == inlineCapacity);
908         if (initialCapacity > inlineCapacity)
909             m_buffer.allocateBuffer(initialCapacity);
910     }
911 
912     template<typename T, size_t inlineCapacity>
913     void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
914     {
915         if (newCapacity >= capacity())
916             return;
917 
918         if (newCapacity < size())
919             shrink(newCapacity);
920 
921         T* oldBuffer = begin();
922         if (newCapacity > 0) {
923             T* oldEnd = end();
924             m_buffer.allocateBuffer(newCapacity);
925             if (begin() != oldBuffer)
926                 TypeOperations::move(oldBuffer, oldEnd, begin());
927         }
928 
929         m_buffer.deallocateBuffer(oldBuffer);
930         m_buffer.restoreInlineBufferIfNeeded();
931     }
932 
933     // Templatizing these is better than just letting the conversion happen implicitly,
934     // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
935     // without refcount thrash.
936 
937     template<typename T, size_t inlineCapacity> template<typename U>
938     void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
939     {
940         size_t newSize = m_size + dataSize;
941         if (newSize > capacity()) {
942             data = expandCapacity(newSize, data);
943             if (!begin())
944                 return;
945         }
946         if (newSize < m_size)
947             CRASH();
948         T* dest = end();
949         for (size_t i = 0; i < dataSize; ++i)
950             new (&dest[i]) T(data[i]);
951         m_size = newSize;
952     }
953 
954     template<typename T, size_t inlineCapacity> template<typename U>
955     bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize)
956     {
957         size_t newSize = m_size + dataSize;
958         if (newSize > capacity()) {
959             data = tryExpandCapacity(newSize, data);
960             if (!data)
961                 return false;
962             ASSERT(begin());
963         }
964         if (newSize < m_size)
965             return false;
966         T* dest = end();
967         for (size_t i = 0; i < dataSize; ++i)
968             new (&dest[i]) T(data[i]);
969         m_size = newSize;
970         return true;
971     }
972 
973     template<typename T, size_t inlineCapacity> template<typename U>
974     ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
975     {
976         const U* ptr = &val;
977         if (size() == capacity()) {
978             ptr = expandCapacity(size() + 1, ptr);
979             if (!begin())
980                 return;
981         }
982 
983 #if COMPILER(MSVC7_OR_LOWER)
984         // FIXME: MSVC7 generates compilation errors when trying to assign
985         // a pointer to a Vector of its base class (i.e. can't downcast). So far
986         // I've been unable to determine any logical reason for this, so I can
987         // only assume it is a bug with the compiler. Casting is a bad solution,
988         // however, because it subverts implicit conversions, so a better
989         // one is needed.
990         new (end()) T(static_cast<T>(*ptr));
991 #else
992         new (end()) T(*ptr);
993 #endif
994         ++m_size;
995     }
996 
997     // This version of append saves a branch in the case where you know that the
998     // vector's capacity is large enough for the append to succeed.
999 
1000     template<typename T, size_t inlineCapacity> template<typename U>
1001     inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
1002     {
1003         ASSERT(size() < capacity());
1004         const U* ptr = &val;
1005         new (end()) T(*ptr);
1006         ++m_size;
1007     }
1008 
1009     // This method should not be called append, a better name would be appendElements.
1010     // It could also be eliminated entirely, and call sites could just use
1011     // appendRange(val.begin(), val.end()).
1012     template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
1013     inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val)
1014     {
1015         append(val.begin(), val.size());
1016     }
1017 
1018     template<typename T, size_t inlineCapacity> template<typename U>
1019     void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
1020     {
1021         ASSERT(position <= size());
1022         size_t newSize = m_size + dataSize;
1023         if (newSize > capacity()) {
1024             data = expandCapacity(newSize, data);
1025             if (!begin())
1026                 return;
1027         }
1028         if (newSize < m_size)
1029             CRASH();
1030         T* spot = begin() + position;
1031         TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1032         for (size_t i = 0; i < dataSize; ++i)
1033             new (&spot[i]) T(data[i]);
1034         m_size = newSize;
1035     }
1036 
1037     template<typename T, size_t inlineCapacity> template<typename U>
1038     inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
1039     {
1040         ASSERT(position <= size());
1041         const U* data = &val;
1042         if (size() == capacity()) {
1043             data = expandCapacity(size() + 1, data);
1044             if (!begin())
1045                 return;
1046         }
1047         T* spot = begin() + position;
1048         TypeOperations::moveOverlapping(spot, end(), spot + 1);
1049         new (spot) T(*data);
1050         ++m_size;
1051     }
1052 
1053     template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1054     inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
1055     {
1056         insert(position, val.begin(), val.size());
1057     }
1058 
1059     template<typename T, size_t inlineCapacity> template<typename U>
1060     void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
1061     {
1062         insert(0, data, dataSize);
1063     }
1064 
1065     template<typename T, size_t inlineCapacity> template<typename U>
1066     inline void Vector<T, inlineCapacity>::prepend(const U& val)
1067     {
1068         insert(0, val);
1069     }
1070 
1071     template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1072     inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
1073     {
1074         insert(0, val.begin(), val.size());
1075     }
1076 
1077     template<typename T, size_t inlineCapacity>
1078     inline void Vector<T, inlineCapacity>::remove(size_t position)
1079     {
1080         ASSERT(position < size());
1081         T* spot = begin() + position;
1082         spot->~T();
1083         TypeOperations::moveOverlapping(spot + 1, end(), spot);
1084         --m_size;
1085     }
1086 
1087     template<typename T, size_t inlineCapacity>
1088     inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length)
1089     {
1090         ASSERT(position < size());
1091         ASSERT(position + length <= size());
1092         T* beginSpot = begin() + position;
1093         T* endSpot = beginSpot + length;
1094         TypeOperations::destruct(beginSpot, endSpot);
1095         TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
1096         m_size -= length;
1097     }
1098 
1099     template<typename T, size_t inlineCapacity>
1100     inline T* Vector<T, inlineCapacity>::releaseBuffer()
1101     {
1102         T* buffer = m_buffer.releaseBuffer();
1103         if (inlineCapacity && !buffer && m_size) {
1104             // If the vector had some data, but no buffer to release,
1105             // that means it was using the inline buffer. In that case,
1106             // we create a brand new buffer so the caller always gets one.
1107             size_t bytes = m_size * sizeof(T);
1108             buffer = static_cast<T*>(fastMalloc(bytes));
1109             memcpy(buffer, data(), bytes);
1110         }
1111         m_size = 0;
1112         return buffer;
1113     }
1114 
1115     template<typename T, size_t inlineCapacity>
1116     inline void Vector<T, inlineCapacity>::checkConsistency()
1117     {
1118 #if !ASSERT_DISABLED
1119         for (size_t i = 0; i < size(); ++i)
1120             ValueCheck<T>::checkConsistency(at(i));
1121 #endif
1122     }
1123 
1124     template<typename T, size_t inlineCapacity>
1125     void deleteAllValues(const Vector<T, inlineCapacity>& collection)
1126     {
1127         typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
1128         iterator end = collection.end();
1129         for (iterator it = collection.begin(); it != end; ++it)
1130             delete *it;
1131     }
1132 
1133     template<typename T, size_t inlineCapacity>
1134     inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
1135     {
1136         a.swap(b);
1137     }
1138 
1139     template<typename T, size_t inlineCapacity>
1140     bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1141     {
1142         if (a.size() != b.size())
1143             return false;
1144 
1145         return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
1146     }
1147 
1148     template<typename T, size_t inlineCapacity>
1149     inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
1150     {
1151         return !(a == b);
1152     }
1153 
1154 #if !ASSERT_DISABLED
1155     template<typename T> struct ValueCheck<Vector<T> > {
1156         typedef Vector<T> TraitType;
1157         static void checkConsistency(const Vector<T>& v)
1158         {
1159             v.checkConsistency();
1160         }
1161     };
1162 #endif
1163 
1164 } // namespace WTF
1165 
1166 using WTF::Vector;
1167 
1168 #endif // WTF_Vector_h
1169