Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Side by Side Diff: Source/WTF/wtf/Vector.h

Issue 14238015: Move Source/WTF/wtf to Source/wtf (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 <wtf/Alignment.h>
25 #include <wtf/FastAllocBase.h>
26 #include <wtf/Noncopyable.h>
27 #include <wtf/NotFound.h>
28 #include <wtf/StdLibExtras.h>
29 #include <wtf/UnusedParam.h>
30 #include <wtf/ValueCheck.h>
31 #include <wtf/VectorTraits.h>
32 #include <limits>
33 #include <utility>
34 #include <string.h>
35
36 namespace WTF {
37
38 template <bool needsDestruction, typename T>
39 struct VectorDestructor;
40
41 template<typename T>
42 struct VectorDestructor<false, T>
43 {
44 static void destruct(T*, T*) {}
45 };
46
47 template<typename T>
48 struct VectorDestructor<true, T>
49 {
50 static void destruct(T* begin, T* end)
51 {
52 for (T* cur = begin; cur != end; ++cur)
53 cur->~T();
54 }
55 };
56
57 template <bool needsInitialization, bool canInitializeWithMemset, typename T >
58 struct VectorInitializer;
59
60 template<bool ignore, typename T>
61 struct VectorInitializer<false, ignore, T>
62 {
63 static void initialize(T*, T*) {}
64 };
65
66 template<typename T>
67 struct VectorInitializer<true, false, T>
68 {
69 static void initialize(T* begin, T* end)
70 {
71 for (T* cur = begin; cur != end; ++cur)
72 new (NotNull, cur) T;
73 }
74 };
75
76 template<typename T>
77 struct VectorInitializer<true, true, T>
78 {
79 static void initialize(T* begin, T* end)
80 {
81 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<cha r*>(begin));
82 }
83 };
84
85 template <bool canMoveWithMemcpy, typename T>
86 struct VectorMover;
87
88 template<typename T>
89 struct VectorMover<false, T>
90 {
91 static void move(const T* src, const T* srcEnd, T* dst)
92 {
93 while (src != srcEnd) {
94 new (NotNull, dst) T(*src);
95 #if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
96 const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compi ler bug.
97 #else
98 src->~T();
99 #endif
100 ++dst;
101 ++src;
102 }
103 }
104 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
105 {
106 if (src > dst)
107 move(src, srcEnd, dst);
108 else {
109 T* dstEnd = dst + (srcEnd - src);
110 while (src != srcEnd) {
111 --srcEnd;
112 --dstEnd;
113 new (NotNull, dstEnd) T(*srcEnd);
114 srcEnd->~T();
115 }
116 }
117 }
118 };
119
120 template<typename T>
121 struct VectorMover<true, T>
122 {
123 static void move(const T* src, const T* srcEnd, T* dst)
124 {
125 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret _cast<const char*>(src));
126 }
127 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
128 {
129 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpre t_cast<const char*>(src));
130 }
131 };
132
133 template <bool canCopyWithMemcpy, typename T>
134 struct VectorCopier;
135
136 template<typename T>
137 struct VectorCopier<false, T>
138 {
139 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
140 {
141 while (src != srcEnd) {
142 new (NotNull, dst) T(*src);
143 ++dst;
144 ++src;
145 }
146 }
147 };
148
149 template<typename T>
150 struct VectorCopier<true, T>
151 {
152 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
153 {
154 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret _cast<const char*>(src));
155 }
156 };
157
158 template <bool canFillWithMemset, typename T>
159 struct VectorFiller;
160
161 template<typename T>
162 struct VectorFiller<false, T>
163 {
164 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
165 {
166 while (dst != dstEnd) {
167 new (NotNull, dst) T(val);
168 ++dst;
169 }
170 }
171 };
172
173 template<typename T>
174 struct VectorFiller<true, T>
175 {
176 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
177 {
178 ASSERT(sizeof(T) == sizeof(char));
179 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE)
180 if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst)))
181 #endif
182 memset(dst, val, dstEnd - dst);
183 }
184 };
185
186 template<bool canCompareWithMemcmp, typename T>
187 struct VectorComparer;
188
189 template<typename T>
190 struct VectorComparer<false, T>
191 {
192 static bool compare(const T* a, const T* b, size_t size)
193 {
194 for (size_t i = 0; i < size; ++i)
195 if (!(a[i] == b[i]))
196 return false;
197 return true;
198 }
199 };
200
201 template<typename T>
202 struct VectorComparer<true, T>
203 {
204 static bool compare(const T* a, const T* b, size_t size)
205 {
206 return memcmp(a, b, sizeof(T) * size) == 0;
207 }
208 };
209
210 template<typename T>
211 struct VectorTypeOperations
212 {
213 static void destruct(T* begin, T* end)
214 {
215 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(beg in, end);
216 }
217
218 static void initialize(T* begin, T* end)
219 {
220 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits <T>::canInitializeWithMemset, T>::initialize(begin, end);
221 }
222
223 static void move(const T* src, const T* srcEnd, T* dst)
224 {
225 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd , dst);
226 }
227
228 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
229 {
230 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping( src, srcEnd, dst);
231 }
232
233 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
234 {
235 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCo py(src, srcEnd, dst);
236 }
237
238 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
239 {
240 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFi ll(dst, dstEnd, val);
241 }
242
243 static bool compare(const T* a, const T* b, size_t size)
244 {
245 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::com pare(a, b, size);
246 }
247 };
248
249 template<typename T>
250 class VectorBufferBase {
251 WTF_MAKE_NONCOPYABLE(VectorBufferBase);
252 public:
253 void allocateBuffer(size_t newCapacity)
254 {
255 ASSERT(newCapacity);
256 // Using "unsigned" is not a limitation because Chromium's max mallo c() is 2GB even on 64-bit.
257 RELEASE_ASSERT(newCapacity <= std::numeric_limits<unsigned>::max() / sizeof(T));
258 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
259 m_capacity = sizeToAllocate / sizeof(T);
260 m_buffer = static_cast<T*>(fastMalloc(sizeToAllocate));
261 }
262
263 bool tryAllocateBuffer(size_t newCapacity)
264 {
265 ASSERT(newCapacity);
266 // Using "unsigned" is not a limitation because Chromium's max mallo c() is 2GB even on 64-bit.
267 if (newCapacity > std::numeric_limits<unsigned>::max() / sizeof(T))
268 return false;
269
270 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
271 T* newBuffer;
272 if (tryFastMalloc(sizeToAllocate).getValue(newBuffer)) {
273 m_capacity = sizeToAllocate / sizeof(T);
274 m_buffer = newBuffer;
275 return true;
276 }
277 return false;
278 }
279
280 bool shouldReallocateBuffer(size_t newCapacity) const
281 {
282 return VectorTraits<T>::canMoveWithMemcpy && m_capacity && newCapaci ty;
283 }
284
285 void reallocateBuffer(size_t newCapacity)
286 {
287 ASSERT(shouldReallocateBuffer(newCapacity));
288 // Using "unsigned" is not a limitation because Chromium's max mallo c() is 2GB even on 64-bit.
289 RELEASE_ASSERT(newCapacity <= std::numeric_limits<unsigned>::max() / sizeof(T));
290 size_t sizeToAllocate = fastMallocGoodSize(newCapacity * sizeof(T));
291 m_capacity = sizeToAllocate / sizeof(T);
292 m_buffer = static_cast<T*>(fastRealloc(m_buffer, sizeToAllocate));
293 }
294
295 void deallocateBuffer(T* bufferToDeallocate)
296 {
297 if (!bufferToDeallocate)
298 return;
299
300 if (m_buffer == bufferToDeallocate) {
301 m_buffer = 0;
302 m_capacity = 0;
303 }
304
305 fastFree(bufferToDeallocate);
306 }
307
308 T* buffer() { return m_buffer; }
309 const T* buffer() const { return m_buffer; }
310 size_t capacity() const { return m_capacity; }
311
312 T* releaseBuffer()
313 {
314 T* buffer = m_buffer;
315 m_buffer = 0;
316 m_capacity = 0;
317 return buffer;
318 }
319
320 protected:
321 VectorBufferBase()
322 : m_buffer(0)
323 , m_capacity(0)
324 {
325 }
326
327 VectorBufferBase(T* buffer, size_t capacity)
328 : m_buffer(buffer)
329 , m_capacity(capacity)
330 {
331 }
332
333 ~VectorBufferBase()
334 {
335 // FIXME: It would be nice to find a way to ASSERT that m_buffer has n't leaked here.
336 }
337
338 T* m_buffer;
339 unsigned m_capacity; // Must come last so that it packs cleanly with Ve ctor::m_size on 64-bit.
340 };
341
342 template<typename T, size_t inlineCapacity>
343 class VectorBuffer;
344
345 template<typename T>
346 class VectorBuffer<T, 0> : private VectorBufferBase<T> {
347 private:
348 typedef VectorBufferBase<T> Base;
349 public:
350 VectorBuffer()
351 {
352 }
353
354 VectorBuffer(size_t capacity)
355 {
356 // Calling malloc(0) might take a lock and may actually do an
357 // allocation on some systems.
358 if (capacity)
359 allocateBuffer(capacity);
360 }
361
362 ~VectorBuffer()
363 {
364 deallocateBuffer(buffer());
365 }
366
367 void swap(VectorBuffer<T, 0>& other)
368 {
369 std::swap(m_buffer, other.m_buffer);
370 std::swap(m_capacity, other.m_capacity);
371 }
372
373 void restoreInlineBufferIfNeeded() { }
374
375 using Base::allocateBuffer;
376 using Base::tryAllocateBuffer;
377 using Base::shouldReallocateBuffer;
378 using Base::reallocateBuffer;
379 using Base::deallocateBuffer;
380
381 using Base::buffer;
382 using Base::capacity;
383
384 using Base::releaseBuffer;
385 private:
386 using Base::m_buffer;
387 using Base::m_capacity;
388 };
389
390 template<typename T, size_t inlineCapacity>
391 class VectorBuffer : private VectorBufferBase<T> {
392 WTF_MAKE_NONCOPYABLE(VectorBuffer);
393 private:
394 typedef VectorBufferBase<T> Base;
395 public:
396 VectorBuffer()
397 : Base(inlineBuffer(), inlineCapacity)
398 {
399 }
400
401 VectorBuffer(size_t capacity)
402 : Base(inlineBuffer(), inlineCapacity)
403 {
404 if (capacity > inlineCapacity)
405 Base::allocateBuffer(capacity);
406 }
407
408 ~VectorBuffer()
409 {
410 deallocateBuffer(buffer());
411 }
412
413 void allocateBuffer(size_t newCapacity)
414 {
415 // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
416 if (newCapacity > inlineCapacity)
417 Base::allocateBuffer(newCapacity);
418 else {
419 m_buffer = inlineBuffer();
420 m_capacity = inlineCapacity;
421 }
422 }
423
424 bool tryAllocateBuffer(size_t newCapacity)
425 {
426 if (newCapacity > inlineCapacity)
427 return Base::tryAllocateBuffer(newCapacity);
428 m_buffer = inlineBuffer();
429 m_capacity = inlineCapacity;
430 return true;
431 }
432
433 void deallocateBuffer(T* bufferToDeallocate)
434 {
435 if (bufferToDeallocate == inlineBuffer())
436 return;
437 Base::deallocateBuffer(bufferToDeallocate);
438 }
439
440 bool shouldReallocateBuffer(size_t newCapacity) const
441 {
442 // We cannot reallocate the inline buffer.
443 return Base::shouldReallocateBuffer(newCapacity) && std::min(static_ cast<size_t>(m_capacity), newCapacity) > inlineCapacity;
444 }
445
446 void reallocateBuffer(size_t newCapacity)
447 {
448 ASSERT(shouldReallocateBuffer(newCapacity));
449 Base::reallocateBuffer(newCapacity);
450 }
451
452 void swap(VectorBuffer<T, inlineCapacity>& other)
453 {
454 if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuff er()) {
455 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
456 std::swap(m_capacity, other.m_capacity);
457 } else if (buffer() == inlineBuffer()) {
458 m_buffer = other.m_buffer;
459 other.m_buffer = other.inlineBuffer();
460 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
461 std::swap(m_capacity, other.m_capacity);
462 } else if (other.buffer() == other.inlineBuffer()) {
463 other.m_buffer = m_buffer;
464 m_buffer = inlineBuffer();
465 WTF::swap(m_inlineBuffer, other.m_inlineBuffer);
466 std::swap(m_capacity, other.m_capacity);
467 } else {
468 std::swap(m_buffer, other.m_buffer);
469 std::swap(m_capacity, other.m_capacity);
470 }
471 }
472
473 void restoreInlineBufferIfNeeded()
474 {
475 if (m_buffer)
476 return;
477 m_buffer = inlineBuffer();
478 m_capacity = inlineCapacity;
479 }
480
481 using Base::buffer;
482 using Base::capacity;
483
484 T* releaseBuffer()
485 {
486 if (buffer() == inlineBuffer())
487 return 0;
488 return Base::releaseBuffer();
489 }
490
491 private:
492 using Base::m_buffer;
493 using Base::m_capacity;
494
495 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
496 T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffe r); }
497 const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_ inlineBuffer.buffer); }
498
499 AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
500 };
501
502 template<typename T, size_t inlineCapacity = 0>
503 class Vector : private VectorBuffer<T, inlineCapacity> {
504 WTF_MAKE_FAST_ALLOCATED;
505 private:
506 typedef VectorBuffer<T, inlineCapacity> Base;
507 typedef VectorTypeOperations<T> TypeOperations;
508
509 public:
510 typedef T ValueType;
511
512 typedef T* iterator;
513 typedef const T* const_iterator;
514 typedef std::reverse_iterator<iterator> reverse_iterator;
515 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
516
517 Vector()
518 : m_size(0)
519 {
520 }
521
522 explicit Vector(size_t size)
523 : Base(size)
524 , m_size(size)
525 {
526 if (begin())
527 TypeOperations::initialize(begin(), end());
528 }
529
530 ~Vector()
531 {
532 if (m_size)
533 shrink(0);
534 }
535
536 Vector(const Vector&);
537 template<size_t otherCapacity>
538 Vector(const Vector<T, otherCapacity>&);
539
540 Vector& operator=(const Vector&);
541 template<size_t otherCapacity>
542 Vector& operator=(const Vector<T, otherCapacity>&);
543
544 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
545 Vector(Vector&&);
546 Vector& operator=(Vector&&);
547 #endif
548
549 size_t size() const { return m_size; }
550 size_t capacity() const { return Base::capacity(); }
551 bool isEmpty() const { return !size(); }
552
553 T& at(size_t i)
554 {
555 RELEASE_ASSERT(i < size());
556 return Base::buffer()[i];
557 }
558 const T& at(size_t i) const
559 {
560 RELEASE_ASSERT(i < size());
561 return Base::buffer()[i];
562 }
563
564 T& operator[](size_t i) { return at(i); }
565 const T& operator[](size_t i) const { return at(i); }
566
567 T* data() { return Base::buffer(); }
568 const T* data() const { return Base::buffer(); }
569
570 iterator begin() { return data(); }
571 iterator end() { return begin() + m_size; }
572 const_iterator begin() const { return data(); }
573 const_iterator end() const { return begin() + m_size; }
574
575 reverse_iterator rbegin() { return reverse_iterator(end()); }
576 reverse_iterator rend() { return reverse_iterator(begin()); }
577 const_reverse_iterator rbegin() const { return const_reverse_iterator(en d()); }
578 const_reverse_iterator rend() const { return const_reverse_iterator(begi n()); }
579
580 T& first() { return at(0); }
581 const T& first() const { return at(0); }
582 T& last() { return at(size() - 1); }
583 const T& last() const { return at(size() - 1); }
584
585 template<typename U> bool contains(const U&) const;
586 template<typename U> size_t find(const U&) const;
587 template<typename U> size_t reverseFind(const U&) const;
588
589 void shrink(size_t size);
590 void grow(size_t size);
591 void resize(size_t size);
592 void reserveCapacity(size_t newCapacity);
593 bool tryReserveCapacity(size_t newCapacity);
594 void reserveInitialCapacity(size_t initialCapacity);
595 void shrinkCapacity(size_t newCapacity);
596 void shrinkToFit() { shrinkCapacity(size()); }
597
598 void clear() { shrinkCapacity(0); }
599
600 template<typename U> void append(const U*, size_t);
601 template<typename U> void append(const U&);
602 template<typename U> void uncheckedAppend(const U& val);
603 template<size_t otherCapacity> void append(const Vector<T, otherCapacity >&);
604 template<typename U, size_t otherCapacity> void appendVector(const Vecto r<U, otherCapacity>&);
605 template<typename U> bool tryAppend(const U*, size_t);
606
607 template<typename U> void insert(size_t position, const U*, size_t);
608 template<typename U> void insert(size_t position, const U&);
609 template<typename U, size_t c> void insert(size_t position, const Vector <U, c>&);
610
611 template<typename U> void prepend(const U*, size_t);
612 template<typename U> void prepend(const U&);
613 template<typename U, size_t c> void prepend(const Vector<U, c>&);
614
615 void remove(size_t position);
616 void remove(size_t position, size_t length);
617
618 void removeLast()
619 {
620 ASSERT(!isEmpty());
621 shrink(size() - 1);
622 }
623
624 Vector(size_t size, const T& val)
625 : Base(size)
626 , m_size(size)
627 {
628 if (begin())
629 TypeOperations::uninitializedFill(begin(), end(), val);
630 }
631
632 void fill(const T&, size_t);
633 void fill(const T& val) { fill(val, size()); }
634
635 template<typename Iterator> void appendRange(Iterator start, Iterator en d);
636
637 T* releaseBuffer();
638
639 void swap(Vector<T, inlineCapacity>& other)
640 {
641 std::swap(m_size, other.m_size);
642 Base::swap(other);
643 }
644
645 void reverse();
646
647 void checkConsistency();
648
649 private:
650 void expandCapacity(size_t newMinCapacity);
651 const T* expandCapacity(size_t newMinCapacity, const T*);
652 bool tryExpandCapacity(size_t newMinCapacity);
653 const T* tryExpandCapacity(size_t newMinCapacity, const T*);
654 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
655 template<typename U> void appendSlowCase(const U&);
656
657 unsigned m_size;
658
659 using Base::buffer;
660 using Base::capacity;
661 using Base::swap;
662 using Base::allocateBuffer;
663 using Base::deallocateBuffer;
664 using Base::tryAllocateBuffer;
665 using Base::shouldReallocateBuffer;
666 using Base::reallocateBuffer;
667 using Base::restoreInlineBufferIfNeeded;
668 using Base::releaseBuffer;
669 };
670
671 template<typename T, size_t inlineCapacity>
672 Vector<T, inlineCapacity>::Vector(const Vector& other)
673 : Base(other.capacity())
674 , m_size(other.size())
675 {
676 if (begin())
677 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin( ));
678 }
679
680 template<typename T, size_t inlineCapacity>
681 template<size_t otherCapacity>
682 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
683 : Base(other.capacity())
684 , m_size(other.size())
685 {
686 if (begin())
687 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin( ));
688 }
689
690 template<typename T, size_t inlineCapacity>
691 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector <T, inlineCapacity>& other)
692 {
693 if (&other == this)
694 return *this;
695
696 if (size() > other.size())
697 shrink(other.size());
698 else if (other.size() > capacity()) {
699 clear();
700 reserveCapacity(other.size());
701 if (!begin())
702 return *this;
703 }
704
705 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
706 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
707 if (!begin())
708 return *this;
709 #endif
710
711 std::copy(other.begin(), other.begin() + size(), begin());
712 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd());
713 m_size = other.size();
714
715 return *this;
716 }
717
718 inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
719
720 template<typename T, size_t inlineCapacity>
721 template<size_t otherCapacity>
722 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector <T, otherCapacity>& other)
723 {
724 // If the inline capacities match, we should call the more specific
725 // template. If the inline capacities don't match, the two objects
726 // shouldn't be allocated the same address.
727 ASSERT(!typelessPointersAreEqual(&other, this));
728
729 if (size() > other.size())
730 shrink(other.size());
731 else if (other.size() > capacity()) {
732 clear();
733 reserveCapacity(other.size());
734 if (!begin())
735 return *this;
736 }
737
738 // Works around an assert in VS2010. See https://connect.microsoft.com/VisualStu dio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
739 #if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
740 if (!begin())
741 return *this;
742 #endif
743
744 std::copy(other.begin(), other.begin() + size(), begin());
745 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), e nd());
746 m_size = other.size();
747
748 return *this;
749 }
750
751 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
752 template<typename T, size_t inlineCapacity>
753 Vector<T, inlineCapacity>::Vector(Vector<T, inlineCapacity>&& other)
754 : m_size(0)
755 {
756 // It's a little weird to implement a move constructor using swap but th is way we
757 // don't have to add a move constructor to VectorBuffer.
758 swap(other);
759 }
760
761 template<typename T, size_t inlineCapacity>
762 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(Vector<T, in lineCapacity>&& other)
763 {
764 swap(other);
765 return *this;
766 }
767 #endif
768
769 template<typename T, size_t inlineCapacity>
770 template<typename U>
771 bool Vector<T, inlineCapacity>::contains(const U& value) const
772 {
773 return find(value) != notFound;
774 }
775
776 template<typename T, size_t inlineCapacity>
777 template<typename U>
778 size_t Vector<T, inlineCapacity>::find(const U& value) const
779 {
780 const T* b = begin();
781 const T* e = end();
782 for (const T* iter = b; iter < e; ++iter) {
783 if (*iter == value)
784 return iter - b;
785 }
786 return notFound;
787 }
788
789 template<typename T, size_t inlineCapacity>
790 template<typename U>
791 size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const
792 {
793 const T* b = begin();
794 const T* iter = end();
795 while (iter > b) {
796 --iter;
797 if (*iter == value)
798 return iter - b;
799 }
800 return notFound;
801 }
802
803 template<typename T, size_t inlineCapacity>
804 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
805 {
806 if (size() > newSize)
807 shrink(newSize);
808 else if (newSize > capacity()) {
809 clear();
810 reserveCapacity(newSize);
811 if (!begin())
812 return;
813 }
814
815 std::fill(begin(), end(), val);
816 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
817 m_size = newSize;
818 }
819
820 template<typename T, size_t inlineCapacity>
821 template<typename Iterator>
822 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end)
823 {
824 for (Iterator it = start; it != end; ++it)
825 append(*it);
826 }
827
828 template<typename T, size_t inlineCapacity>
829 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
830 {
831 reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(16 ), capacity() + capacity() / 4 + 1)));
832 }
833
834 template<typename T, size_t inlineCapacity>
835 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, co nst T* ptr)
836 {
837 if (ptr < begin() || ptr >= end()) {
838 expandCapacity(newMinCapacity);
839 return ptr;
840 }
841 size_t index = ptr - begin();
842 expandCapacity(newMinCapacity);
843 return begin() + index;
844 }
845
846 template<typename T, size_t inlineCapacity>
847 bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity)
848 {
849 return tryReserveCapacity(std::max(newMinCapacity, std::max(static_cast< size_t>(16), capacity() + capacity() / 4 + 1)));
850 }
851
852 template<typename T, size_t inlineCapacity>
853 const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr)
854 {
855 if (ptr < begin() || ptr >= end()) {
856 if (!tryExpandCapacity(newMinCapacity))
857 return 0;
858 return ptr;
859 }
860 size_t index = ptr - begin();
861 if (!tryExpandCapacity(newMinCapacity))
862 return 0;
863 return begin() + index;
864 }
865
866 template<typename T, size_t inlineCapacity> template<typename U>
867 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U * ptr)
868 {
869 expandCapacity(newMinCapacity);
870 return ptr;
871 }
872
873 template<typename T, size_t inlineCapacity>
874 inline void Vector<T, inlineCapacity>::resize(size_t size)
875 {
876 if (size <= m_size)
877 TypeOperations::destruct(begin() + size, end());
878 else {
879 if (size > capacity())
880 expandCapacity(size);
881 if (begin())
882 TypeOperations::initialize(end(), begin() + size);
883 }
884
885 m_size = size;
886 }
887
888 template<typename T, size_t inlineCapacity>
889 void Vector<T, inlineCapacity>::shrink(size_t size)
890 {
891 ASSERT(size <= m_size);
892 TypeOperations::destruct(begin() + size, end());
893 m_size = size;
894 }
895
896 template<typename T, size_t inlineCapacity>
897 void Vector<T, inlineCapacity>::grow(size_t size)
898 {
899 ASSERT(size >= m_size);
900 if (size > capacity())
901 expandCapacity(size);
902 if (begin())
903 TypeOperations::initialize(end(), begin() + size);
904 m_size = size;
905 }
906
907 template<typename T, size_t inlineCapacity>
908 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
909 {
910 if (newCapacity <= capacity())
911 return;
912 T* oldBuffer = begin();
913 T* oldEnd = end();
914 Base::allocateBuffer(newCapacity);
915 if (begin())
916 TypeOperations::move(oldBuffer, oldEnd, begin());
917 Base::deallocateBuffer(oldBuffer);
918 }
919
920 template<typename T, size_t inlineCapacity>
921 bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity)
922 {
923 if (newCapacity <= capacity())
924 return true;
925 T* oldBuffer = begin();
926 T* oldEnd = end();
927 if (!Base::tryAllocateBuffer(newCapacity))
928 return false;
929 ASSERT(begin());
930 TypeOperations::move(oldBuffer, oldEnd, begin());
931 Base::deallocateBuffer(oldBuffer);
932 return true;
933 }
934
935 template<typename T, size_t inlineCapacity>
936 inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initial Capacity)
937 {
938 ASSERT(!m_size);
939 ASSERT(capacity() == inlineCapacity);
940 if (initialCapacity > inlineCapacity)
941 Base::allocateBuffer(initialCapacity);
942 }
943
944 template<typename T, size_t inlineCapacity>
945 void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity)
946 {
947 if (newCapacity >= capacity())
948 return;
949
950 if (newCapacity < size())
951 shrink(newCapacity);
952
953 T* oldBuffer = begin();
954 if (newCapacity > 0) {
955 if (Base::shouldReallocateBuffer(newCapacity)) {
956 Base::reallocateBuffer(newCapacity);
957 return;
958 }
959
960 T* oldEnd = end();
961 Base::allocateBuffer(newCapacity);
962 if (begin() != oldBuffer)
963 TypeOperations::move(oldBuffer, oldEnd, begin());
964 }
965
966 Base::deallocateBuffer(oldBuffer);
967 Base::restoreInlineBufferIfNeeded();
968 }
969
970 // Templatizing these is better than just letting the conversion happen impl icitly,
971 // because for instance it allows a PassRefPtr to be appended to a RefPtr ve ctor
972 // without refcount thrash.
973
974 template<typename T, size_t inlineCapacity> template<typename U>
975 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
976 {
977 size_t newSize = m_size + dataSize;
978 if (newSize > capacity()) {
979 data = expandCapacity(newSize, data);
980 if (!begin())
981 return;
982 }
983 RELEASE_ASSERT(newSize >= m_size);
984 T* dest = end();
985 for (size_t i = 0; i < dataSize; ++i)
986 new (NotNull, &dest[i]) T(data[i]);
987 m_size = newSize;
988 }
989
990 template<typename T, size_t inlineCapacity> template<typename U>
991 bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize)
992 {
993 size_t newSize = m_size + dataSize;
994 if (newSize > capacity()) {
995 data = tryExpandCapacity(newSize, data);
996 if (!data)
997 return false;
998 ASSERT(begin());
999 }
1000 if (newSize < m_size)
1001 return false;
1002 T* dest = end();
1003 for (size_t i = 0; i < dataSize; ++i)
1004 new (NotNull, &dest[i]) T(data[i]);
1005 m_size = newSize;
1006 return true;
1007 }
1008
1009 template<typename T, size_t inlineCapacity> template<typename U>
1010 ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val)
1011 {
1012 if (size() != capacity()) {
1013 new (NotNull, end()) T(val);
1014 ++m_size;
1015 return;
1016 }
1017
1018 appendSlowCase(val);
1019 }
1020
1021 template<typename T, size_t inlineCapacity> template<typename U>
1022 void Vector<T, inlineCapacity>::appendSlowCase(const U& val)
1023 {
1024 ASSERT(size() == capacity());
1025
1026 const U* ptr = &val;
1027 ptr = expandCapacity(size() + 1, ptr);
1028 if (!begin())
1029 return;
1030
1031 new (NotNull, end()) T(*ptr);
1032 ++m_size;
1033 }
1034
1035 // This version of append saves a branch in the case where you know that the
1036 // vector's capacity is large enough for the append to succeed.
1037
1038 template<typename T, size_t inlineCapacity> template<typename U>
1039 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val)
1040 {
1041 ASSERT(size() < capacity());
1042 const U* ptr = &val;
1043 new (NotNull, end()) T(*ptr);
1044 ++m_size;
1045 }
1046
1047 // This method should not be called append, a better name would be appendEle ments.
1048 // It could also be eliminated entirely, and call sites could just use
1049 // appendRange(val.begin(), val.end()).
1050 template<typename T, size_t inlineCapacity> template<size_t otherCapacity>
1051 inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity> & val)
1052 {
1053 append(val.begin(), val.size());
1054 }
1055
1056 template<typename T, size_t inlineCapacity> template<typename U, size_t othe rCapacity>
1057 inline void Vector<T, inlineCapacity>::appendVector(const Vector<U, otherCap acity>& val)
1058 {
1059 append(val.begin(), val.size());
1060 }
1061
1062 template<typename T, size_t inlineCapacity> template<typename U>
1063 void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_ t dataSize)
1064 {
1065 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1066 size_t newSize = m_size + dataSize;
1067 if (newSize > capacity()) {
1068 data = expandCapacity(newSize, data);
1069 if (!begin())
1070 return;
1071 }
1072 RELEASE_ASSERT(newSize >= m_size);
1073 T* spot = begin() + position;
1074 TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
1075 for (size_t i = 0; i < dataSize; ++i)
1076 new (NotNull, &spot[i]) T(data[i]);
1077 m_size = newSize;
1078 }
1079
1080 template<typename T, size_t inlineCapacity> template<typename U>
1081 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
1082 {
1083 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1084 const U* data = &val;
1085 if (size() == capacity()) {
1086 data = expandCapacity(size() + 1, data);
1087 if (!begin())
1088 return;
1089 }
1090 T* spot = begin() + position;
1091 TypeOperations::moveOverlapping(spot, end(), spot + 1);
1092 new (NotNull, spot) T(*data);
1093 ++m_size;
1094 }
1095
1096 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1097 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector< U, c>& val)
1098 {
1099 insert(position, val.begin(), val.size());
1100 }
1101
1102 template<typename T, size_t inlineCapacity> template<typename U>
1103 void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize)
1104 {
1105 insert(0, data, dataSize);
1106 }
1107
1108 template<typename T, size_t inlineCapacity> template<typename U>
1109 inline void Vector<T, inlineCapacity>::prepend(const U& val)
1110 {
1111 insert(0, val);
1112 }
1113
1114 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
1115 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val)
1116 {
1117 insert(0, val.begin(), val.size());
1118 }
1119
1120 template<typename T, size_t inlineCapacity>
1121 inline void Vector<T, inlineCapacity>::remove(size_t position)
1122 {
1123 ASSERT_WITH_SECURITY_IMPLICATION(position < size());
1124 T* spot = begin() + position;
1125 spot->~T();
1126 TypeOperations::moveOverlapping(spot + 1, end(), spot);
1127 --m_size;
1128 }
1129
1130 template<typename T, size_t inlineCapacity>
1131 inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length )
1132 {
1133 ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
1134 ASSERT_WITH_SECURITY_IMPLICATION(position + length <= size());
1135 T* beginSpot = begin() + position;
1136 T* endSpot = beginSpot + length;
1137 TypeOperations::destruct(beginSpot, endSpot);
1138 TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
1139 m_size -= length;
1140 }
1141
1142 template<typename T, size_t inlineCapacity>
1143 inline void Vector<T, inlineCapacity>::reverse()
1144 {
1145 for (size_t i = 0; i < m_size / 2; ++i)
1146 std::swap(at(i), at(m_size - 1 - i));
1147 }
1148
1149 template<typename T, size_t inlineCapacity>
1150 inline T* Vector<T, inlineCapacity>::releaseBuffer()
1151 {
1152 T* buffer = Base::releaseBuffer();
1153 if (inlineCapacity && !buffer && m_size) {
1154 // If the vector had some data, but no buffer to release,
1155 // that means it was using the inline buffer. In that case,
1156 // we create a brand new buffer so the caller always gets one.
1157 size_t bytes = m_size * sizeof(T);
1158 buffer = static_cast<T*>(fastMalloc(bytes));
1159 memcpy(buffer, data(), bytes);
1160 }
1161 m_size = 0;
1162 return buffer;
1163 }
1164
1165 template<typename T, size_t inlineCapacity>
1166 inline void Vector<T, inlineCapacity>::checkConsistency()
1167 {
1168 #if !ASSERT_DISABLED
1169 for (size_t i = 0; i < size(); ++i)
1170 ValueCheck<T>::checkConsistency(at(i));
1171 #endif
1172 }
1173
1174 template<typename T, size_t inlineCapacity>
1175 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
1176 {
1177 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
1178 iterator end = collection.end();
1179 for (iterator it = collection.begin(); it != end; ++it)
1180 delete *it;
1181 }
1182
1183 template<typename T, size_t inlineCapacity>
1184 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
1185 {
1186 a.swap(b);
1187 }
1188
1189 template<typename T, size_t inlineCapacity>
1190 bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCa pacity>& b)
1191 {
1192 if (a.size() != b.size())
1193 return false;
1194
1195 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
1196 }
1197
1198 template<typename T, size_t inlineCapacity>
1199 inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, i nlineCapacity>& b)
1200 {
1201 return !(a == b);
1202 }
1203
1204 #if !ASSERT_DISABLED
1205 template<typename T> struct ValueCheck<Vector<T> > {
1206 typedef Vector<T> TraitType;
1207 static void checkConsistency(const Vector<T>& v)
1208 {
1209 v.checkConsistency();
1210 }
1211 };
1212 #endif
1213
1214 } // namespace WTF
1215
1216 using WTF::Vector;
1217
1218 #endif // WTF_Vector_h
OLDNEW
« no previous file with comments | « Source/WTF/wtf/ValueCheck.h ('k') | Source/WTF/wtf/VectorTraits.h » ('j') | Source/config.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698