Add range erase, element insert, and range insert methods to
authorChandler Carruth <chandlerc@gmail.com>
Wed, 1 Aug 2012 08:40:48 +0000 (08:40 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 1 Aug 2012 08:40:48 +0000 (08:40 +0000)
TinyPtrVector. With these, it is sufficiently functional for my more
normal / pedestrian uses.

I've not included some r-value reference stuff here because the value
type for a TinyPtrVector is, necessarily, just a pointer.

I've added tests that cover the basic behavior of these routines, but
they aren't as comprehensive as I'd like. In particular, they don't
really test the iterator semantics as thoroughly as they should. Maybe
some brave soul will feel enterprising and flesh them out. ;]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161104 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/TinyPtrVector.h
unittests/ADT/TinyPtrVectorTest.cpp

index d226bc208529101e02b4dfce82ce553d84ec9ad9..d3d33b8adde1baa93f4a2fd1b60f48838aca5007 100644 (file)
@@ -11,8 +11,9 @@
 #define LLVM_ADT_TINYPTRVECTOR_H
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
@@ -229,6 +230,61 @@ public:
     }
     return end();
   }
+
+  iterator erase(iterator S, iterator E) {
+    assert(S >= begin() && "Range to erase is out of bounds.");
+    assert(S <= E && "Trying to erase invalid range.");
+    assert(E <= end() && "Trying to erase past the end.");
+
+    if (Val.template is<EltTy>()) {
+      if (S == begin() && S != E)
+        Val = (EltTy)0;
+    } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
+      return Vec->erase(S, E);
+    }
+    return end();
+  }
+
+  iterator insert(iterator I, const EltTy &Elt) {
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+    if (I == end()) {
+      push_back(Elt);
+      return llvm::prior(end());
+    }
+    assert(!Val.isNull() && "Null value with non-end insert iterator.");
+    if (EltTy V = Val.template dyn_cast<EltTy>()) {
+      assert(I == begin());
+      Val = Elt;
+      push_back(V);
+      return begin();
+    }
+
+    return Val.template get<VecTy*>()->insert(I, Elt);
+  }
+
+  template<typename ItTy>
+  iterator insert(iterator I, ItTy From, ItTy To) {
+    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
+    assert(I <= this->end() && "Inserting past the end of the vector.");
+    if (From == To)
+      return I;
+
+    // If we have a single value, convert to a vector.
+    ptrdiff_t Offset = I - begin();
+    if (Val.isNull()) {
+      if (llvm::next(From) == To) {
+        Val = *From;
+        return begin();
+      }
+
+      Val = new VecTy();
+    } else if (EltTy V = Val.template dyn_cast<EltTy>()) {
+      Val = new VecTy();
+      Val.template get<VecTy*>()->push_back(V);
+    }
+    return Val.template get<VecTy*>()->insert(begin() + Offset, From, To);
+  }
 };
 } // end namespace llvm
 
index 94939279c14771f6bfdfff69dd97517797ca35a7..05dd797e0141b922c277930872f91f10c825a325 100644 (file)
@@ -354,4 +354,95 @@ TYPED_TEST(TinyPtrVectorTest, EraseTest) {
   this->expectValues(this->V, this->testArray(0));
 }
 
