1 // -*- mode: c++; c-basic-offset: 4 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 2005, 2006 Apple Computer, Inc.
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.
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.
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.
26 #include "Assertions.h"
27 #include "FastMalloc.h"
28 #include "VectorTraits.h"
38 template <bool needsDestruction, typename T>
39 class VectorDestructor;
42 struct VectorDestructor<false, T>
44 static void destruct(T*, T*) {}
48 struct VectorDestructor<true, T>
50 static void destruct(T* begin, T* end)
52 for (T* cur = begin; cur != end; ++cur)
57 template <bool needsInitialization, bool canInitializeWithMemset, typename T>
58 class VectorInitializer;
60 template<bool ignore, typename T>
61 struct VectorInitializer<false, ignore, T>
63 static void initialize(T*, T*) {}
67 struct VectorInitializer<true, false, T>
69 static void initialize(T* begin, T* end)
71 for (T* cur = begin; cur != end; ++cur)
77 struct VectorInitializer<true, true, T>
79 static void initialize(T* begin, T* end)
81 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
85 template <bool canMoveWithMemcpy, typename T>
89 struct VectorMover<false, T>
91 static void move(const T* src, const T* srcEnd, T* dst)
93 while (src != srcEnd) {
100 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
103 move(src, srcEnd, dst);
105 T* dstEnd = dst + (srcEnd - src);
106 while (src != srcEnd) {
109 new (dstEnd) T(*srcEnd);
117 struct VectorMover<true, T>
119 static void move(const T* src, const T* srcEnd, T* dst)
121 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
123 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
125 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
129 template <bool canCopyWithMemcpy, typename T>
133 struct VectorCopier<false, T>
135 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
137 while (src != srcEnd) {
146 struct VectorCopier<true, T>
148 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
150 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
154 template <bool canFillWithMemset, typename T>
158 struct VectorFiller<false, T>
160 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
162 while (dst != dstEnd) {
170 struct VectorFiller<true, T>
172 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
174 ASSERT(sizeof(T) == sizeof(char));
175 memset(dst, val, dstEnd - dst);
180 struct VectorTypeOperations
182 static void destruct(T* begin, T* end)
184 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
187 static void initialize(T* begin, T* end)
189 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
192 static void move(const T* src, const T* srcEnd, T* dst)
194 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
197 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
199 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
202 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
204 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
207 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
209 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
213 template<typename T, size_t inlineCapacity>
217 class VectorBuffer<T, 0> {
220 : m_buffer(0), m_capacity(0)
224 VectorBuffer(size_t capacity)
229 allocateBuffer(capacity);
234 deallocateBuffer(m_buffer);
237 static void deallocateBuffer(T* buffer)
242 void allocateBuffer(size_t newCapacity)
244 ASSERT(newCapacity >= m_capacity);
245 m_capacity = newCapacity;
246 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
248 m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
251 T* buffer() { return m_buffer; }
252 const T* buffer() const { return m_buffer; }
253 size_t capacity() const { return m_capacity; }
255 void swap(VectorBuffer<T, 0>& other)
257 std::swap(m_capacity, other.m_capacity);
258 std::swap(m_buffer, other.m_buffer);
263 T* buffer = m_buffer;
270 VectorBuffer(T* buffer, size_t capacity)
271 : m_buffer(buffer), m_capacity(capacity)
281 template<typename T, size_t inlineCapacity>
282 class VectorBuffer : private VectorBuffer<T, 0> {
284 typedef VectorBuffer<T, 0> BaseBuffer;
287 : BaseBuffer(inlineBuffer(), inlineCapacity)
291 VectorBuffer(size_t capacity)
292 : BaseBuffer(inlineBuffer(), inlineCapacity)
294 if (capacity > inlineCapacity)
295 allocateBuffer(capacity);
300 if (buffer() == inlineBuffer())
301 BaseBuffer::m_buffer = 0;
304 void deallocateBuffer(T* buffer)
306 if (buffer != inlineBuffer())
307 BaseBuffer::deallocateBuffer(buffer);
310 using BaseBuffer::allocateBuffer;
312 using BaseBuffer::buffer;
313 using BaseBuffer::capacity;
317 if (buffer() == inlineBuffer())
319 return BaseBuffer::releaseBuffer();
322 void swap(VectorBuffer<T, inlineCapacity>&);
325 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
326 T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
328 // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T.
329 char m_inlineBuffer[m_inlineBufferSize];
332 template<typename T, size_t inlineCapacity = 0>
335 typedef VectorBuffer<T, inlineCapacity> Impl;
336 typedef VectorTypeOperations<T> TypeOperations;
340 typedef const T* const_iterator;
347 explicit Vector(size_t size)
358 Vector(const Vector&);
359 template<size_t otherCapacity>
360 Vector(const Vector<T, otherCapacity>&);
362 Vector& operator=(const Vector&);
363 template<size_t otherCapacity>
364 Vector& operator=(const Vector<T, otherCapacity>&);
366 size_t size() const { return m_size; }
367 size_t capacity() const { return m_impl.capacity(); }
368 bool isEmpty() const { return !size(); }
373 return m_impl.buffer()[i];
375 const T& at(size_t i) const
378 return m_impl.buffer()[i];
381 T& operator[](long i) { return at(i); }
382 const T& operator[](long i) const { return at(i); }
383 T& operator[](unsigned long i) { return at(i); }
384 const T& operator[](unsigned long i) const { return at(i); }
385 T& operator[](int i) { return at(i); }
386 const T& operator[](int i) const { return at(i); }
387 T& operator[](unsigned i) { return at(i); }
388 const T& operator[](unsigned i) const { return at(i); }
389 T& operator[](short i) { return at(i); }
390 const T& operator[](short i) const { return at(i); }
391 T& operator[](unsigned short i) { return at(i); }
392 const T& operator[](unsigned short i) const { return at(i); }
394 T* data() { return m_impl.buffer(); }
395 const T* data() const { return m_impl.buffer(); }
396 operator T*() { return data(); }
397 operator const T*() const { return data(); }
399 iterator begin() { return data(); }
400 iterator end() { return begin() + m_size; }
401 const_iterator begin() const { return data(); }
402 const_iterator end() const { return begin() + m_size; }
404 T& first() { return at(0); }
405 const T& first() const { return at(0); }
406 T& last() { return at(size() - 1); }
407 const T& last() const { return at(size() - 1); }
409 void resize(size_t size);
410 void reserveCapacity(size_t newCapacity);
412 void clear() { resize(0); }
414 template<typename U> void append(const U*, size_t);
415 template<typename U> void append(const U&);
416 template<typename U, size_t c> void append(const Vector<U, c>&);
418 template<typename U> void insert(size_t position, const U&);
420 void remove(size_t position);
428 Vector(size_t size, const T& val)
432 TypeOperations::uninitializedFill(begin(), end(), val);
435 void fill(const T&, size_t);
436 void fill(const T& val) { fill(val, size()); }
440 void swap(Vector<T, inlineCapacity>& other)
442 std::swap(m_size, other.m_size);
443 m_impl.swap(other.m_impl);
447 void expandCapacity(size_t newMinCapacity);
448 const T* expandCapacity(size_t newMinCapacity, const T*);
449 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
455 template<typename T, size_t inlineCapacity>
456 Vector<T, inlineCapacity>::Vector(const Vector& other)
457 : m_size(other.size())
458 , m_impl(other.capacity())
460 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
463 template<typename T, size_t inlineCapacity>
464 template<size_t otherCapacity>
465 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
466 : m_size(other.size())
467 , m_impl(other.capacity())
469 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
472 template<typename T, size_t inlineCapacity>
473 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
478 if (size() > other.size())
479 resize(other.size());
480 else if (other.size() > capacity()) {
482 reserveCapacity(other.size());
485 std::copy(other.begin(), other.begin() + size(), begin());
486 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
487 m_size = other.size();
492 template<typename T, size_t inlineCapacity>
493 template<size_t otherCapacity>
494 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
499 if (size() > other.size())
500 resize(other.size());
501 else if (other.size() > capacity()) {
503 reserveCapacity(other.size());
506 std::copy(other.begin(), other.begin() + size(), begin());
507 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
508 m_size = other.size();
513 template<typename T, size_t inlineCapacity>
514 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
516 if (size() > newSize)
518 else if (newSize > capacity()) {
520 reserveCapacity(newSize);
523 std::fill(begin(), end(), val);
524 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
528 template<typename T, size_t inlineCapacity>
529 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
531 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
534 template<typename T, size_t inlineCapacity>
535 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
537 if (ptr < begin() || ptr >= end()) {
538 expandCapacity(newMinCapacity);
541 size_t index = ptr - begin();
542 expandCapacity(newMinCapacity);
543 return begin() + index;
546 template<typename T, size_t inlineCapacity> template<typename U>
547 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
549 expandCapacity(newMinCapacity);
553 template<typename T, size_t inlineCapacity>
554 void Vector<T, inlineCapacity>::resize(size_t size)
557 TypeOperations::destruct(begin() + size, end());
559 if (size > capacity())
560 expandCapacity(size);
561 TypeOperations::initialize(end(), begin() + size);
567 template<typename T, size_t inlineCapacity>
568 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
570 if (newCapacity < capacity())
572 T* oldBuffer = begin();
574 m_impl.allocateBuffer(newCapacity);
575 TypeOperations::move(oldBuffer, oldEnd, begin());
576 m_impl.deallocateBuffer(oldBuffer);
579 // Templatizing these is better than just letting the conversion happen implicitly,
580 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
581 // without refcount thrash.
583 template<typename T, size_t inlineCapacity> template<typename U>
584 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
586 size_t newSize = m_size + dataSize;
587 if (newSize > capacity())
588 data = expandCapacity(newSize, data);
590 for (size_t i = 0; i < dataSize; ++i)
591 new (&dest[i]) T(data[i]);
595 template<typename T, size_t inlineCapacity> template<typename U>
596 inline void Vector<T, inlineCapacity>::append(const U& val)
599 if (size() == capacity())
600 ptr = expandCapacity(size() + 1, ptr);
605 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
606 inline void Vector<T, inlineCapacity>::append(const Vector<U, c>& val)
608 append(val.begin(), val.size());
611 template<typename T, size_t inlineCapacity> template<typename U>
612 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
614 ASSERT(position <= size());
616 if (size() == capacity())
617 ptr = expandCapacity(size() + 1, ptr);
618 T* spot = begin() + position;
619 TypeOperations::moveOverlapping(spot, end(), spot + 1);
624 template<typename T, size_t inlineCapacity>
625 inline void Vector<T, inlineCapacity>::remove(size_t position)
627 ASSERT(position < size());
628 T* spot = begin() + position;
630 TypeOperations::moveOverlapping(spot + 1, end(), spot);
634 template<typename T, size_t inlineCapacity>
635 T* Vector<T, inlineCapacity>::releaseBuffer()
637 T* buffer = m_impl.releaseBuffer();
638 if (!buffer && m_size) {
639 // If the vector had some data, but no buffer to release,
640 // that means it was using the inline buffer. In that case,
641 // we create a brand new buffer so the caller always gets one.
642 size_t bytes = m_size * sizeof(T);
643 buffer = static_cast<T*>(fastMalloc(bytes));
644 memcpy(buffer, data(), bytes);
650 template<typename T, size_t inlineCapacity>
651 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
653 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
654 iterator end = collection.end();
655 for (iterator it = collection.begin(); it != end; ++it)
659 template<typename T, size_t inlineCapacity>
660 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
669 #endif // WTF_Vector_h