File indexing completed on 2024-05-12 15:43:40
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 0004 * 0005 * This library is free software; you can redistribute it and/or 0006 * modify it under the terms of the GNU Library General Public 0007 * License as published by the Free Software Foundation; either 0008 * version 2 of the License, or (at your option) any later version. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 * 0020 */ 0021 0022 #ifndef WTF_Vector_h 0023 #define WTF_Vector_h 0024 0025 #include <wtf/Assertions.h> 0026 #include <wtf/FastMalloc.h> 0027 #include <wtf/Noncopyable.h> 0028 #include <wtf/VectorTraits.h> 0029 #include <limits> 0030 #include <stdlib.h> 0031 #include <cstring> 0032 #include <utility> 0033 0034 // Temporary workaround for Win32. 0035 // We should use NOMINMAX instead. 0036 #undef max 0037 0038 namespace WTF 0039 { 0040 0041 using std::min; 0042 using std::max; 0043 0044 template <bool needsDestruction, typename T> 0045 struct VectorDestructor; 0046 0047 template<typename T> 0048 struct VectorDestructor<false, T> { 0049 static void destruct(T *, T *) {} 0050 }; 0051 0052 template<typename T> 0053 struct VectorDestructor<true, T> { 0054 static void destruct(T *begin, T *end) 0055 { 0056 for (T *cur = begin; cur != end; ++cur) { 0057 cur->~T(); 0058 } 0059 } 0060 }; 0061 0062 template <bool needsInitialization, bool canInitializeWithMemset, typename T> 0063 struct VectorInitializer; 0064 0065 template<bool ignore, typename T> 0066 struct VectorInitializer<false, ignore, T> { 0067 static void initialize(T *, T *) {} 0068 }; 0069 0070 template<typename T> 0071 struct VectorInitializer<true, false, T> { 0072 static void initialize(T *begin, T *end) 0073 { 0074 for (T *cur = begin; cur != end; ++cur) { 0075 new(cur) T; 0076 } 0077 } 0078 }; 0079 0080 template<typename T> 0081 struct VectorInitializer<true, true, T> { 0082 static void initialize(T *begin, T *end) 0083 { 0084 std::memset(begin, 0, reinterpret_cast<char *>(end) - reinterpret_cast<char *>(begin)); 0085 } 0086 }; 0087 0088 template <bool canMoveWithMemcpy, typename T> 0089 struct VectorMover; 0090 0091 template<typename T> 0092 struct VectorMover<false, T> { 0093 static void move(const T *src, const T *srcEnd, T *dst) 0094 { 0095 while (src != srcEnd) { 0096 new(dst) T(*src); 0097 const_cast<T *>(src)->~T(); 0098 ++dst; 0099 ++src; 0100 } 0101 } 0102 static void moveOverlapping(const T *src, const T *srcEnd, T *dst) 0103 { 0104 if (src > dst) { 0105 move(src, srcEnd, dst); 0106 } else { 0107 T *dstEnd = dst + (srcEnd - src); 0108 while (src != srcEnd) { 0109 --srcEnd; 0110 --dstEnd; 0111 new(dstEnd) T(*srcEnd); 0112 const_cast<T *>(srcEnd)->~T(); 0113 } 0114 } 0115 } 0116 }; 0117 0118 template<typename T> 0119 struct VectorMover<true, T> { 0120 static void move(const T *src, const T *srcEnd, T *dst) 0121 { 0122 std::memcpy(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src)); 0123 } 0124 static void moveOverlapping(const T *src, const T *srcEnd, T *dst) 0125 { 0126 std::memmove(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src)); 0127 } 0128 }; 0129 0130 template <bool canCopyWithMemcpy, typename T> 0131 struct VectorCopier; 0132 0133 template<typename T> 0134 struct VectorCopier<false, T> { 0135 static void uninitializedCopy(const T *src, const T *srcEnd, T *dst) 0136 { 0137 while (src != srcEnd) { 0138 new(dst) T(*src); 0139 ++dst; 0140 ++src; 0141 } 0142 } 0143 }; 0144 0145 template<typename T> 0146 struct VectorCopier<true, T> { 0147 static void uninitializedCopy(const T *src, const T *srcEnd, T *dst) 0148 { 0149 std::memcpy(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src)); 0150 } 0151 }; 0152 0153 template <bool canFillWithMemset, typename T> 0154 struct VectorFiller; 0155 0156 template<typename T> 0157 struct VectorFiller<false, T> { 0158 static void uninitializedFill(T *dst, T *dstEnd, const T &val) 0159 { 0160 while (dst != dstEnd) { 0161 new(dst) T(val); 0162 ++dst; 0163 } 0164 } 0165 }; 0166 0167 template<typename T> 0168 struct VectorFiller<true, T> { 0169 static void uninitializedFill(T *dst, T *dstEnd, const T &val) 0170 { 0171 ASSERT(sizeof(T) == sizeof(char)); 0172 std::memset(dst, val, dstEnd - dst); 0173 } 0174 }; 0175 0176 template<bool canCompareWithMemcmp, typename T> 0177 struct VectorComparer; 0178 0179 template<typename T> 0180 struct VectorComparer<false, T> { 0181 static bool compare(const T *a, const T *b, size_t size) 0182 { 0183 for (size_t i = 0; i < size; ++i) 0184 if (a[i] != b[i]) { 0185 return false; 0186 } 0187 return true; 0188 } 0189 }; 0190 0191 template<typename T> 0192 struct VectorComparer<true, T> { 0193 static bool compare(const T *a, const T *b, size_t size) 0194 { 0195 return std::memcmp(a, b, sizeof(T) * size) == 0; 0196 } 0197 }; 0198 0199 template<typename T> 0200 struct VectorTypeOperations { 0201 static void destruct(T *begin, T *end) 0202 { 0203 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end); 0204 } 0205 0206 static void initialize(T *begin, T *end) 0207 { 0208 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end); 0209 } 0210 0211 static void move(const T *src, const T *srcEnd, T *dst) 0212 { 0213 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst); 0214 } 0215 0216 static void moveOverlapping(const T *src, const T *srcEnd, T *dst) 0217 { 0218 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst); 0219 } 0220 0221 static void uninitializedCopy(const T *src, const T *srcEnd, T *dst) 0222 { 0223 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst); 0224 } 0225 0226 static void uninitializedFill(T *dst, T *dstEnd, const T &val) 0227 { 0228 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val); 0229 } 0230 0231 static bool compare(const T *a, const T *b, size_t size) 0232 { 0233 return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size); 0234 } 0235 }; 0236 0237 template<typename T> 0238 class VectorBufferBase : Noncopyable 0239 { 0240 public: 0241 void allocateBuffer(size_t newCapacity) 0242 { 0243 m_capacity = newCapacity; 0244 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) { 0245 CRASH(); 0246 } 0247 m_buffer = static_cast<T *>(fastMalloc(newCapacity * sizeof(T))); 0248 } 0249 0250 void deallocateBuffer(T *bufferToDeallocate) 0251 { 0252 if (m_buffer == bufferToDeallocate) { 0253 m_buffer = nullptr; 0254 } 0255 fastFree(bufferToDeallocate); 0256 } 0257 0258 T *buffer() 0259 { 0260 return m_buffer; 0261 } 0262 const T *buffer() const 0263 { 0264 return m_buffer; 0265 } 0266 size_t capacity() const 0267 { 0268 return m_capacity; 0269 } 0270 0271 T *releaseBuffer() 0272 { 0273 T *buffer = m_buffer; 0274 m_buffer = nullptr; 0275 m_capacity = 0; 0276 return buffer; 0277 } 0278 0279 protected: 0280 VectorBufferBase() 0281 : m_buffer(nullptr) 0282 , m_capacity(0) 0283 { 0284 } 0285 0286 VectorBufferBase(T *buffer, size_t capacity) 0287 : m_buffer(buffer) 0288 , m_capacity(capacity) 0289 { 0290 } 0291 0292 ~VectorBufferBase() 0293 { 0294 // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here. 0295 } 0296 0297 T *m_buffer; 0298 size_t m_capacity; 0299 }; 0300 0301 template<typename T, size_t inlineCapacity> 0302 class VectorBuffer; 0303 0304 template<typename T> 0305 class VectorBuffer<T, 0> : private VectorBufferBase<T> 0306 { 0307 private: 0308 typedef VectorBufferBase<T> Base; 0309 public: 0310 VectorBuffer() 0311 { 0312 } 0313 0314 VectorBuffer(size_t capacity) 0315 { 0316 allocateBuffer(capacity); 0317 } 0318 0319 ~VectorBuffer() 0320 { 0321 deallocateBuffer(buffer()); 0322 } 0323 0324 void swap(VectorBuffer<T, 0> &other) 0325 { 0326 std::swap(m_buffer, other.m_buffer); 0327 std::swap(m_capacity, other.m_capacity); 0328 } 0329 0330 using Base::allocateBuffer; 0331 using Base::deallocateBuffer; 0332 0333 using Base::buffer; 0334 using Base::capacity; 0335 0336 using Base::releaseBuffer; 0337 private: 0338 using Base::m_buffer; 0339 using Base::m_capacity; 0340 }; 0341 0342 template<typename T, size_t inlineCapacity> 0343 class VectorBuffer : private VectorBufferBase<T> 0344 { 0345 private: 0346 typedef VectorBufferBase<T> Base; 0347 public: 0348 VectorBuffer() 0349 : Base(inlineBuffer(), inlineCapacity) 0350 { 0351 } 0352 0353 VectorBuffer(size_t capacity) 0354 : Base(inlineBuffer(), inlineCapacity) 0355 { 0356 allocateBuffer(capacity); 0357 } 0358 0359 ~VectorBuffer() 0360 { 0361 deallocateBuffer(buffer()); 0362 } 0363 0364 void allocateBuffer(size_t newCapacity) 0365 { 0366 if (newCapacity > inlineCapacity) { 0367 Base::allocateBuffer(newCapacity); 0368 } 0369 } 0370 0371 void deallocateBuffer(T *bufferToDeallocate) 0372 { 0373 if (bufferToDeallocate == inlineBuffer()) { 0374 return; 0375 } 0376 Base::deallocateBuffer(bufferToDeallocate); 0377 } 0378 0379 using Base::buffer; 0380 using Base::capacity; 0381 0382 T *releaseBuffer() 0383 { 0384 if (buffer() == inlineBuffer()) { 0385 return nullptr; 0386 } 0387 return Base::releaseBuffer(); 0388 } 0389 0390 private: 0391 using Base::m_buffer; 0392 using Base::m_capacity; 0393 0394 static const size_t m_inlineBufferSize = inlineCapacity *sizeof(T); 0395 T *inlineBuffer() 0396 { 0397 return reinterpret_cast<T *>(&m_inlineBuffer); 0398 } 0399 0400 // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T. 0401 char m_inlineBuffer[m_inlineBufferSize]; 0402 }; 0403 0404 template<typename T, size_t inlineCapacity = 0> 0405 class Vector 0406 { 0407 private: 0408 typedef VectorBuffer<T, inlineCapacity> Buffer; 0409 typedef VectorTypeOperations<T> TypeOperations; 0410 0411 public: 0412 typedef T ValueType; 0413 0414 typedef T *iterator; 0415 typedef const T *const_iterator; 0416 0417 Vector() 0418 : m_size(0) 0419 { 0420 } 0421 0422 explicit Vector(size_t size) 0423 : m_size(size) 0424 , m_buffer(size) 0425 { 0426 TypeOperations::initialize(begin(), end()); 0427 } 0428 0429 ~Vector() 0430 { 0431 clear(); 0432 } 0433 0434 Vector(const Vector &); 0435 template<size_t otherCapacity> 0436 Vector(const Vector<T, otherCapacity> &); 0437 0438 Vector &operator=(const Vector &); 0439 template<size_t otherCapacity> 0440 Vector &operator=(const Vector<T, otherCapacity> &); 0441 0442 size_t size() const 0443 { 0444 return m_size; 0445 } 0446 size_t capacity() const 0447 { 0448 return m_buffer.capacity(); 0449 } 0450 bool isEmpty() const 0451 { 0452 return !size(); 0453 } 0454 0455 T &at(size_t i) 0456 { 0457 ASSERT(i < size()); 0458 return m_buffer.buffer()[i]; 0459 } 0460 const T &at(size_t i) const 0461 { 0462 ASSERT(i < size()); 0463 return m_buffer.buffer()[i]; 0464 } 0465 0466 T &operator[](size_t i) 0467 { 0468 return at(i); 0469 } 0470 const T &operator[](size_t i) const 0471 { 0472 return at(i); 0473 } 0474 0475 T *data() 0476 { 0477 return m_buffer.buffer(); 0478 } 0479 const T *data() const 0480 { 0481 return m_buffer.buffer(); 0482 } 0483 0484 iterator begin() 0485 { 0486 return data(); 0487 } 0488 iterator end() 0489 { 0490 return begin() + m_size; 0491 } 0492 const_iterator begin() const 0493 { 0494 return data(); 0495 } 0496 const_iterator end() const 0497 { 0498 return begin() + m_size; 0499 } 0500 0501 T &first() 0502 { 0503 return at(0); 0504 } 0505 const T &first() const 0506 { 0507 return at(0); 0508 } 0509 T &last() 0510 { 0511 return at(size() - 1); 0512 } 0513 const T &last() const 0514 { 0515 return at(size() - 1); 0516 } 0517 0518 void shrink(size_t size); 0519 void grow(size_t size); 0520 void resize(size_t size); 0521 void reserveCapacity(size_t newCapacity); 0522 void shrinkCapacity(size_t newCapacity); 0523 0524 void clear() 0525 { 0526 if (m_size) { 0527 shrink(0); 0528 } 0529 } 0530 0531 template<typename U> void append(const U *, size_t); 0532 template<typename U> void append(const U &); 0533 template<typename U> void uncheckedAppend(const U &val); 0534 template<typename U, size_t c> void append(const Vector<U, c> &); 0535 0536 template<typename U> void insert(size_t position, const U *, size_t); 0537 template<typename U> void insert(size_t position, const U &); 0538 template<typename U, size_t c> void insert(size_t position, const Vector<U, c> &); 0539 0540 template<typename U> void prepend(const U *, size_t); 0541 template<typename U> void prepend(const U &); 0542 template<typename U, size_t c> void prepend(const Vector<U, c> &); 0543 0544 void remove(size_t position); 0545 void remove(size_t position, size_t length); 0546 0547 void removeLast() 0548 { 0549 ASSERT(!isEmpty()); 0550 shrink(size() - 1); 0551 } 0552 0553 Vector(size_t size, const T &val) 0554 : m_size(size) 0555 , m_buffer(size) 0556 { 0557 TypeOperations::uninitializedFill(begin(), end(), val); 0558 } 0559 0560 void fill(const T &, size_t); 0561 void fill(const T &val) 0562 { 0563 fill(val, size()); 0564 } 0565 0566 template<typename Iterator> void appendRange(Iterator start, Iterator end); 0567 0568 T *releaseBuffer(); 0569 0570 void swap(Vector<T, inlineCapacity> &other) 0571 { 0572 std::swap(m_size, other.m_size); 0573 m_buffer.swap(other.m_buffer); 0574 } 0575 0576 private: 0577 void expandCapacity(size_t newMinCapacity); 0578 const T *expandCapacity(size_t newMinCapacity, const T *); 0579 template<typename U> U *expandCapacity(size_t newMinCapacity, U *); 0580 0581 size_t m_size; 0582 Buffer m_buffer; 0583 }; 0584 0585 template<typename T, size_t inlineCapacity> 0586 Vector<T, inlineCapacity>::Vector(const Vector &other) 0587 : m_size(other.size()) 0588 , m_buffer(other.capacity()) 0589 { 0590 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); 0591 } 0592 0593 template<typename T, size_t inlineCapacity> 0594 template<size_t otherCapacity> 0595 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity> &other) 0596 : m_size(other.size()) 0597 , m_buffer(other.capacity()) 0598 { 0599 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); 0600 } 0601 0602 template<typename T, size_t inlineCapacity> 0603 Vector<T, inlineCapacity> &Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity> &other) 0604 { 0605 if (&other == this) { 0606 return *this; 0607 } 0608 0609 if (size() > other.size()) { 0610 shrink(other.size()); 0611 } else if (other.size() > capacity()) { 0612 clear(); 0613 reserveCapacity(other.size()); 0614 } 0615 0616 std::copy(other.begin(), other.begin() + size(), begin()); 0617 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); 0618 m_size = other.size(); 0619 0620 return *this; 0621 } 0622 0623 template<typename T, size_t inlineCapacity> 0624 template<size_t otherCapacity> 0625 Vector<T, inlineCapacity> &Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity> &other) 0626 { 0627 if (&other == this) { 0628 return *this; 0629 } 0630 0631 if (size() > other.size()) { 0632 shrink(other.size()); 0633 } else if (other.size() > capacity()) { 0634 clear(); 0635 reserveCapacity(other.size()); 0636 } 0637 0638 std::copy(other.begin(), other.begin() + size(), begin()); 0639 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); 0640 m_size = other.size(); 0641 0642 return *this; 0643 } 0644 0645 template<typename T, size_t inlineCapacity> 0646 void Vector<T, inlineCapacity>::fill(const T &val, size_t newSize) 0647 { 0648 if (size() > newSize) { 0649 shrink(newSize); 0650 } else if (newSize > capacity()) { 0651 clear(); 0652 reserveCapacity(newSize); 0653 } 0654 0655 std::fill(begin(), end(), val); 0656 TypeOperations::uninitializedFill(end(), begin() + newSize, val); 0657 m_size = newSize; 0658 } 0659 0660 template<typename T, size_t inlineCapacity> 0661 template<typename Iterator> 0662 void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end) 0663 { 0664 for (Iterator it = start; it != end; ++it) { 0665 append(*it); 0666 } 0667 } 0668 0669 template<typename T, size_t inlineCapacity> 0670 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity) 0671 { 0672 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); 0673 } 0674 0675 template<typename T, size_t inlineCapacity> 0676 const T *Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T *ptr) 0677 { 0678 if (ptr < begin() || ptr >= end()) { 0679 expandCapacity(newMinCapacity); 0680 return ptr; 0681 } 0682 size_t index = ptr - begin(); 0683 expandCapacity(newMinCapacity); 0684 return begin() + index; 0685 } 0686 0687 template<typename T, size_t inlineCapacity> template<typename U> 0688 inline U *Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U *ptr) 0689 { 0690 expandCapacity(newMinCapacity); 0691 return ptr; 0692 } 0693 0694 template<typename T, size_t inlineCapacity> 0695 void Vector<T, inlineCapacity>::resize(size_t size) 0696 { 0697 if (size <= m_size) { 0698 TypeOperations::destruct(begin() + size, end()); 0699 } else { 0700 if (size > capacity()) { 0701 expandCapacity(size); 0702 } 0703 if (begin()) { 0704 TypeOperations::initialize(end(), begin() + size); 0705 } 0706 } 0707 0708 m_size = size; 0709 } 0710 0711 template<typename T, size_t inlineCapacity> 0712 void Vector<T, inlineCapacity>::shrink(size_t size) 0713 { 0714 ASSERT(size <= m_size); 0715 TypeOperations::destruct(begin() + size, end()); 0716 m_size = size; 0717 } 0718 0719 template<typename T, size_t inlineCapacity> 0720 void Vector<T, inlineCapacity>::grow(size_t size) 0721 { 0722 ASSERT(size >= m_size); 0723 if (size > capacity()) { 0724 expandCapacity(size); 0725 } 0726 if (begin()) { 0727 TypeOperations::initialize(end(), begin() + size); 0728 } 0729 m_size = size; 0730 } 0731 0732 template<typename T, size_t inlineCapacity> 0733 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity) 0734 { 0735 if (newCapacity <= capacity()) { 0736 return; 0737 } 0738 T *oldBuffer = begin(); 0739 T *oldEnd = end(); 0740 m_buffer.allocateBuffer(newCapacity); 0741 if (begin()) { 0742 TypeOperations::move(oldBuffer, oldEnd, begin()); 0743 } 0744 m_buffer.deallocateBuffer(oldBuffer); 0745 } 0746 0747 template<typename T, size_t inlineCapacity> 0748 void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity) 0749 { 0750 if (newCapacity >= capacity()) { 0751 return; 0752 } 0753 0754 resize(min(m_size, newCapacity)); 0755 0756 T *oldBuffer = begin(); 0757 if (newCapacity > 0) { 0758 T *oldEnd = end(); 0759 m_buffer.allocateBuffer(newCapacity); 0760 if (begin() != oldBuffer) { 0761 TypeOperations::move(oldBuffer, oldEnd, begin()); 0762 } 0763 } 0764 0765 m_buffer.deallocateBuffer(oldBuffer); 0766 } 0767 0768 // Templatizing these is better than just letting the conversion happen implicitly, 0769 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector 0770 // without refcount thrash. 0771 0772 template<typename T, size_t inlineCapacity> template<typename U> 0773 void Vector<T, inlineCapacity>::append(const U *data, size_t dataSize) 0774 { 0775 size_t newSize = m_size + dataSize; 0776 if (newSize > capacity()) { 0777 data = expandCapacity(newSize, data); 0778 if (!begin()) { 0779 return; 0780 } 0781 } 0782 T *dest = end(); 0783 for (size_t i = 0; i < dataSize; ++i) { 0784 new(&dest[i]) T(data[i]); 0785 } 0786 m_size = newSize; 0787 } 0788 0789 template<typename T, size_t inlineCapacity> template<typename U> 0790 inline void Vector<T, inlineCapacity>::append(const U &val) 0791 { 0792 const U *ptr = &val; 0793 if (size() == capacity()) { 0794 ptr = expandCapacity(size() + 1, ptr); 0795 if (!begin()) { 0796 return; 0797 } 0798 } 0799 0800 #if defined(WTF_COMPILER_MSVC7) 0801 // FIXME: MSVC7 generates compilation errors when trying to assign 0802 // a pointer to a Vector of its base class (i.e. can't downcast). So far 0803 // I've been unable to determine any logical reason for this, so I can 0804 // only assume it is a bug with the compiler. Casting is a bad solution, 0805 // however, because it subverts implicit conversions, so a better 0806 // one is needed. 0807 new(end()) T(static_cast<T>(*ptr)); 0808 #else 0809 new(end()) T(*ptr); 0810 #endif 0811 ++m_size; 0812 } 0813 0814 // This version of append saves a branch in the case where you know that the 0815 // vector's capacity is large enough for the append to succeed. 0816 0817 template<typename T, size_t inlineCapacity> template<typename U> 0818 inline void Vector<T, inlineCapacity>::uncheckedAppend(const U &val) 0819 { 0820 ASSERT(size() < capacity()); 0821 const U *ptr = &val; 0822 new(end()) T(*ptr); 0823 ++m_size; 0824 } 0825 0826 template<typename T, size_t inlineCapacity> template<typename U, size_t c> 0827 inline void Vector<T, inlineCapacity>::append(const Vector<U, c> &val) 0828 { 0829 append(val.begin(), val.size()); 0830 } 0831 0832 template<typename T, size_t inlineCapacity> template<typename U> 0833 void Vector<T, inlineCapacity>::insert(size_t position, const U *data, size_t dataSize) 0834 { 0835 ASSERT(position <= size()); 0836 size_t newSize = m_size + dataSize; 0837 if (newSize > capacity()) { 0838 data = expandCapacity(newSize, data); 0839 if (!begin()) { 0840 return; 0841 } 0842 } 0843 T *spot = begin() + position; 0844 TypeOperations::moveOverlapping(spot, end(), spot + dataSize); 0845 for (size_t i = 0; i < dataSize; ++i) { 0846 new(&spot[i]) T(data[i]); 0847 } 0848 m_size = newSize; 0849 } 0850 0851 template<typename T, size_t inlineCapacity> template<typename U> 0852 inline void Vector<T, inlineCapacity>::insert(size_t position, const U &val) 0853 { 0854 ASSERT(position <= size()); 0855 const U *data = &val; 0856 if (size() == capacity()) { 0857 data = expandCapacity(size() + 1, data); 0858 if (!begin()) { 0859 return; 0860 } 0861 } 0862 T *spot = begin() + position; 0863 TypeOperations::moveOverlapping(spot, end(), spot + 1); 0864 new(spot) T(*data); 0865 ++m_size; 0866 } 0867 0868 template<typename T, size_t inlineCapacity> template<typename U, size_t c> 0869 inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c> &val) 0870 { 0871 insert(position, val.begin(), val.size()); 0872 } 0873 0874 template<typename T, size_t inlineCapacity> template<typename U> 0875 void Vector<T, inlineCapacity>::prepend(const U *data, size_t dataSize) 0876 { 0877 insert(0, data, dataSize); 0878 } 0879 0880 template<typename T, size_t inlineCapacity> template<typename U> 0881 inline void Vector<T, inlineCapacity>::prepend(const U &val) 0882 { 0883 insert(0, val); 0884 } 0885 0886 template<typename T, size_t inlineCapacity> template<typename U, size_t c> 0887 inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c> &val) 0888 { 0889 insert(0, val.begin(), val.size()); 0890 } 0891 0892 template<typename T, size_t inlineCapacity> 0893 inline void Vector<T, inlineCapacity>::remove(size_t position) 0894 { 0895 ASSERT(position < size()); 0896 T *spot = begin() + position; 0897 spot->~T(); 0898 TypeOperations::moveOverlapping(spot + 1, end(), spot); 0899 --m_size; 0900 } 0901 0902 template<typename T, size_t inlineCapacity> 0903 inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length) 0904 { 0905 ASSERT(position < size()); 0906 ASSERT(position + length < size()); 0907 T *beginSpot = begin() + position; 0908 T *endSpot = beginSpot + length; 0909 TypeOperations::destruct(beginSpot, endSpot); 0910 TypeOperations::moveOverlapping(endSpot, end(), beginSpot); 0911 m_size -= length; 0912 } 0913 0914 template<typename T, size_t inlineCapacity> 0915 inline T *Vector<T, inlineCapacity>::releaseBuffer() 0916 { 0917 T *buffer = m_buffer.releaseBuffer(); 0918 if (inlineCapacity && !buffer && m_size) { 0919 // If the vector had some data, but no buffer to release, 0920 // that means it was using the inline buffer. In that case, 0921 // we create a brand new buffer so the caller always gets one. 0922 size_t bytes = m_size * sizeof(T); 0923 buffer = static_cast<T *>(fastMalloc(bytes)); 0924 memcpy(buffer, data(), bytes); 0925 } 0926 ASSERT(buffer); 0927 m_size = 0; 0928 return buffer; 0929 } 0930 0931 template<typename T, size_t inlineCapacity> 0932 void deleteAllValues(const Vector<T, inlineCapacity> &collection) 0933 { 0934 typedef typename Vector<T, inlineCapacity>::const_iterator iterator; 0935 iterator end = collection.end(); 0936 for (iterator it = collection.begin(); it != end; ++it) { 0937 delete *it; 0938 } 0939 } 0940 0941 template<typename T, size_t inlineCapacity> 0942 inline void swap(Vector<T, inlineCapacity> &a, Vector<T, inlineCapacity> &b) 0943 { 0944 a.swap(b); 0945 } 0946 0947 template<typename T, size_t inlineCapacity> 0948 bool operator==(const Vector<T, inlineCapacity> &a, const Vector<T, inlineCapacity> &b) 0949 { 0950 if (a.size() != b.size()) { 0951 return false; 0952 } 0953 0954 return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); 0955 } 0956 0957 template<typename T, size_t inlineCapacity> 0958 inline bool operator!=(const Vector<T, inlineCapacity> &a, const Vector<T, inlineCapacity> &b) 0959 { 0960 return !(a == b); 0961 } 0962 0963 } // namespace WTF 0964 0965 using WTF::Vector; 0966 0967 #endif // WTF_Vector_h