From 19d59ce917006e6658a5606c29ae580323342f3d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 22 Aug 2006 06:27:16 +0000 Subject: [PATCH] add a bunch more operations, including swap, insert, erase, front(), and bugfixes for operator=. llvm-svn: 29811 --- include/llvm/ADT/SmallVector.h | 128 +++++++++++++++++++++++++++++---- 1 file changed, 115 insertions(+), 13 deletions(-) diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index bd2f260cd03..ac76944f267 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -48,8 +48,7 @@ public: ~SmallVectorImpl() { // Destroy the constructed elements in the vector. - for (iterator I = Begin, E = End; I != E; ++I) - I->~T(); + destroy_range(Begin, End); // If this wasn't grown from the inline copy, deallocate the old space. if (!isSmall()) @@ -78,6 +77,13 @@ public: return Begin[idx]; } + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + reference back() { return end()[-1]; } @@ -102,9 +108,44 @@ public: } void clear() { - while (End != Begin) { - End->~T(); - --End; + destroy_range(Begin, End); + End = Begin; + } + + void swap(SmallVectorImpl &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!isSmall() && !RHS.isSmall()) { + std::swap(Begin, RHS.Begin); + std::swap(End, RHS.End); + std::swap(Capacity, RHS.Capacity); + return; + } + if (Begin+RHS.size() > Capacity) + grow(RHS.size()); + if (RHS.begin()+size() > RHS.Capacity) + RHS.grow(size()); + + // Swap the shared elements. + unsigned NumShared = size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (unsigned i = 0; i != NumShared; ++i) + std::swap(Begin[i], RHS[i]); + + // Copy over the extra elts. + if (size() > RHS.size()) { + unsigned EltDiff = size() - RHS.size(); + std::uninitialized_copy(Begin+NumShared, End, RHS.End); + RHS.End += EltDiff; + destroy_range(Begin+NumShared, End); + End = Begin+NumShared; + } else if (RHS.size() > size()) { + unsigned EltDiff = RHS.size() - size(); + std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); + End += EltDiff; + destroy_range(RHS.Begin+NumShared, RHS.End); + RHS.End = RHS.Begin+NumShared; } } @@ -131,6 +172,42 @@ public: new (Begin+NumElts-1) T(Elt); } + void erase(iterator I) { + // Shift all elts down one. + std::copy(I+1, End, I); + // Drop the last elt. + pop_back(); + } + + void erase(iterator S, iterator E) { + // Shift all elts down. + iterator I = std::copy(E, End, S); + // Drop the last elts. + destroy_range(I, End); + End = I; + } + + iterator insert(iterator I, const T &Elt) { + if (I == End) { // Important special case for empty vector. + push_back(Elt); + return end()-1; + } + + if (End < Capacity) { + Retry: + new (End) T(back()); + ++End; + // Push everything else over. + std::copy_backward(I, End-1, End); + *I = Elt; + return I; + } + unsigned EltNo = I-Begin; + grow(); + I = Begin+EltNo; + goto Retry; + } + const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); private: @@ -143,6 +220,13 @@ private: /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. void grow(unsigned MinSize = 0); + + void destroy_range(T *S, T *E) { + while (S != E) { + E->~T(); + --E; + } + } }; // Define this out-of-line to dissuade the C++ compiler from inlining it. @@ -159,8 +243,7 @@ void SmallVectorImpl::grow(unsigned MinSize) { std::uninitialized_copy(Begin, End, NewElts); // Destroy the original elements. - for (iterator I = Begin, E = End; I != E; ++I) - I->~T(); + destroy_range(Begin, End); // If this wasn't grown from the inline copy, deallocate the old space. if (!isSmall()) @@ -183,14 +266,13 @@ SmallVectorImpl::operator=(const SmallVectorImpl &RHS) { unsigned CurSize = size(); if (CurSize >= RHSSize) { // Assign common elements. - std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); + iterator NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); // Destroy excess elements. - for (unsigned i = RHSSize; i != CurSize; ++i) - Begin[i].~T(); + destroy_range(NewEnd, End); // Trim. - End = Begin + RHSSize; + End = NewEnd; return *this; } @@ -198,8 +280,7 @@ SmallVectorImpl::operator=(const SmallVectorImpl &RHS) { // This allows us to avoid copying them during the grow. if (unsigned(Capacity-Begin) < RHSSize) { // Destroy current elements. - for (iterator I = Begin, E = End; I != E; ++I) - I->~T(); + destroy_range(Begin, End); End = Begin; CurSize = 0; grow(RHSSize); @@ -255,8 +336,29 @@ public: SmallVector(const SmallVector &RHS) : SmallVectorImpl(NumTsAvailable) { operator=(RHS); } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl::operator=(RHS); + return *this; + } }; } // End llvm namespace +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { + LHS.swap(RHS); + } +} + #endif