• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

WTF

Vector.h

Go to the documentation of this file.
00001 // -*- mode: c++; c-basic-offset: 4 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2005, 2006 Apple Computer, Inc.
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public License
00017  *  along with this library; see the file COPYING.LIB.  If not, write to
00018  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifndef WTF_Vector_h
00024 #define WTF_Vector_h
00025 
00026 #include "Assertions.h"
00027 #include "FastMalloc.h"
00028 #include "VectorTraits.h"
00029 #include <limits>
00030 #include <stdlib.h>
00031 #include <cstring>
00032 #include <utility>
00033 
00034 // Temporary workaround for Win32.
00035 // We should use NOMINMAX instead.
00036 #undef max
00037 
00038 namespace WTF {
00039 
00040     using std::min;
00041     using std::max;
00042     
00043     template <bool needsDestruction, typename T>
00044     struct VectorDestructor;
00045 
00046     template<typename T>
00047     struct VectorDestructor<false, T>
00048     {
00049         static void destruct(T*, T*) {}
00050     };
00051 
00052     template<typename T>
00053     struct VectorDestructor<true, T>
00054     {
00055         static void destruct(T* begin, T* end) 
00056         {
00057             for (T* cur = begin; cur != end; ++cur)
00058                 cur->~T();
00059         }
00060     };
00061 
00062     template <bool needsInitialization, bool canInitializeWithMemset, typename T>
00063     struct VectorInitializer;
00064 
00065     template<bool ignore, typename T>
00066     struct VectorInitializer<false, ignore, T>
00067     {
00068         static void initialize(T*, T*) {}
00069     };
00070 
00071     template<typename T>
00072     struct VectorInitializer<true, false, T>
00073     {
00074         static void initialize(T* begin, T* end) 
00075         {
00076             for (T* cur = begin; cur != end; ++cur)
00077                 new (cur) T;
00078         }
00079     };
00080 
00081     template<typename T>
00082     struct VectorInitializer<true, true, T>
00083     {
00084         static void initialize(T* begin, T* end) 
00085         {
00086             std::memset(begin, 0, reinterpret_cast<char *>(end) - reinterpret_cast<char *>(begin));
00087         }
00088     };
00089 
00090     template <bool canMoveWithMemcpy, typename T>
00091     struct VectorMover;
00092 
00093     template<typename T>
00094     struct VectorMover<false, T>
00095     {
00096         static void move(const T* src, const T* srcEnd, T* dst)
00097         {
00098             while (src != srcEnd) {
00099                 new (dst) T(*src);
00100                 src->~T();
00101                 ++dst;
00102                 ++src;
00103             }
00104         }
00105         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
00106         {
00107             if (src > dst)
00108                 move(src, srcEnd, dst);
00109             else {
00110                 T* dstEnd = dst + (srcEnd - src);
00111                 while (src != srcEnd) {
00112                     --srcEnd;
00113                     --dstEnd;
00114                     new (dstEnd) T(*srcEnd);
00115                     srcEnd->~T();
00116                 }
00117             }
00118         }
00119     };
00120 
00121     template<typename T>
00122     struct VectorMover<true, T>
00123     {
00124         static void move(const T* src, const T* srcEnd, T* dst) 
00125         {
00126             std::memcpy(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src));
00127         }
00128         static void moveOverlapping(const T* src, const T* srcEnd, T* dst) 
00129         {
00130             std::memmove(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src));
00131         }
00132     };
00133 
00134     template <bool canCopyWithMemcpy, typename T>
00135     struct VectorCopier;
00136 
00137     template<typename T>
00138     struct VectorCopier<false, T>
00139     {
00140         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
00141         {
00142             while (src != srcEnd) {
00143                 new (dst) T(*src);
00144                 ++dst;
00145                 ++src;
00146             }
00147         }
00148     };
00149 
00150     template<typename T>
00151     struct VectorCopier<true, T>
00152     {
00153         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) 
00154         {
00155             std::memcpy(dst, src, reinterpret_cast<const char *>(srcEnd) - reinterpret_cast<const char *>(src));
00156         }
00157     };
00158 
00159     template <bool canFillWithMemset, typename T>
00160     struct VectorFiller;
00161 
00162     template<typename T>
00163     struct VectorFiller<false, T>
00164     {
00165         static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
00166         {
00167             while (dst != dstEnd) {
00168                 new (dst) T(val);
00169                 ++dst;
00170             }
00171         }
00172     };
00173 
00174     template<typename T>
00175     struct VectorFiller<true, T>
00176     {
00177         static void uninitializedFill(T* dst, T* dstEnd, const T& val) 
00178         {
00179             ASSERT(sizeof(T) == sizeof(char));
00180             std::memset(dst, val, dstEnd - dst);
00181         }
00182     };
00183     
00184     template<typename T>
00185     struct VectorTypeOperations
00186     {
00187         static void destruct(T* begin, T* end)
00188         {
00189             VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
00190         }
00191 
00192         static void initialize(T* begin, T* end)
00193         {
00194             VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
00195         }
00196 
00197         static void move(const T* src, const T* srcEnd, T* dst)
00198         {
00199             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
00200         }
00201 
00202         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
00203         {
00204             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
00205         }
00206 
00207         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
00208         {
00209             VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
00210         }
00211 
00212         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
00213         {
00214             VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
00215         }
00216     };
00217 
00218     template<typename T, size_t inlineCapacity>
00219     class VectorBuffer;
00220 
00221     template<typename T>
00222     class VectorBuffer<T, 0> 
00223     {
00224     public:
00225         VectorBuffer()
00226             : m_capacity(0)
00227             , m_buffer(0)
00228         {
00229         }
00230         
00231         VectorBuffer(size_t capacity)
00232             : m_capacity(0)
00233         {
00234             allocateBuffer(capacity);
00235         }
00236 
00237         ~VectorBuffer()
00238         {
00239             deallocateBuffer(m_buffer);
00240         }
00241 
00242         void swap(VectorBuffer<T, 0>& other)
00243         {
00244             std::swap(m_buffer, other.m_buffer);
00245             std::swap(m_capacity, other.m_capacity);
00246         }
00247         
00248         void deallocateBuffer(T* buffer)
00249         {
00250             fastFree(buffer);
00251         }
00252         
00253         void allocateBuffer(size_t newCapacity)
00254         {
00255             ASSERT(newCapacity >= m_capacity);
00256             m_capacity = newCapacity;
00257             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
00258                 abort();
00259             m_buffer = reinterpret_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
00260         }
00261 
00262         T* buffer() { return m_buffer; }
00263         const T* buffer() const { return m_buffer; }
00264         size_t capacity() const { return m_capacity; }
00265 
00266     protected:
00267         VectorBuffer(T* buffer, size_t capacity)
00268             : m_capacity(capacity)
00269             , m_buffer(buffer)
00270         {
00271         }
00272 
00273         size_t m_capacity;
00274         T *m_buffer;
00275     };
00276 
00277     template<typename T, size_t inlineCapacity>
00278     class VectorBuffer : public VectorBuffer<T, 0> {
00279     private:
00280         typedef VectorBuffer<T, 0> BaseBuffer;
00281     public:
00282         VectorBuffer() 
00283             : BaseBuffer(inlineBuffer(), inlineCapacity)
00284         {
00285         }
00286 
00287         VectorBuffer(size_t capacity)
00288             : BaseBuffer(inlineBuffer(), inlineCapacity)
00289         {
00290             if (capacity > inlineCapacity)
00291                 BaseBuffer::allocateBuffer(capacity);
00292         }
00293 
00294         ~VectorBuffer()
00295         {
00296             if (BaseBuffer::buffer() == inlineBuffer())
00297                 BaseBuffer::m_buffer = 0;
00298         }
00299 
00300         void deallocateBuffer(T* buffer)
00301         {
00302             if (buffer != inlineBuffer())
00303                 BaseBuffer::deallocateBuffer(buffer);
00304         }
00305 
00306     private:
00307         static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
00308         T *inlineBuffer() { return reinterpret_cast<T *>(&m_inlineBuffer); }
00309         char m_inlineBuffer[m_inlineBufferSize];
00310     };
00311 
00312     template<typename T, size_t inlineCapacity = 0>
00313     class Vector {
00314     private:
00315         typedef VectorBuffer<T, inlineCapacity> Impl;
00316         typedef VectorTypeOperations<T> TypeOperations;
00317 
00318     public:
00319         typedef T* iterator;
00320         typedef const T* const_iterator;
00321 
00322         Vector() 
00323             : m_size(0)
00324         {
00325         }
00326         
00327         explicit Vector(size_t size) 
00328             : m_size(0)
00329         {
00330             resize(size);
00331         }
00332 
00333         ~Vector()
00334         {
00335             clear();
00336         }
00337 
00338         Vector(const Vector&);
00339         template<size_t otherCapacity> 
00340         Vector(const Vector<T, otherCapacity>&);
00341 
00342         Vector& operator=(const Vector&);
00343         template<size_t otherCapacity> 
00344         Vector& operator=(const Vector<T, otherCapacity>&);
00345 
00346         size_t size() const { return m_size; }
00347         size_t capacity() const { return m_impl.capacity(); }
00348         bool isEmpty() const { return !size(); }
00349 
00350         T& at(size_t i) 
00351         { 
00352             ASSERT(i < size());
00353             return m_impl.buffer()[i]; 
00354         }
00355         const T& at(size_t i) const 
00356         {
00357             ASSERT(i < size());
00358             return m_impl.buffer()[i]; 
00359         }
00360 
00361         T& operator[](long i) { return at(i); }
00362         const T& operator[](long i) const { return at(i); }
00363         T& operator[](unsigned long i) { return at(i); }
00364         const T& operator[](unsigned long i) const { return at(i); }
00365         T& operator[](int i) { return at(i); }
00366         const T& operator[](int i) const { return at(i); }
00367         T& operator[](unsigned i) { return at(i); }
00368         const T& operator[](unsigned i) const { return at(i); }
00369         T& operator[](short i) { return at(i); }
00370         const T& operator[](short i) const { return at(i); }
00371         T& operator[](unsigned short i) { return at(i); }
00372         const T& operator[](unsigned short i) const { return at(i); }
00373 
00374         T* data() { return m_impl.buffer(); }
00375         const T* data() const { return m_impl.buffer(); }
00376         operator T*() { return data(); }
00377         operator const T*() const { return data(); }
00378 
00379         iterator begin() { return data(); }
00380         iterator end() { return begin() + m_size; }
00381         const_iterator begin() const { return data(); }
00382         const_iterator end() const { return begin() + m_size; }
00383         
00384         T& first() { return at(0); }
00385         const T& first() const { return at(0); }
00386         T& last() { return at(size() - 1); }
00387         const T& last() const { return at(size() - 1); }
00388 
00389         void resize(size_t size);
00390         void reserveCapacity(size_t newCapacity);
00391 
00392         void clear() { resize(0); }
00393 
00394         template<typename U> void append(const U&);
00395         template<typename U> void append(const Vector<U>&);
00396         template<typename U> void insert(size_t position, const U&);
00397         void remove(size_t position);
00398 
00399         void removeLast() 
00400         {
00401             ASSERT(!isEmpty());
00402             resize(size() - 1); 
00403         }
00404 
00405         Vector(size_t size, const T& val)
00406             : m_size(size)
00407             , m_impl(size)
00408         {
00409             TypeOperations::uninitializedFill(begin(), end(), val);
00410         }
00411 
00412         void fill(const T& val, size_t size);
00413         void fill(const T& val) { fill(val, size()); }
00414 
00415         void swap(Vector<T, inlineCapacity>& other)
00416         {
00417             std::swap(m_size, other.m_size);
00418             m_impl.swap(other.m_impl);
00419         }
00420 
00421     private:
00422         void expandCapacity(size_t newMinCapacity);
00423         const T* expandCapacity(size_t newMinCapacity, const T*);
00424         template<typename U> U* expandCapacity(size_t newMinCapacity, U*); 
00425 
00426         size_t m_size;
00427         Impl m_impl;
00428     };
00429 
00430     template<typename T, size_t inlineCapacity>
00431     Vector<T, inlineCapacity>::Vector(const Vector& other)
00432         : m_size(other.size())
00433         , m_impl(other.capacity())
00434     {
00435         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
00436     }
00437 
00438     template<typename T, size_t inlineCapacity>
00439     template<size_t otherCapacity> 
00440     Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other)
00441         : m_size(other.size())
00442         , m_impl(other.capacity())
00443     {
00444         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
00445     }
00446 
00447     template<typename T, size_t inlineCapacity>
00448     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other)
00449     {
00450         if (&other == this)
00451             return *this;
00452         
00453         if (size() > other.size())
00454             resize(other.size());
00455         else if (other.size() > capacity()) {
00456             clear();
00457             reserveCapacity(other.size());
00458         }
00459         
00460         std::copy(other.begin(), other.begin() + size(), begin());
00461         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
00462         m_size = other.size();
00463 
00464         return *this;
00465     }
00466 
00467     template<typename T, size_t inlineCapacity>
00468     template<size_t otherCapacity> 
00469     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
00470     {
00471         if (&other == this)
00472             return *this;
00473         
00474         if (size() > other.size())
00475             resize(other.size());
00476         else if (other.size() > capacity()) {
00477             clear();
00478             reserveCapacity(other.size());
00479         }
00480         
00481         std::copy(other.begin(), other.begin() + size(), begin());
00482         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
00483         m_size = other.size();
00484 
00485         return *this;
00486     }
00487 
00488     template<typename T, size_t inlineCapacity>
00489     void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
00490     {
00491         if (size() > newSize)
00492             resize(newSize);
00493         else if (newSize > capacity()) {
00494             clear();
00495             reserveCapacity(newSize);
00496         }
00497         
00498         std::fill(begin(), end(), val);
00499         TypeOperations::uninitializedFill(end(), begin() + newSize, val);
00500         m_size = newSize;
00501     }
00502 
00503     template<typename T, size_t inlineCapacity>
00504     void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity)
00505     {
00506         reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1)));
00507     }
00508     
00509     template<typename T, size_t inlineCapacity>
00510     const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr)
00511     {
00512         if (ptr < begin() || ptr >= end()) {
00513             expandCapacity(newMinCapacity);
00514             return ptr;
00515         }
00516         size_t index = ptr - begin();
00517         expandCapacity(newMinCapacity);
00518         return begin() + index;
00519     }
00520 
00521     template<typename T, size_t inlineCapacity> template<typename U>
00522     inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr)
00523     {
00524         expandCapacity(newMinCapacity);
00525         return ptr;
00526     }
00527 
00528     template<typename T, size_t inlineCapacity>
00529     void Vector<T, inlineCapacity>::resize(size_t size)
00530     {
00531         if (size <= m_size)
00532             TypeOperations::destruct(begin() + size, end());
00533         else {
00534             if (size > capacity())
00535                 expandCapacity(size);
00536             TypeOperations::initialize(end(), begin() + size);
00537         }
00538         
00539         m_size = size;
00540     }
00541 
00542     template<typename T, size_t inlineCapacity>
00543     void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity)
00544     {
00545         if (newCapacity < capacity())
00546             return;
00547         T* oldBuffer = begin();
00548         T* oldEnd = end();
00549         m_impl.allocateBuffer(newCapacity);
00550         TypeOperations::move(oldBuffer, oldEnd, begin());
00551         m_impl.deallocateBuffer(oldBuffer);
00552     }
00553 
00554     // templatizing these is better than just letting the conversion happen implicitly,
00555     // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
00556     // without refcount thrash.
00557 
00558     template<typename T, size_t inlineCapacity> template<typename U>
00559     inline void Vector<T, inlineCapacity>::append(const U& val)
00560     {
00561         const U* ptr = &val;
00562         if (size() == capacity())
00563             ptr = expandCapacity(size() + 1, ptr);
00564 #if defined(_MSC_VER)
00565         new (end()) T(static_cast<T>(*ptr));
00566 #else
00567         new (end()) T(*ptr);
00568 #endif
00569         ++m_size;
00570     }
00571 
00572     template<typename T, size_t inlineCapacity> template<typename U>
00573     inline void Vector<T, inlineCapacity>::append(const Vector<U>& val)
00574     {
00575         if (size() + val.size() >= capacity())
00576             expandCapacity(size() + val.size());
00577         for (unsigned i = 0; i < val.size(); i++)
00578             append(val[i]);
00579     }
00580     
00581     template<typename T, size_t inlineCapacity> template<typename U>
00582     inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val)
00583     {
00584         ASSERT(position <= size());
00585         const U* ptr = &val;
00586         if (size() == capacity())
00587             ptr = expandCapacity(size() + 1, ptr);
00588         T* spot = begin() + position;
00589         TypeOperations::moveOverlapping(spot, end(), spot + 1);
00590         new (spot) T(*ptr);
00591         ++m_size;
00592     }
00593 
00594     template<typename T, size_t inlineCapacity>
00595     inline void Vector<T, inlineCapacity>::remove(size_t position)
00596     {
00597         ASSERT(position < size());
00598         T* spot = begin() + position;
00599         spot->~T();
00600         TypeOperations::moveOverlapping(spot + 1, end(), spot);
00601         --m_size;
00602     }
00603 
00604     template<typename T, size_t inlineCapacity>
00605     void deleteAllValues(const Vector<T, inlineCapacity>& collection)
00606     {
00607         typedef typename Vector<T, inlineCapacity>::const_iterator iterator;
00608         iterator end = collection.end();
00609         for (iterator it = collection.begin(); it != end; ++it)
00610             delete *it;
00611     }
00612 
00613     template<typename T, size_t inlineCapacity>
00614     inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b)
00615     {
00616         a.swap(b);
00617     }
00618 
00619 } // namespace WTF
00620 
00621 using WTF::Vector;
00622 
00623 #endif // WTF_Vector_h
00624 

WTF

Skip menu "WTF"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   WTF
  • KJSEmbed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  •   core
  • Phonon
  •   Backend
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal