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"
33 // FIXME: For unknown reasons defining NOMINMAX is not preventing the
34 // min and max macros from being defined on Win32.
48 template <bool needsDestruction, typename T>
49 class VectorDestructor;
52 struct VectorDestructor<false, T>
54 static void destruct(T*, T*) {}
58 struct VectorDestructor<true, T>
60 static void destruct(T* begin, T* end)
62 for (T* cur = begin; cur != end; ++cur)
67 template <bool needsInitialization, bool canInitializeWithMemset, typename T>
68 class VectorInitializer;
70 template<bool ignore, typename T>
71 struct VectorInitializer<false, ignore, T>
73 static void initialize(T*, T*) {}
77 struct VectorInitializer<true, false, T>
79 static void initialize(T* begin, T* end)
81 for (T* cur = begin; cur != end; ++cur)
87 struct VectorInitializer<true, true, T>
89 static void initialize(T* begin, T* end)
91 memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
95 template <bool canMoveWithMemcpy, typename T>
99 struct VectorMover<false, T>
101 static void move(const T* src, const T* srcEnd, T* dst)
103 while (src != srcEnd) {
110 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
113 move(src, srcEnd, dst);
115 T* dstEnd = dst + (srcEnd - src);
116 while (src != srcEnd) {
119 new (dstEnd) T(*srcEnd);
127 struct VectorMover<true, T>
129 static void move(const T* src, const T* srcEnd, T* dst)
131 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
133 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
135 memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
139 template <bool canCopyWithMemcpy, typename T>
143 struct VectorCopier<false, T>
145 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
147 while (src != srcEnd) {
156 struct VectorCopier<true, T>
158 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
160 memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
164 template <bool canFillWithMemset, typename T>
168 struct VectorFiller<false, T>
170 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
172 while (dst != dstEnd) {
180 struct VectorFiller<true, T>
182 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
184 ASSERT(sizeof(T) == sizeof(char));
185 memset(dst, val, dstEnd - dst);
190 struct VectorTypeOperations
192 static void destruct(T* begin, T* end)
194 VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
197 static void initialize(T* begin, T* end)
199 VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
202 static void move(const T* src, const T* srcEnd, T* dst)
204 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
207 static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
209 VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
212 static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
214 VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
217 static void uninitializedFill(T* dst, T* dstEnd, const T& val)
219 VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
223 template<typename T, size_t inlineCapacity>
227 class VectorBuffer<T, 0> {
230 : m_buffer(0), m_capacity(0)
234 VectorBuffer(size_t capacity)
239 allocateBuffer(capacity);
244 deallocateBuffer(m_buffer);
247 static void deallocateBuffer(T* buffer)
252 void allocateBuffer(size_t newCapacity)
254 ASSERT(newCapacity >= m_capacity);
255 m_capacity = newCapacity;
256 if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
258 m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
261 T* buffer() { return m_buffer; }
262 const T* buffer() const { return m_buffer; }
263 size_t capacity() const { return m_capacity; }
265 void swap(VectorBuffer<T, 0>& other)
267 std::swap(m_capacity, other.m_capacity);
268 std::swap(m_buffer, other.m_buffer);
273 T* buffer = m_buffer;
280 VectorBuffer(T* buffer, size_t capacity)
281 : m_buffer(buffer), m_capacity(capacity)
291 template<typename T, size_t inlineCapacity>
292 class VectorBuffer : private VectorBuffer<T, 0> {
294 typedef VectorBuffer<T, 0> BaseBuffer;
297 : BaseBuffer(inlineBuffer(), inlineCapacity)
301 VectorBuffer(size_t capacity)
302 : BaseBuffer(inlineBuffer(), inlineCapacity)
304 if (capacity > inlineCapacity)
305 allocateBuffer(capacity);
310 if (buffer() == inlineBuffer())
311 BaseBuffer::m_buffer = 0;
314 void deallocateBuffer(T* buffer)
316 if (buffer != inlineBuffer())
317 BaseBuffer::deallocateBuffer(buffer);
320 using BaseBuffer::allocateBuffer;
322 using BaseBuffer::buffer;
323 using BaseBuffer::capacity;
327 if (buffer() == inlineBuffer())
329 return BaseBuffer::releaseBuffer();
332 void swap(VectorBuffer<T, inlineCapacity>&);
335 static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
336 T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
338 // FIXME: Nothing guarantees this buffer is appropriately aligned to hold objects of type T.
339 char m_inlineBuffer[m_inlineBufferSize];
342 template<typename T, size_t inlineCapacity = 0>
345 typedef VectorBuffer<T, inlineCapacity> Impl;
346 typedef VectorTypeOperations<T> TypeOperations;
350 typedef const T* const_iterator;
357 explicit Vector(size_t size)
368 Vector(const Vector&);
369 template<size_t otherCapacity>
370 Vector(const Vector<T, otherCapacity>&);
372 Vector& operator=(const Vector&);
373 template<size_t otherCapacity>
374 Vector& operator=(const Vector<T, otherCapacity>&);
376 size_t size() const { return m_size; }
377 size_t capacity() const { return m_impl.capacity(); }
378 bool isEmpty() const { return !size(); }
383 return m_impl.buffer()[i];
385 const T& at(size_t i) const
388 return m_impl.buffer()[i];
391 T& operator[](long i) { return at(i); }
392 const T& operator[](long i) const { return at(i); }
393 T& operator[](unsigned long i) { return at(i); }
394 const T& operator[](unsigned long i) const { return at(i); }
395 T& operator[](int i) { return at(i); }
396 const T& operator[](int i) const { return at(i); }
397 T& operator[](unsigned i) { return at(i); }
398 const T& operator[](unsigned i) const { return at(i); }
399 T& operator[](short i) { return at(i); }
400 const T& operator[](short i) const { return at(i); }
401 T& operator[](unsigned short i) { return at(i); }
402 const T& operator[](unsigned short i) const { return at(i); }
404 T* data() { return m_impl.buffer(); }
405 const T* data() const { return m_impl.buffer(); }
406 operator T*() { return data(); }
407 operator const T*() const { return data(); }
409 iterator begin() { return data(); }
410 iterator end() { return begin() + m_size; }
411 const_iterator begin() const { return data(); }
412 const_iterator end() const { return begin() + m_size; }
414 T& first() { return at(0); }
415 const T& first() const { return at(0); }
416 T& last() { return at(size() - 1); }
417 const T& last() const { return at(size() - 1); }
419 void resize(size_t size);
420 void reserveCapacity(size_t newCapacity);
422 void clear() { resize(0); }
424 template<typename U> void append(const U*, size_t);
425 template<typename U> void append(const U&);
426 template<typename U, size_t c> void append(const Vector<U, c>&);
428 template<typename U> void insert(size_t position, const U&);
430 void remove(size_t position);
438 Vector(size_t size, const T& val)
442 TypeOperations::uninitializedFill(begin(), end(), val);
445 void fill(const T&, size_t);
446 void fill(const T& val) { fill(val, size()); }
450 void swap(Vector<T, inlineCapacity>& other)
452 std::swap(m_size, other.m_size);
453 m_impl.swap(other.m_impl);
457 void expandCapacity(size_t newMinCapacity);
458 const T* expandCapacity(size_t newMinCapacity, const T*);
459 template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
465 template<typename T, size_t inlineCapacity>
466 Vector<T, inlineCapacity>::Vector(const Vector& other)
467 : m_size(other.size())
468 , m_impl(other.capacity())
470 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
473 template<typename T, size_t inlineCapacity>
474 template<size_t otherCapacity>
475 Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
476 : m_size(other.size())
477 , m_impl(other.capacity())
479 TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
482 template<typename T, size_t inlineCapacity>
483 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
488 if (size() > other.size())
489 resize(other.size());
490 else if (other.size() > capacity()) {
492 reserveCapacity(other.size());
495 std::copy(other.begin(), other.begin() + size(), begin());
496 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
497 m_size = other.size();
502 template<typename T, size_t inlineCapacity>
503 template<size_t otherCapacity>
504 Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
509 if (size() > other.size())
510 resize(other.size());
511 else if (other.size() > capacity()) {
513 reserveCapacity(other.size());
516 std::copy(other.begin(), other.begin() + size(), begin());
517 TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
518 m_size = other.size();
523 template<typename T, size_t inlineCapacity>
524 void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
526 if (size() > newSize)
528 else if (newSize > capacity()) {
530 reserveCapacity(newSize);
533 std::fill(begin(), end(), val);
534 TypeOperations::uninitializedFill(end(), begin() + newSize, val);
538 template<typename T, size_t inlineCapacity>
539 void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
541 reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
544 template<typename T, size_t inlineCapacity>
545 const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
547 if (ptr < begin() || ptr >= end()) {
548 expandCapacity(newMinCapacity);
551 size_t index = ptr - begin();
552 expandCapacity(newMinCapacity);
553 return begin() + index;
556 template<typename T, size_t inlineCapacity> template<typename U>
557 inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
559 expandCapacity(newMinCapacity);
563 template<typename T, size_t inlineCapacity>
564 void Vector<T, inlineCapacity>::resize(size_t size)
567 TypeOperations::destruct(begin() + size, end());
569 if (size > capacity())
570 expandCapacity(size);
571 TypeOperations::initialize(end(), begin() + size);
577 template<typename T, size_t inlineCapacity>
578 void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
580 if (newCapacity < capacity())
582 T* oldBuffer = begin();
584 m_impl.allocateBuffer(newCapacity);
585 TypeOperations::move(oldBuffer, oldEnd, begin());
586 m_impl.deallocateBuffer(oldBuffer);
589 // Templatizing these is better than just letting the conversion happen implicitly,
590 // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
591 // without refcount thrash.
593 template<typename T, size_t inlineCapacity> template<typename U>
594 void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize)
596 size_t newSize = m_size + dataSize;
597 if (newSize > capacity())
598 data = expandCapacity(newSize, data);
600 for (size_t i = 0; i < dataSize; ++i)
601 new (&dest[i]) T(data[i]);
605 template<typename T, size_t inlineCapacity> template<typename U>
606 inline void Vector<T, inlineCapacity>::append(const U& val)
609 if (size() == capacity())
610 ptr = expandCapacity(size() + 1, ptr);
615 template<typename T, size_t inlineCapacity> template<typename U, size_t c>
616 inline void Vector<T, inlineCapacity>::append(const Vector<U, c>& val)
618 append(val.begin(), val.size());
621 template<typename T, size_t inlineCapacity> template<typename U>
622 inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
624 ASSERT(position <= size());
626 if (size() == capacity())
627 ptr = expandCapacity(size() + 1, ptr);
628 T* spot = begin() + position;
629 TypeOperations::moveOverlapping(spot, end(), spot + 1);
634 template<typename T, size_t inlineCapacity>
635 inline void Vector<T, inlineCapacity>::remove(size_t position)
637 ASSERT(position < size());
638 T* spot = begin() + position;
640 TypeOperations::moveOverlapping(spot + 1, end(), spot);
644 template<typename T, size_t inlineCapacity>
645 T* Vector<T, inlineCapacity>::releaseBuffer()
647 T* buffer = m_impl.releaseBuffer();
648 if (!buffer && m_size) {
649 // If the vector had some data, but no buffer to release,
650 // that means it was using the inline buffer. In that case,
651 // we create a brand new buffer so the caller always gets one.
652 size_t bytes = m_size * sizeof(T);
653 buffer = static_cast<T*>(fastMalloc(bytes));
654 memcpy(buffer, data(), bytes);
660 template<typename T, size_t inlineCapacity>
661 void deleteAllValues(const Vector<T, inlineCapacity>& collection)
663 typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
664 iterator end = collection.end();
665 for (iterator it = collection.begin(); it != end; ++it)
669 template<typename T, size_t inlineCapacity>
670 inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
679 #endif // WTF_Vector_h