]> granicus.if.org Git - clang/commitdiff
Fix rewrite rope to keep the leaf list up-to-date as it erases leaves
authorChris Lattner <sabre@nondot.org>
Wed, 28 May 2008 18:45:56 +0000 (18:45 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 28 May 2008 18:45:56 +0000 (18:45 +0000)
from the rope.  rdar://5952468

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

include/clang/Rewrite/RewriteRope.h
lib/Rewrite/RewriteRope.cpp

index 00e59096a4c0a8305d0bdec5aa3471bfe2caa6e7..a1fab31c932d1854681d368da3858f9309c37f8f 100644 (file)
@@ -181,7 +181,7 @@ class RewriteRope {
   RopeRefCountString *AllocBuffer;
   unsigned AllocOffs;
   enum { AllocChunkSize = 4080 };
-  
+
 public:
   RewriteRope() :  AllocBuffer(0), AllocOffs(AllocChunkSize) {}
   RewriteRope(const RewriteRope &RHS) 
index f1fd3f7ba9711e24ef5839773c646a003071744b..0a4dc8596844208a51d1d50b33e19eaef084f770 100644 (file)
@@ -147,9 +147,14 @@ namespace {
     
     /// NextLeaf - This is a pointer to the next leaf in the tree, allowing
     /// efficient in-order forward iteration of the tree without traversal.
-    const RopePieceBTreeLeaf *NextLeaf;
+    RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
   public:
-    RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0), NextLeaf(0){}
+    RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
+                           PrevLeaf(0), NextLeaf(0) {}
+    ~RopePieceBTreeLeaf() {
+      if (PrevLeaf || NextLeaf)
+        removeFromLeafInOrder();
+    }
     
     bool isFull() const { return NumPieces == 2*WidthFactor; }
     
@@ -168,7 +173,25 @@ namespace {
     }
     
     const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
-    void setNextLeafInOrder(const RopePieceBTreeLeaf *NL) { NextLeaf = NL; }
+    void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
+      assert(PrevLeaf == 0 && NextLeaf == 0 && "Already in ordering");
+      
+      NextLeaf = Node->NextLeaf;
+      if (NextLeaf)
+        NextLeaf->PrevLeaf = &NextLeaf;
+      PrevLeaf = &Node->NextLeaf;
+      Node->NextLeaf = this;
+    }
+    
+    void removeFromLeafInOrder() {
+      if (PrevLeaf) {
+        *PrevLeaf = NextLeaf;
+        if (NextLeaf)
+          NextLeaf->PrevLeaf = PrevLeaf;
+      } else if (NextLeaf) {
+        NextLeaf->PrevLeaf = 0;
+      }
+    }
     
     /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
     /// summing the size of all RopePieces.
@@ -302,8 +325,7 @@ RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
   FullRecomputeSizeLocally();
   
   // Update the list of leaves.
-  NewNode->setNextLeafInOrder(this->getNextLeafInOrder());
-  this->setNextLeafInOrder(NewNode);
+  NewNode->insertAfterLeafInOrder(this);
   
   // These insertions can't fail.
   if (this->size() >= Offset)