]> git.saurik.com Git - apple/javascriptcore.git/blame - wtf/Vector.h
JavaScriptCore-466.1.3.tar.gz
[apple/javascriptcore.git] / wtf / Vector.h
CommitLineData
b37bf2e1
A
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef WTF_Vector_h
23#define WTF_Vector_h
24
25#include "Assertions.h"
26#include "FastMalloc.h"
27#include "Noncopyable.h"
28#include "VectorTraits.h"
29#include <limits>
30#include <stdlib.h>
31#include <string.h>
32#include <utility>
33
34namespace 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 : Noncopyable {
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#if PLATFORM(ARM)
381 T *inlineBuffer() { return reinterpret_cast<T*>((void*)((&m_inlineBuffer))); }
382
383 __attribute__ ((aligned (4))) char m_inlineBuffer[m_inlineBufferSize];
384#else
385 T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
386
387 // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T.
388 char m_inlineBuffer[m_inlineBufferSize];
389#endif
390 };
391
392 template<typename T, size_t inlineCapacity = 0>
393 class Vector {
394 private:
395 typedef VectorBuffer<T, inlineCapacity> Buffer;
396 typedef VectorTypeOperations<T> TypeOperations;
397
398 public:
399 typedef T ValueType;
400
401 typedef T* iterator;
402 typedef const T* const_iterator;
403
404 Vector()
405 : m_size(0)
406 {
407 }
408
409 explicit Vector(size_t size)
410 : m_size(size)
411 , m_buffer(size)
412 {
413 TypeOperations::initialize(begin(), end());
414 }
415
416 ~Vector()
417 {
418 clear();
419 }
420
421 Vector(const Vector&);
422 template<size_t otherCapacity>
423 Vector(const Vector<T, otherCapacity>&);
424
425 Vector& operator=(const Vector&);
426 template<size_t otherCapacity>
427 Vector& operator=(const Vector<T, otherCapacity>&);
428
429 size_t size() const { return m_size; }
430 size_t capacity() const { return m_buffer.capacity(); }
431 bool isEmpty() const { return !size(); }
432
433 T& at(size_t i)
434 {
435 ASSERT(i < size());
436 return m_buffer.buffer()[i];
437 }
438 const T& at(size_t i) const
439 {
440 ASSERT(i < size());
441 return m_buffer.buffer()[i];
442 }
443
444 T& operator[](size_t i) { return at(i); }
445 const T& operator[](size_t i) const { return at(i); }
446
447 T* data() { return m_buffer.buffer(); }
448 const T* data() const { return m_buffer.buffer(); }
449
450 iterator begin() { return data(); }
451 iterator end() { return begin() + m_size; }
452 const_iterator begin() const { return data(); }
453 const_iterator end() const { return begin() + m_size; }
454
455 T& first() { return at(0); }
456 const T& first() const { return at(0); }
457 T& last() { return at(size() - 1); }
458 const T& last() const { return at(size() - 1); }
459
460 void shrink(size_t size);
461 void grow(size_t size);
462 void resize(size_t size);
463 void reserveCapacity(size_t newCapacity);
464
465 void clear() { if (m_size) shrink(0); }
466
467 template<typename U> void append(const U*, size_t);
468 template<typename U> void append(const U&);
469 template<typename U> void uncheckedAppend(const U& val);
470 template<typename U, size_t c> void append(const Vector<U, c>&);
471
472 template<typename U> void insert(size_t position, const U*, size_t);
473 template<typename U> void insert(size_t position, const U&);
474 template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&);
475
476 template<typename U> void prepend(const U*, size_t);
477 template<typename U> void prepend(const U&);
478 template<typename U, size_t c> void prepend(const Vector<U, c>&);
479
480 void remove(size_t position);
481
482 void removeLast()
483 {
484 ASSERT(!isEmpty());
485 shrink(size() - 1);
486 }
487
488 Vector(size_t size, const T& val)
489 : m_size(size)
490 , m_buffer(size)
491 {
492 TypeOperations::uninitializedFill(begin(), end(), val);
493 }
494
495 void fill(const T&, size_t);
496 void fill(const T& val) { fill(val, size()); }
497
498 template<typename Iterator> void appendRange(Iterator start, Iterator end);
499
500 T* releaseBuffer();
501
502 void swap(Vector<T, inlineCapacity>& other)
503 {
504 std::swap(m_size, other.m_size);
505 m_buffer.swap(other.m_buffer);
506 }
507
508 private:
509 void expandCapacity(size_t newMinCapacity);
510 const T* expandCapacity(size_t newMinCapacity, const T*);
511 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
512
513 size_t m_size;
514 Buffer m_buffer;
515 };
516
517 template<typename T, size_t inlineCapacity>
518 Vector<T, inlineCapacity>::Vector(const Vector& other)
519 : m_size(other.size())
520 , m_buffer(other.capacity())
521 {
522 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
523 }
524
525 template<typename T, size_t inlineCapacity>
526 template<size_t otherCapacity>
527 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
528 : m_size(other.size())
529 , m_buffer(other.capacity())
530 {
531 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
532 }
533
534 template<typename T, size_t inlineCapacity>
535 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
536 {
537 if (&other == this)
538 return *this;
539
540 if (size() > other.size())
541 shrink(other.size());
542 else if (other.size() > capacity()) {
543 clear();
544 reserveCapacity(other.size());
545 }
546
547 std::copy(other.begin(), other.begin() + size(), begin());
548 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
549 m_size = other.size();
550
551 return *this;
552 }
553
554 template<typename T, size_t inlineCapacity>
555 template<size_t otherCapacity>
556 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
557 {
558 if (&other == this)
559 return *this;
560
561 if (size() > other.size())
562 shrink(other.size());
563 else if (other.size() > capacity()) {
564 clear();
565 reserveCapacity(other.size());
566 }
567
568 std::copy(other.begin(), other.begin() + size(), begin());
569 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
570 m_size = other.size();
571
572 return *this;
573 }
574
575 template<typename T, size_t inlineCapacity>
576 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
577 {
578 if (size() > newSize)
579 shrink(newSize);
580 else if (newSize > capacity()) {
581 clear();
582 reserveCapacity(newSize);
583 }
584
585 std::fill(begin(), end(), val);
586 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
587 m_size = newSize;
588 }
589
590 template<typename T, size_t inlineCapacity>
591 template<typename Iterator>
592 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
593 {
594 for (Iterator it = start; it != end; ++it)
595 append(*it);
596 }
597
598 template<typename T, size_t inlineCapacity>
599 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
600 {
601 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
602 }
603
604 template<typename T, size_t inlineCapacity>
605 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
606 {
607 if (ptr < begin() || ptr >= end()) {
608 expandCapacity(newMinCapacity);
609 return ptr;
610 }
611 size_t index = ptr - begin();
612 expandCapacity(newMinCapacity);
613 return begin() + index;
614 }
615
616 template<typename T, size_t inlineCapacity> template<typename U>
617 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
618 {
619 expandCapacity(newMinCapacity);
620 return ptr;
621 }
622
623 template<typename T, size_t inlineCapacity>
624 void Vector<T, inlineCapacity>::resize(size_t size)
625 {
626 if (size <= m_size)
627 TypeOperations::destruct(begin() + size, end());
628 else {
629 if (size > capacity())
630 expandCapacity(size);
631 TypeOperations::initialize(end(), begin() + size);
632 }
633
634 m_size = size;
635 }
636
637 template<typename T, size_t inlineCapacity>
638 void Vector<T, inlineCapacity>::shrink(size_t size)
639 {
640 ASSERT(size <= m_size);
641 TypeOperations::destruct(begin() + size, end());
642 m_size = size;
643 }
644
645 template<typename T, size_t inlineCapacity>
646 void Vector<T, inlineCapacity>::grow(size_t size)
647 {
648 ASSERT(size >= m_size);
649 if (size > capacity())
650 expandCapacity(size);
651 TypeOperations::initialize(end(), begin() + size);
652 m_size = size;
653 }
654
655 template<typename T, size_t inlineCapacity>
656 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
657 {
658 if (newCapacity <= capacity())
659 return;
660 T* oldBuffer = begin();
661 T* oldEnd = end();
662 m_buffer.allocateBuffer(newCapacity);
663 TypeOperations::move(oldBuffer, oldEnd, begin());
664 m_buffer.deallocateBuffer(oldBuffer);
665 }
666
667 // Templatizing these is better than just letting the conversion happen implicitly,
668 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
669 // without refcount thrash.
670
671 template<typename T, size_t inlineCapacity> template<typename U>
672 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
673 {
674 size_t newSize = m_size + dataSize;
675 if (newSize > capacity())
676 data = expandCapacity(newSize, data);
677 T* dest = end();
678 for (size_t i = 0; i < dataSize; ++i)
679 new (&dest[i]) T(data[i]);
680 m_size = newSize;
681 }
682
683 template<typename T, size_t inlineCapacity> template<typename U>
684 inline void Vector<T, inlineCapacity>::append(const U& val)
685 {
686 const U* ptr = &val;
687 if (size() == capacity())
688 ptr = expandCapacity(size() + 1, ptr);
689
690#if COMPILER(MSVC7)
691 // FIXME: MSVC7 generates compilation errors when trying to assign
692 // a pointer to a Vector of its base class (i.e. can't downcast). So far
693 // I've been unable to determine any logical reason for this, so I can
694 // only assume it is a bug with the compiler. Casting is a bad solution,
695 // however, because it subverts implicit conversions, so a better
696 // one is needed.
697 new (end()) T(static_cast<T>(*ptr));
698#else
699 new (end()) T(*ptr);
700#endif
701 ++m_size;
702 }
703
704 // This version of append saves a branch in the case where you know that the
705 // vector's capacity is large enough for the append to succeed.
706
707 template<typename T, size_t inlineCapacity> template<typename U>
708 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
709 {
710 ASSERT(size() < capacity());
711 const U* ptr = &val;
712 new (end()) T(*ptr);
713 ++m_size;
714 }
715
716 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
717 inline void Vector<T, inlineCapacity>::append(const Vector<U, c>& val)
718 {
719 append(val.begin(), val.size());
720 }
721
722 template<typename T, size_t inlineCapacity> template<typename U>
723 void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize)
724 {
725 ASSERT(position <= size());
726 size_t newSize = m_size + dataSize;
727 if (newSize > capacity())
728 data = expandCapacity(newSize, data);
729 T* spot = begin() + position;
730 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
731 for (size_t i = 0; i < dataSize; ++i)
732 new (&spot[i]) T(data[i]);
733 m_size = newSize;
734 }
735
736 template<typename T, size_t inlineCapacity> template<typename U>
737 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
738 {
739 ASSERT(position <= size());
740 const U* data = &val;
741 if (size() == capacity())
742 data = expandCapacity(size() + 1, data);
743 T* spot = begin() + position;
744 TypeOperations::moveOverlapping(spot, end(), spot + 1);
745 new (spot) T(*data);
746 ++m_size;
747 }
748
749 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
750 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val)
751 {
752 insert(position, val.begin(), val.size());
753 }
754
755 template<typename T, size_t inlineCapacity> template<typename U>
756 void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
757 {
758 insert(0, data, dataSize);
759 }
760
761 template<typename T, size_t inlineCapacity> template<typename U>
762 inline void Vector<T, inlineCapacity>::prepend(const U& val)
763 {
764 insert(0, val);
765 }
766
767 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
768 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
769 {
770 insert(0, val.begin(), val.size());
771 }
772
773 template<typename T, size_t inlineCapacity>
774 inline void Vector<T, inlineCapacity>::remove(size_t position)
775 {
776 ASSERT(position < size());
777 T* spot = begin() + position;
778 spot->~T();
779 TypeOperations::moveOverlapping(spot + 1, end(), spot);
780 --m_size;
781 }
782
783 template<typename T, size_t inlineCapacity>
784 inline T* Vector<T, inlineCapacity>::releaseBuffer()
785 {
786 T* buffer = m_buffer.releaseBuffer();
787 if (inlineCapacity && !buffer && m_size) {
788 // If the vector had some data, but no buffer to release,
789 // that means it was using the inline buffer. In that case,
790 // we create a brand new buffer so the caller always gets one.
791 size_t bytes = m_size * sizeof(T);
792 buffer = static_cast<T*>(fastMalloc(bytes));
793 memcpy(buffer, data(), bytes);
794 }
795 ASSERT(buffer);
796 m_size = 0;
797 return buffer;
798 }
799
800 template<typename T, size_t inlineCapacity>
801 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
802 {
803 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
804 iterator end = collection.end();
805 for (iterator it = collection.begin(); it != end; ++it)
806 delete *it;
807 }
808
809 template<typename T, size_t inlineCapacity>
810 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
811 {
812 a.swap(b);
813 }
814
815 template<typename T, size_t inlineCapacity>
816 bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
817 {
818 if (a.size() != b.size())
819 return false;
820
821 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
822 }
823
824 template<typename T, size_t inlineCapacity>
825 inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b)
826 {
827 return !(a == b);
828 }
829
830
831} // namespace WTF
832
833using WTF::Vector;
834
835#endif // WTF_Vector_h