diff options
Diffstat (limited to 'include/llvm/ADT/SmallVector.h')
-rw-r--r-- | include/llvm/ADT/SmallVector.h | 160 |
1 files changed, 82 insertions, 78 deletions
diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 18c8619..fa61d20 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -17,6 +17,8 @@ #include "llvm/Support/type_traits.h" #include <algorithm> #include <cassert> +#include <cstddef> +#include <cstdlib> #include <cstring> #include <memory> @@ -70,35 +72,35 @@ protected: #endif } FirstEl; // Space after 'FirstEl' is clobbered, do not add any instance vars after it. - + protected: SmallVectorBase(size_t Size) : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {} - + /// isSmall - Return true if this is a smallvector which has not had dynamic /// memory allocated for it. bool isSmall() const { return BeginX == static_cast<const void*>(&FirstEl); } - + /// size_in_bytes - This returns size()*sizeof(T). size_t size_in_bytes() const { return size_t((char*)EndX - (char*)BeginX); } - + /// capacity_in_bytes - This returns capacity()*sizeof(T). size_t capacity_in_bytes() const { return size_t((char*)CapacityX - (char*)BeginX); } - + /// grow_pod - This is an implementation of the grow() method which only works /// on POD-like datatypes and is out of line to reduce code duplication. void grow_pod(size_t MinSizeInBytes, size_t TSize); - + public: bool empty() const { return BeginX == EndX; } }; - + template <typename T> class SmallVectorTemplateCommon : public SmallVectorBase { @@ -106,21 +108,21 @@ protected: void setEnd(T *P) { this->EndX = P; } public: SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} - + typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; typedef T *iterator; typedef const T *const_iterator; - + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; - + typedef T &reference; typedef const T &const_reference; typedef T *pointer; typedef const T *const_pointer; - + // forward iterator creation methods. iterator begin() { return (iterator)this->BeginX; } const_iterator begin() const { return (const_iterator)this->BeginX; } @@ -130,7 +132,7 @@ protected: iterator capacity_ptr() { return (iterator)this->CapacityX; } const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} public: - + // reverse iterator creation methods. reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } @@ -139,16 +141,16 @@ public: size_type size() const { return end()-begin(); } size_type max_size() const { return size_type(-1) / sizeof(T); } - + /// capacity - Return the total number of elements in the currently allocated /// buffer. size_t capacity() const { return capacity_ptr() - begin(); } - + /// data - Return a pointer to the vector's buffer, even if empty(). pointer data() { return pointer(begin()); } /// data - Return a pointer to the vector's buffer, even if empty(). const_pointer data() const { return const_pointer(begin()); } - + reference operator[](unsigned idx) { assert(begin() + idx < end()); return begin()[idx]; @@ -172,7 +174,7 @@ public: return end()[-1]; } }; - + /// SmallVectorTemplateBase<isPodLike = false> - This is where we put method /// implementations that are designed to work with non-POD-like T's. template <typename T, bool isPodLike> @@ -186,14 +188,14 @@ public: E->~T(); } } - + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename It1, typename It2> static void uninitialized_copy(It1 I, It1 E, It2 Dest) { std::uninitialized_copy(I, E, Dest); } - + /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. void grow(size_t MinSize = 0); @@ -207,34 +209,34 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { size_t NewCapacity = 2*CurCapacity; if (NewCapacity < MinSize) NewCapacity = MinSize; - T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T))); - + T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); + // Copy the elements over. this->uninitialized_copy(this->begin(), this->end(), NewElts); - + // Destroy the original elements. destroy_range(this->begin(), this->end()); - + // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) - operator delete(this->begin()); - + free(this->begin()); + this->setEnd(NewElts+CurSize); this->BeginX = NewElts; this->CapacityX = this->begin()+NewCapacity; } - - + + /// SmallVectorTemplateBase<isPodLike = true> - This is where we put method /// implementations that are designed to work with POD-like T's. template <typename T> class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { public: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} - + // No need to do a destroy loop for POD's. static void destroy_range(T *, T *) {} - + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template<typename It1, typename It2> @@ -259,33 +261,35 @@ public: this->grow_pod(MinSize*sizeof(T), sizeof(T)); } }; - - + + /// SmallVectorImpl - This class consists of common code factored out of the /// SmallVector class to reduce code duplication based on the SmallVector 'N' /// template parameter. template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> { typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass; + + SmallVectorImpl(const SmallVectorImpl&); // DISABLED. public: typedef typename SuperClass::iterator iterator; typedef typename SuperClass::size_type size_type; - + // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned N) : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) { } - + ~SmallVectorImpl() { // Destroy the constructed elements in the vector. this->destroy_range(this->begin(), this->end()); - + // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) - operator delete(this->begin()); + free(this->begin()); } - - + + void clear() { this->destroy_range(this->begin(), this->end()); this->EndX = this->BeginX; @@ -319,7 +323,7 @@ public: if (this->capacity() < N) this->grow(N); } - + void push_back(const T &Elt) { if (this->EndX < this->CapacityX) { Retry: @@ -330,21 +334,21 @@ public: this->grow(); goto Retry; } - + void pop_back() { this->setEnd(this->end()-1); this->end()->~T(); } - + T pop_back_val() { T Result = this->back(); pop_back(); return Result; } - - + + void swap(SmallVectorImpl &RHS); - + /// append - Add the specified range to the end of the SmallVector. /// template<typename in_iter> @@ -353,26 +357,26 @@ public: // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) this->grow(this->size()+NumInputs); - + // Copy the new elements over. // TODO: NEED To compile time dispatch on whether in_iter is a random access // iterator to use the fast uninitialized_copy. std::uninitialized_copy(in_start, in_end, this->end()); this->setEnd(this->end() + NumInputs); } - + /// append - Add the specified range to the end of the SmallVector. /// void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) this->grow(this->size()+NumInputs); - + // Copy the new elements over. std::uninitialized_fill_n(this->end(), NumInputs, Elt); this->setEnd(this->end() + NumInputs); } - + void assign(unsigned NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) @@ -380,7 +384,7 @@ public: this->setEnd(this->begin()+NumElts); construct_range(this->begin(), this->end(), Elt); } - + iterator erase(iterator I) { iterator N = I; // Shift all elts down one. @@ -389,7 +393,7 @@ public: pop_back(); return(N); } - + iterator erase(iterator S, iterator E) { iterator N = S; // Shift all elts down. @@ -399,13 +403,13 @@ public: this->setEnd(I); return(N); } - + iterator insert(iterator I, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. push_back(Elt); return this->end()-1; } - + if (this->EndX < this->CapacityX) { Retry: new (this->end()) T(this->back()); @@ -420,22 +424,22 @@ public: I = this->begin()+EltNo; goto Retry; } - + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. append(NumToInsert, Elt); return this->end()-1; } - + // Convert iterator to elt# to avoid invalidating iterator when we reserve() size_t InsertElt = I - this->begin(); - + // Ensure there is enough space. reserve(static_cast<unsigned>(this->size() + NumToInsert)); - + // Uninvalidate the iterator. I = this->begin()+InsertElt; - + // If there are more elements between the insertion point and the end of the // range than there are being inserted, we can use a simple approach to // insertion. Since we already reserved space, we know that this won't @@ -443,48 +447,48 @@ public: if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); append(this->end()-NumToInsert, this->end()); - + // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - + std::fill_n(I, NumToInsert, Elt); return I; } - + // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - + // Copy over the elements that we're about to overwrite. T *OldEnd = this->end(); this->setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); - + // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); - + // Insert the non-overwritten middle part. std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); return I; } - + template<typename ItTy> iterator insert(iterator I, ItTy From, ItTy To) { if (I == this->end()) { // Important special case for empty vector. append(From, To); return this->end()-1; } - + size_t NumToInsert = std::distance(From, To); // Convert iterator to elt# to avoid invalidating iterator when we reserve() size_t InsertElt = I - this->begin(); - + // Ensure there is enough space. reserve(static_cast<unsigned>(this->size() + NumToInsert)); - + // Uninvalidate the iterator. I = this->begin()+InsertElt; - + // If there are more elements between the insertion point and the end of the // range than there are being inserted, we can use a simple approach to // insertion. Since we already reserved space, we know that this won't @@ -492,37 +496,37 @@ public: if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); append(this->end()-NumToInsert, this->end()); - + // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - + std::copy(From, To, I); return I; } - + // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - + // Copy over the elements that we're about to overwrite. T *OldEnd = this->end(); this->setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); - + // Replace the overwritten part. for (; NumOverwritten > 0; --NumOverwritten) { *I = *From; ++I; ++From; } - + // Insert the non-overwritten middle part. this->uninitialized_copy(From, To, OldEnd); return I; } - + const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); - + bool operator==(const SmallVectorImpl &RHS) const { if (this->size() != RHS.size()) return false; return std::equal(this->begin(), this->end(), RHS.begin()); @@ -530,12 +534,12 @@ public: bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } - + bool operator<(const SmallVectorImpl &RHS) const { return std::lexicographical_compare(this->begin(), this->end(), RHS.begin(), RHS.end()); } - + /// set_size - Set the array size to \arg N, which the current array must have /// enough capacity for. /// @@ -549,14 +553,14 @@ public: assert(N <= this->capacity()); this->setEnd(this->begin() + N); } - + private: static void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) new (S) T(Elt); } }; - + template <typename T> void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { |