308a51b24235d2aa4d6e5c7262528a8ac9a91d4a
[WebKit-https.git] / JavaScriptCore / wtf / Vector.h
1 // -*- mode: c++; c-basic-offset: 4 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 2005, 2006 Apple Computer, Inc.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #ifndef WTF_Vector_h
24 #define WTF_Vector_h
25
26 #include "Assertions.h"
27 #include "FastMalloc.h"
28 #include "VectorTraits.h"
29 #include <limits>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <utility>
33
34 namespace WTF {
35
36     using std::min;
37     using std::max;
38     
39     template <bool needsDestruction, typename T>
40     class VectorDestructor;
41
42     template<typename T>
43     struct VectorDestructor<false, T>
44     {
45         static void destruct(T*, T*) {}
46     };
47
48     template<typename T>
49     struct VectorDestructor<true, T>
50     {
51         static void destruct(T* begin, T* end) 
52         {
53             for (T* cur = begin; cur != end; ++cur)
54                 cur->~T();
55         }
56     };
57
58     template <bool needsInitialization, bool canInitializeWithMemset, typename T>
59     class VectorInitializer;
60
61     template<bool ignore, typename T>
62     struct VectorInitializer<false, ignore, T>
63     {
64         static void initialize(T*, T*) {}
65     };
66
67     template<typename T>
68     struct VectorInitializer<true, false, T>
69     {
70         static void initialize(T* begin, T* end) 
71         {
72             for (T* cur = begin; cur != end; ++cur)
73                 new (cur) T;
74         }
75     };
76
77     template<typename T>
78     struct VectorInitializer<true, true, T>
79     {
80         static void initialize(T* begin, T* end) 
81         {
82             memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
83         }
84     };
85
86     template <bool canMoveWithMemcpy, typename T>
87     class VectorMover;
88
89     template<typename T>
90     struct VectorMover<false, T>
91     {
92         static void move(const T* src, const T* srcEnd, T* dst)
93         {
94             while (src != srcEnd) {
95                 new (dst) T(*src);
96                 src->~T();
97                 ++dst;
98                 ++src;
99             }
100         }
101         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
102         {
103             if (src > dst)
104                 move(src, srcEnd, dst);
105             else {
106                 T* dstEnd = dst + (srcEnd - src);
107                 while (src != srcEnd) {
108                     --srcEnd;
109                     --dstEnd;
110                     new (dstEnd) T(*srcEnd);
111                     srcEnd->~T();
112                 }
113             }
114         }
115     };
116
117     template<typename T>
118     struct VectorMover<true, T>
119     {
120         static void move(const T* src, const T* srcEnd, T* dst) 
121         {
122             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
123         }
124         static void moveOverlapping(const T* src, const T* srcEnd, T* dst) 
125         {
126             memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
127         }
128     };
129
130     template <bool canCopyWithMemcpy, typename T>
131     class VectorCopier;
132
133     template<typename T>
134     struct VectorCopier<false, T>
135     {
136         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
137         {
138             while (src != srcEnd) {
139                 new (dst) T(*src);
140                 ++dst;
141                 ++src;
142             }
143         }
144     };
145
146     template<typename T>
147     struct VectorCopier<true, T>
148     {
149         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
150         {
151             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
152         }
153     };
154
155     template <bool canFillWithMemset, typename T>
156     class VectorFiller;
157
158     template<typename T>
159     struct VectorFiller<false, T>
160     {
161         static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
162         {
163             while (dst != dstEnd) {
164                 new (dst) T(val);
165                 ++dst;
166             }
167         }
168     };
169
170     template<typename T>
171     struct VectorFiller<true, T>
172     {
173         static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
174         {
175             ASSERT(sizeof(T) == sizeof(char));
176             memset(dst, val, dstEnd - dst);
177         }
178     };
179     
180     template<bool canCompareWithMemcmp, typename T>
181     class VectorComparer;
182     
183     template<typename T>
184     struct VectorComparer<false, T>
185     {
186         static bool compare(const T* a, const T* b, size_t size)
187         {
188             for (size_t i = 0; i < size; ++i)
189                 if (a[i] != b[i])
190                     return false;
191             return true;
192         }
193     };
194
195     template<typename T>
196     struct VectorComparer<true, T>
197     {
198         static bool compare(const T* a, const T* b, size_t size)
199         {
200             return memcmp(a, b, sizeof(T) * size) == 0;
201         }
202     };
203     
204     template<typename T>
205     struct VectorTypeOperations
206     {
207         static void destruct(T* begin, T* end)
208         {
209             VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
210         }
211
212         static void initialize(T* begin, T* end)
213         {
214             VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
215         }
216
217         static void move(const T* src, const T* srcEnd, T* dst)
218         {
219             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
220         }
221
222         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
223         {
224             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
225         }
226
227         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
228         {
229             VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
230         }
231
232         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
233         {
234             VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
235         }
236         
237         static bool compare(const T* a, const T* b, size_t size)
238         {
239             return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
240         }
241     };
242
243     template<typename T>
244     class VectorBufferBase {
245     public:
246         void allocateBuffer(size_t newCapacity)
247         {
248             ASSERT(newCapacity >= m_capacity);
249             m_capacity = newCapacity;
250             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
251                 CRASH();
252             m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
253         }
254
255         void deallocateBuffer(T* bufferToDeallocate)
256         {
257             fastFree(bufferToDeallocate);
258         }
259
260         T* buffer() { return m_buffer; }
261         const T* buffer() const { return m_buffer; }
262         size_t capacity() const { return m_capacity; }
263
264         T* releaseBuffer()
265         {
266             T* buffer = m_buffer;
267             m_buffer = 0;
268             m_capacity = 0;
269             return buffer;
270         }
271
272     protected:
273         VectorBufferBase()
274             : m_buffer(0)
275             , m_capacity(0)
276         {
277         }
278
279         VectorBufferBase(T* buffer, size_t capacity)
280             : m_buffer(buffer)
281             , m_capacity(capacity)
282         {
283         }
284
285         ~VectorBufferBase()
286         {
287             // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here.
288         }
289
290         T* m_buffer;
291         size_t m_capacity;
292     };
293
294     template<typename T, size_t inlineCapacity>
295     class VectorBuffer;
296
297     template<typename T>
298     class VectorBuffer<T, 0> : private VectorBufferBase<T> {
299     private:
300         typedef VectorBufferBase<T> Base;
301     public:
302         VectorBuffer()
303         {
304         }
305
306         VectorBuffer(size_t capacity)
307         {
308             allocateBuffer(capacity);
309         }
310
311         ~VectorBuffer()
312         {
313             deallocateBuffer(buffer());
314         }
315         
316         void swap(VectorBuffer<T, 0>& other)
317         {
318             std::swap(m_buffer, other.m_buffer);
319             std::swap(m_capacity, other.m_capacity);
320         }
321
322         using Base::allocateBuffer;
323         using Base::deallocateBuffer;
324
325         using Base::buffer;
326         using Base::capacity;
327
328         using Base::releaseBuffer;
329     private:
330         using Base::m_buffer;
331         using Base::m_capacity;
332     };
333
334     template<typename T, size_t inlineCapacity>
335     class VectorBuffer : private VectorBufferBase<T> {
336     private:
337         typedef VectorBufferBase<T> Base;
338     public:
339         VectorBuffer()
340             : Base(inlineBuffer(), inlineCapacity)
341         {
342         }
343
344         VectorBuffer(size_t capacity)
345             : Base(inlineBuffer(), inlineCapacity)
346         {
347             if (capacity > inlineCapacity)
348                 allocateBuffer(capacity);
349         }
350
351         ~VectorBuffer()
352         {
353             deallocateBuffer(buffer());
354         }
355
356         using Base::allocateBuffer;
357
358         void deallocateBuffer(T* bufferToDeallocate)
359         {
360             if (bufferToDeallocate == inlineBuffer())
361                 return;
362             Base::deallocateBuffer(bufferToDeallocate);
363         }
364
365         using Base::buffer;
366         using Base::capacity;
367
368         T* releaseBuffer()
369         {
370             if (buffer() == inlineBuffer())
371                 return 0;
372             return Base::releaseBuffer();
373         }
374
375     private:
376         using Base::m_buffer;
377         using Base::m_capacity;
378
379         static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
380         T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
381
382         // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T.
383         char m_inlineBuffer[m_inlineBufferSize];
384     };
385
386     template<typename T, size_t inlineCapacity = 0>
387     class Vector {
388     private:
389         typedef VectorBuffer<T, inlineCapacity> Impl;
390         typedef VectorTypeOperations<T> TypeOperations;
391
392     public:
393         typedef T ValueType;
394
395         typedef T* iterator;
396         typedef const T* const_iterator;
397
398         Vector() 
399             : m_size(0)
400         {
401         }
402         
403         explicit Vector(size_t size) 
404             : m_size(0)
405         {
406             resize(size);
407         }
408
409         ~Vector()
410         {
411             clear();
412         }
413
414         Vector(const Vector&);
415         template<size_t otherCapacity> 
416         Vector(const Vector<T, otherCapacity>&);
417
418         Vector& operator=(const Vector&);
419         template<size_t otherCapacity> 
420         Vector& operator=(const Vector<T, otherCapacity>&);
421
422         size_t size() const { return m_size; }
423         size_t capacity() const { return m_impl.capacity(); }
424         bool isEmpty() const { return !size(); }
425
426         T& at(size_t i) 
427         { 
428             ASSERT(i < size());
429             return m_impl.buffer()[i]; 
430         }
431         const T& at(size_t i) const 
432         {
433             ASSERT(i < size());
434             return m_impl.buffer()[i]; 
435         }
436
437         T& operator[](size_t i) { return at(i); }
438         const T& operator[](size_t i) const { return at(i); }
439
440         T* data() { return m_impl.buffer(); }
441         const T* data() const { return m_impl.buffer(); }
442
443         iterator begin() { return data(); }
444         iterator end() { return begin() + m_size; }
445         const_iterator begin() const { return data(); }
446         const_iterator end() const { return begin() + m_size; }
447         
448         T& first() { return at(0); }
449         const T& first() const { return at(0); }
450         T& last() { return at(size() - 1); }
451         const T& last() const { return at(size() - 1); }
452
453         void shrink(size_t size);
454         void resize(size_t size);
455         void reserveCapacity(size_t newCapacity);
456
457         void clear() { shrink(0); }
458
459         template<typename U> void append(const U*, size_t);
460         template<typename U> void append(const U&);
461         template<typename U> void uncheckedAppend(const U& val);
462         template<typename U, size_t c> void append(const Vector<U, c>&);
463
464         template<typename U> void insert(size_t position, const U*, size_t);
465         template<typename U> void insert(size_t position, const U&);
466         template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
467
468         template<typename U> void prepend(const U*, size_t);
469         template<typename U> void prepend(const U&);
470         template<typename U, size_t c> void prepend(const Vector<U, c>&);
471
472         void remove(size_t position);
473
474         void removeLast() 
475         {
476             ASSERT(!isEmpty());
477             shrink(size() - 1); 
478         }
479
480         Vector(size_t size, const T& val)
481             : m_size(size)
482             , m_impl(size)
483         {
484             TypeOperations::uninitializedFill(begin(), end(), val);
485         }
486
487         void fill(const T&, size_t);
488         void fill(const T& val) { fill(val, size()); }
489
490         template<typename Iterator> void appendRange(Iterator start, Iterator end);
491
492         T* releaseBuffer();
493
494         void swap(Vector<T, inlineCapacity>& other)
495         {
496             std::swap(m_size, other.m_size);
497             m_impl.swap(other.m_impl);
498         }
499
500     private:
501         void expandCapacity(size_t newMinCapacity);
502         const T* expandCapacity(size_t newMinCapacity, const T*);
503         template<typename U> U* expandCapacity(size_t newMinCapacity, U*); 
504
505         size_t m_size;
506         Impl m_impl;
507     };
508
509     template<typename T, size_t inlineCapacity>
510     Vector<T, inlineCapacity>::Vector(const Vector& other)
511         : m_size(other.size())
512         , m_impl(other.capacity())
513     {
514         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
515     }
516
517     template<typename T, size_t inlineCapacity>
518     template<size_t otherCapacity> 
519     Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
520         : m_size(other.size())
521         , m_impl(other.capacity())
522     {
523         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
524     }
525
526     template<typename T, size_t inlineCapacity>
527     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
528     {
529         if (&other == this)
530             return *this;
531         
532         if (size() > other.size())
533             shrink(other.size());
534         else if (other.size() > capacity()) {
535             clear();
536             reserveCapacity(other.size());
537         }
538         
539         std::copy(other.begin(), other.begin() + size(), begin());
540         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
541         m_size = other.size();
542
543         return *this;
544     }
545
546     template<typename T, size_t inlineCapacity>
547     template<size_t otherCapacity> 
548     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
549     {
550         if (&other == this)
551             return *this;
552         
553         if (size() > other.size())
554             shrink(other.size());
555         else if (other.size() > capacity()) {
556             clear();
557             reserveCapacity(other.size());
558         }
559         
560         std::copy(other.begin(), other.begin() + size(), begin());
561         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
562         m_size = other.size();
563
564         return *this;
565     }
566
567     template<typename T, size_t inlineCapacity>
568     void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
569     {
570         if (size() > newSize)
571             shrink(newSize);
572         else if (newSize > capacity()) {
573             clear();
574             reserveCapacity(newSize);
575         }
576         
577         std::fill(begin(), end(), val);
578         TypeOperations::uninitializedFill(end(), begin() + newSize, val);
579         m_size = newSize;
580     }
581
582     template<typename T, size_t inlineCapacity>
583     template<typename Iterator>
584     void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
585     {
586         for (Iterator it = start; it != end; ++it)
587             append(*it);
588     }
589
590     template<typename T, size_t inlineCapacity>
591     void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
592     {
593         reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
594     }
595     
596     template<typename T, size_t inlineCapacity>
597     const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
598     {
599         if (ptr < begin() || ptr >= end()) {
600             expandCapacity(newMinCapacity);
601             return ptr;
602         }
603         size_t index = ptr - begin();
604         expandCapacity(newMinCapacity);
605         return begin() + index;
606     }
607
608     template<typename T, size_t inlineCapacity> template<typename U>
609     inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
610     {
611         expandCapacity(newMinCapacity);
612         return ptr;
613     }
614
615     template<typename T, size_t inlineCapacity>
616     void Vector<T, inlineCapacity>::resize(size_t size)
617     {
618         if (size <= m_size)
619             TypeOperations::destruct(begin() + size, end());
620         else {
621             if (size > capacity())
622                 expandCapacity(size);
623             TypeOperations::initialize(end(), begin() + size);
624         }
625         
626         m_size = size;
627     }
628
629     template<typename T, size_t inlineCapacity>
630     void Vector<T, inlineCapacity>::shrink(size_t size)
631     {
632         ASSERT(size <= m_size);
633         TypeOperations::destruct(begin() + size, end());
634         m_size = size;
635     }
636
637     template<typename T, size_t inlineCapacity>
638     void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
639     {
640         if (newCapacity < capacity())
641             return;
642         T* oldBuffer = begin();
643         T* oldEnd = end();
644         m_impl.allocateBuffer(newCapacity);
645         TypeOperations::move(oldBuffer, oldEnd, begin());
646         m_impl.deallocateBuffer(oldBuffer);
647     }
648
649     // Templatizing these is better than just letting the conversion happen implicitly,
650     // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
651     // without refcount thrash.
652
653     template<typename T, size_t inlineCapacity> template<typename U>
654     void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
655     {
656         size_t newSize = m_size + dataSize;
657         if (newSize > capacity())
658             data = expandCapacity(newSize, data);
659         T* dest = end();
660         for (size_t i = 0; i < dataSize; ++i)
661             new (&dest[i]) T(data[i]);
662         m_size = newSize;
663     }
664
665     template<typename T, size_t inlineCapacity> template<typename U>
666     inline void Vector<T, inlineCapacity>::append(const U& val)
667     {
668         const U* ptr = &val;
669         if (size() == capacity())
670             ptr = expandCapacity(size() + 1, ptr);
671         new (end()) T(*ptr);
672         ++m_size;
673     }
674
675     // This version of append saves a branch in the case where you know that the
676     // vector's capacity is large enough for the append to succeed.
677
678     template<typename T, size_t inlineCapacity> template<typename U>
679     inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
680     {
681         ASSERT(size() < capacity());
682         const U* ptr = &val;
683         new (end()) T(*ptr);
684         ++m_size;
685     }
686
687     template<typename T, size_t inlineCapacity> template<typename U, size_t c>
688     inline void Vector<T, inlineCapacity>::append(const Vector<U, c>& val)
689     {
690         append(val.begin(), val.size());
691     }
692
693     template<typename T, size_t inlineCapacity> template<typename U>
694     void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
695     {
696         ASSERT(position <= size());
697         size_t newSize = m_size + dataSize;
698         if (newSize > capacity())
699             data = expandCapacity(newSize, data);
700         T* spot = begin() + position;
701         TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
702         for (size_t i = 0; i < dataSize; ++i)
703             new (&spot[i]) T(data[i]);
704         m_size = newSize;
705     }
706      
707     template<typename T, size_t inlineCapacity> template<typename U>
708     inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
709     {
710         ASSERT(position <= size());
711         const U* data = &val;
712         if (size() == capacity())
713             data = expandCapacity(size() + 1, data);
714         T* spot = begin() + position;
715         TypeOperations::moveOverlapping(spot, end(), spot + 1);
716         new (spot) T(*data);
717         ++m_size;
718     }
719    
720     template<typename T, size_t inlineCapacity> template<typename U, size_t c>
721     inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
722     {
723         insert(position, val.begin(), val.size());
724     }
725
726     template<typename T, size_t inlineCapacity> template<typename U>
727     void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
728     {
729         insert(0, data, dataSize);
730     }
731
732     template<typename T, size_t inlineCapacity> template<typename U>
733     inline void Vector<T, inlineCapacity>::prepend(const U& val)
734     {
735         insert(0, val);
736     }
737    
738     template<typename T, size_t inlineCapacity> template<typename U, size_t c>
739     inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
740     {
741         insert(0, val.begin(), val.size());
742     }
743     
744     template<typename T, size_t inlineCapacity>
745     inline void Vector<T, inlineCapacity>::remove(size_t position)
746     {
747         ASSERT(position < size());
748         T* spot = begin() + position;
749         spot->~T();
750         TypeOperations::moveOverlapping(spot + 1, end(), spot);
751         --m_size;
752     }
753
754     template<typename T, size_t inlineCapacity>
755     T* Vector<T, inlineCapacity>::releaseBuffer()
756     {
757         T* buffer = m_impl.releaseBuffer();
758         if (!buffer && m_size) {
759             // If the vector had some data, but no buffer to release,
760             // that means it was using the inline buffer. In that case,
761             // we create a brand new buffer so the caller always gets one.
762             size_t bytes = m_size * sizeof(T);
763             buffer = static_cast<T*>(fastMalloc(bytes));
764             memcpy(buffer, data(), bytes);
765         }
766         m_size = 0;
767         return buffer;
768     }
769
770     template<typename T, size_t inlineCapacity>
771     void deleteAllValues(const Vector<T, inlineCapacity>& collection)
772     {
773         typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
774         iterator end = collection.end();
775         for (iterator it = collection.begin(); it != end; ++it)
776             delete *it;
777     }
778
779     template<typename T, size_t inlineCapacity>
780     inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
781     {
782         a.swap(b);
783     }
784
785     template<typename T, size_t inlineCapacity>
786     bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
787     {
788         if (a.size() != b.size())
789             return false;
790
791         return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
792     }
793
794     template<typename T, size_t inlineCapacity>
795     inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
796     {
797         return !(a == b);
798     }
799
800
801 } // namespace WTF
802
803 using WTF::Vector;
804
805 #endif // WTF_Vector_h