+TYPED_TEST(TinyPtrVectorTest, EraseRangeTest) {
+  this->appendValues(this->V, this->testArray(1));
+  this->expectValues(this->V, this->testArray(1));
+  this->V.erase(this->V.begin(), this->V.begin());
+  this->expectValues(this->V, this->testArray(1));
+  this->V.erase(this->V.end(), this->V.end());
+  this->expectValues(this->V, this->testArray(1));
+  this->V.erase(this->V.begin(), this->V.end());
+  this->expectValues(this->V, this->testArray(0));
+
+  this->appendValues(this->V, this->testArray(42));
+  this->expectValues(this->V, this->testArray(42));
+  this->V.erase(this->V.begin(), llvm::next(this->V.begin(), 1));
+  this->TestPtrs.erase(this->TestPtrs.begin(),
+                       llvm::next(this->TestPtrs.begin(), 1));
+  this->expectValues(this->V, this->testArray(41));
+  this->V.erase(llvm::next(this->V.begin(), 1), llvm::next(this->V.begin(), 2));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1),
+                       llvm::next(this->TestPtrs.begin(), 2));
+  this->expectValues(this->V, this->testArray(40));
+  this->V.erase(llvm::next(this->V.begin(), 2), llvm::next(this->V.begin(), 4));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2),
+                       llvm::next(this->TestPtrs.begin(), 4));
+  this->expectValues(this->V, this->testArray(38));
+  this->V.erase(llvm::next(this->V.begin(), 5), llvm::next(this->V.begin(), 10));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5),
+                       llvm::next(this->TestPtrs.begin(), 10));
+  this->expectValues(this->V, this->testArray(33));
+  this->V.erase(llvm::next(this->V.begin(), 13), llvm::next(this->V.begin(), 26));
+  this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13),
+                       llvm::next(this->TestPtrs.begin(), 26));
+  this->expectValues(this->V, this->testArray(20));
+  this->V.erase(llvm::next(this->V.begin(), 7), this->V.end());
+  this->expectValues(this->V, this->testArray(7));
+  this->V.erase(this->V.begin(), this->V.end());
+  this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, Insert) {
+  this->V.insert(this->V.end(), this->TestPtrs[0]);
+  this->expectValues(this->V, this->testArray(1));
+  this->V.clear();
+  this->appendValues(this->V, this->testArray(4));
+  this->expectValues(this->V, this->testArray(4));
+  this->V.insert(this->V.end(), this->TestPtrs[4]);
+  this->expectValues(this->V, this->testArray(5));
+  this->V.insert(this->V.begin(), this->TestPtrs[42]);
+  this->TestPtrs.insert(this->TestPtrs.begin(), this->TestPtrs[42]);
+  this->expectValues(this->V, this->testArray(6));
+  this->V.insert(llvm::next(this->V.begin(), 3), this->TestPtrs[43]);
+  this->TestPtrs.insert(llvm::next(this->TestPtrs.begin(), 3),
+                        this->TestPtrs[43]);
+  this->expectValues(this->V, this->testArray(7));
+}
+
+TYPED_TEST(TinyPtrVectorTest, InsertRange) {
+  this->V.insert(this->V.end(), this->TestPtrs.begin(), this->TestPtrs.begin());
+  this->expectValues(this->V, this->testArray(0));
+  this->V.insert(this->V.begin(), this->TestPtrs.begin(),
+                 this->TestPtrs.begin());
+  this->expectValues(this->V, this->testArray(0));
+  this->V.insert(this->V.end(), this->TestPtrs.end(), this->TestPtrs.end());
+  this->expectValues(this->V, this->testArray(0));
+  this->V.insert(this->V.end(), this->TestPtrs.begin(),
+                 llvm::next(this->TestPtrs.begin()));
+  this->expectValues(this->V, this->testArray(1));
+  this->V.clear();
+  this->V.insert(this->V.end(), this->TestPtrs.begin(),
+                 llvm::next(this->TestPtrs.begin(), 2));
+  this->expectValues(this->V, this->testArray(2));
+  this->V.clear();
+  this->V.insert(this->V.end(), this->TestPtrs.begin(),
+                 llvm::next(this->TestPtrs.begin(), 42));
+  this->expectValues(this->V, this->testArray(42));
+  this->V.clear();
+  this->V.insert(this->V.end(),
+                 llvm::next(this->TestPtrs.begin(), 5),
+                 llvm::next(this->TestPtrs.begin(), 13));
+  this->V.insert(this->V.begin(),
+                 llvm::next(this->TestPtrs.begin(), 0),
+                 llvm::next(this->TestPtrs.begin(), 3));
+  this->V.insert(llvm::next(this->V.begin(), 2),
+                 llvm::next(this->TestPtrs.begin(), 2),
+                 llvm::next(this->TestPtrs.begin(), 4));
+  this->V.erase(llvm::next(this->V.begin(), 4));
+  this->V.insert(llvm::next(this->V.begin(), 4),
+                 llvm::next(this->TestPtrs.begin(), 4),
+                 llvm::next(this->TestPtrs.begin(), 5));
+  this->expectValues(this->V, this->testArray(13));
+}
+
 }