clang API Documentation

RewriteRope.cpp
Go to the documentation of this file.
00001 //===--- RewriteRope.cpp - Rope specialized for rewriter --------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file implements the RewriteRope class, which is a powerful string.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Rewrite/Core/RewriteRope.h"
00015 #include "clang/Basic/LLVM.h"
00016 #include <algorithm>
00017 using namespace clang;
00018 
00019 /// RewriteRope is a "strong" string class, designed to make insertions and
00020 /// deletions in the middle of the string nearly constant time (really, they are
00021 /// O(log N), but with a very low constant factor).
00022 ///
00023 /// The implementation of this datastructure is a conceptual linear sequence of
00024 /// RopePiece elements.  Each RopePiece represents a view on a separately
00025 /// allocated and reference counted string.  This means that splitting a very
00026 /// long string can be done in constant time by splitting a RopePiece that
00027 /// references the whole string into two rope pieces that reference each half.
00028 /// Once split, another string can be inserted in between the two halves by
00029 /// inserting a RopePiece in between the two others.  All of this is very
00030 /// inexpensive: it takes time proportional to the number of RopePieces, not the
00031 /// length of the strings they represent.
00032 ///
00033 /// While a linear sequences of RopePieces is the conceptual model, the actual
00034 /// implementation captures them in an adapted B+ Tree.  Using a B+ tree (which
00035 /// is a tree that keeps the values in the leaves and has where each node
00036 /// contains a reasonable number of pointers to children/values) allows us to
00037 /// maintain efficient operation when the RewriteRope contains a *huge* number
00038 /// of RopePieces.  The basic idea of the B+ Tree is that it allows us to find
00039 /// the RopePiece corresponding to some offset very efficiently, and it
00040 /// automatically balances itself on insertions of RopePieces (which can happen
00041 /// for both insertions and erases of string ranges).
00042 ///
00043 /// The one wrinkle on the theory is that we don't attempt to keep the tree
00044 /// properly balanced when erases happen.  Erases of string data can both insert
00045 /// new RopePieces (e.g. when the middle of some other rope piece is deleted,
00046 /// which results in two rope pieces, which is just like an insert) or it can
00047 /// reduce the number of RopePieces maintained by the B+Tree.  In the case when
00048 /// the number of RopePieces is reduced, we don't attempt to maintain the
00049 /// standard 'invariant' that each node in the tree contains at least
00050 /// 'WidthFactor' children/values.  For our use cases, this doesn't seem to
00051 /// matter.
00052 ///
00053 /// The implementation below is primarily implemented in terms of three classes:
00054 ///   RopePieceBTreeNode - Common base class for:
00055 ///
00056 ///     RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
00057 ///          nodes.  This directly represents a chunk of the string with those
00058 ///          RopePieces contatenated.
00059 ///     RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
00060 ///          up to '2*WidthFactor' other nodes in the tree.
00061 
00062 
00063 //===----------------------------------------------------------------------===//
00064 // RopePieceBTreeNode Class
00065 //===----------------------------------------------------------------------===//
00066 
00067 namespace {
00068   /// RopePieceBTreeNode - Common base class of RopePieceBTreeLeaf and
00069   /// RopePieceBTreeInterior.  This provides some 'virtual' dispatching methods
00070   /// and a flag that determines which subclass the instance is.  Also
00071   /// important, this node knows the full extend of the node, including any
00072   /// children that it has.  This allows efficient skipping over entire subtrees
00073   /// when looking for an offset in the BTree.
00074   class RopePieceBTreeNode {
00075   protected:
00076     /// WidthFactor - This controls the number of K/V slots held in the BTree:
00077     /// how wide it is.  Each level of the BTree is guaranteed to have at least
00078     /// 'WidthFactor' elements in it (either ropepieces or children), (except
00079     /// the root, which may have less) and may have at most 2*WidthFactor
00080     /// elements.
00081     enum { WidthFactor = 8 };
00082 
00083     /// Size - This is the number of bytes of file this node (including any
00084     /// potential children) covers.
00085     unsigned Size;
00086 
00087     /// IsLeaf - True if this is an instance of RopePieceBTreeLeaf, false if it
00088     /// is an instance of RopePieceBTreeInterior.
00089     bool IsLeaf;
00090 
00091     RopePieceBTreeNode(bool isLeaf) : Size(0), IsLeaf(isLeaf) {}
00092     ~RopePieceBTreeNode() {}
00093   public:
00094 
00095     bool isLeaf() const { return IsLeaf; }
00096     unsigned size() const { return Size; }
00097 
00098     void Destroy();
00099 
00100     /// split - Split the range containing the specified offset so that we are
00101     /// guaranteed that there is a place to do an insertion at the specified
00102     /// offset.  The offset is relative, so "0" is the start of the node.
00103     ///
00104     /// If there is no space in this subtree for the extra piece, the extra tree
00105     /// node is returned and must be inserted into a parent.
00106     RopePieceBTreeNode *split(unsigned Offset);
00107 
00108     /// insert - Insert the specified ropepiece into this tree node at the
00109     /// specified offset.  The offset is relative, so "0" is the start of the
00110     /// node.
00111     ///
00112     /// If there is no space in this subtree for the extra piece, the extra tree
00113     /// node is returned and must be inserted into a parent.
00114     RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
00115 
00116     /// erase - Remove NumBytes from this node at the specified offset.  We are
00117     /// guaranteed that there is a split at Offset.
00118     void erase(unsigned Offset, unsigned NumBytes);
00119 
00120   };
00121 } // end anonymous namespace
00122 
00123 //===----------------------------------------------------------------------===//
00124 // RopePieceBTreeLeaf Class
00125 //===----------------------------------------------------------------------===//
00126 
00127 namespace {
00128   /// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
00129   /// nodes.  This directly represents a chunk of the string with those
00130   /// RopePieces contatenated.  Since this is a B+Tree, all values (in this case
00131   /// instances of RopePiece) are stored in leaves like this.  To make iteration
00132   /// over the leaves efficient, they maintain a singly linked list through the
00133   /// NextLeaf field.  This allows the B+Tree forward iterator to be constant
00134   /// time for all increments.
00135   class RopePieceBTreeLeaf : public RopePieceBTreeNode {
00136     /// NumPieces - This holds the number of rope pieces currently active in the
00137     /// Pieces array.
00138     unsigned char NumPieces;
00139 
00140     /// Pieces - This tracks the file chunks currently in this leaf.
00141     ///
00142     RopePiece Pieces[2*WidthFactor];
00143 
00144     /// NextLeaf - This is a pointer to the next leaf in the tree, allowing
00145     /// efficient in-order forward iteration of the tree without traversal.
00146     RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
00147   public:
00148     RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
00149                            PrevLeaf(nullptr), NextLeaf(nullptr) {}
00150     ~RopePieceBTreeLeaf() {
00151       if (PrevLeaf || NextLeaf)
00152         removeFromLeafInOrder();
00153       clear();
00154     }
00155 
00156     bool isFull() const { return NumPieces == 2*WidthFactor; }
00157 
00158     /// clear - Remove all rope pieces from this leaf.
00159     void clear() {
00160       while (NumPieces)
00161         Pieces[--NumPieces] = RopePiece();
00162       Size = 0;
00163     }
00164 
00165     unsigned getNumPieces() const { return NumPieces; }
00166 
00167     const RopePiece &getPiece(unsigned i) const {
00168       assert(i < getNumPieces() && "Invalid piece ID");
00169       return Pieces[i];
00170     }
00171 
00172     const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
00173     void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
00174       assert(!PrevLeaf && !NextLeaf && "Already in ordering");
00175 
00176       NextLeaf = Node->NextLeaf;
00177       if (NextLeaf)
00178         NextLeaf->PrevLeaf = &NextLeaf;
00179       PrevLeaf = &Node->NextLeaf;
00180       Node->NextLeaf = this;
00181     }
00182 
00183     void removeFromLeafInOrder() {
00184       if (PrevLeaf) {
00185         *PrevLeaf = NextLeaf;
00186         if (NextLeaf)
00187           NextLeaf->PrevLeaf = PrevLeaf;
00188       } else if (NextLeaf) {
00189         NextLeaf->PrevLeaf = nullptr;
00190       }
00191     }
00192 
00193     /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
00194     /// summing the size of all RopePieces.
00195     void FullRecomputeSizeLocally() {
00196       Size = 0;
00197       for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
00198         Size += getPiece(i).size();
00199     }
00200 
00201     /// split - Split the range containing the specified offset so that we are
00202     /// guaranteed that there is a place to do an insertion at the specified
00203     /// offset.  The offset is relative, so "0" is the start of the node.
00204     ///
00205     /// If there is no space in this subtree for the extra piece, the extra tree
00206     /// node is returned and must be inserted into a parent.
00207     RopePieceBTreeNode *split(unsigned Offset);
00208 
00209     /// insert - Insert the specified ropepiece into this tree node at the
00210     /// specified offset.  The offset is relative, so "0" is the start of the
00211     /// node.
00212     ///
00213     /// If there is no space in this subtree for the extra piece, the extra tree
00214     /// node is returned and must be inserted into a parent.
00215     RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
00216 
00217 
00218     /// erase - Remove NumBytes from this node at the specified offset.  We are
00219     /// guaranteed that there is a split at Offset.
00220     void erase(unsigned Offset, unsigned NumBytes);
00221 
00222     static inline bool classof(const RopePieceBTreeNode *N) {
00223       return N->isLeaf();
00224     }
00225   };
00226 } // end anonymous namespace
00227 
00228 /// split - Split the range containing the specified offset so that we are
00229 /// guaranteed that there is a place to do an insertion at the specified
00230 /// offset.  The offset is relative, so "0" is the start of the node.
00231 ///
00232 /// If there is no space in this subtree for the extra piece, the extra tree
00233 /// node is returned and must be inserted into a parent.
00234 RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
00235   // Find the insertion point.  We are guaranteed that there is a split at the
00236   // specified offset so find it.
00237   if (Offset == 0 || Offset == size()) {
00238     // Fastpath for a common case.  There is already a splitpoint at the end.
00239     return nullptr;
00240   }
00241 
00242   // Find the piece that this offset lands in.
00243   unsigned PieceOffs = 0;
00244   unsigned i = 0;
00245   while (Offset >= PieceOffs+Pieces[i].size()) {
00246     PieceOffs += Pieces[i].size();
00247     ++i;
00248   }
00249 
00250   // If there is already a split point at the specified offset, just return
00251   // success.
00252   if (PieceOffs == Offset)
00253     return nullptr;
00254 
00255   // Otherwise, we need to split piece 'i' at Offset-PieceOffs.  Convert Offset
00256   // to being Piece relative.
00257   unsigned IntraPieceOffset = Offset-PieceOffs;
00258 
00259   // We do this by shrinking the RopePiece and then doing an insert of the tail.
00260   RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset,
00261                  Pieces[i].EndOffs);
00262   Size -= Pieces[i].size();
00263   Pieces[i].EndOffs = Pieces[i].StartOffs+IntraPieceOffset;
00264   Size += Pieces[i].size();
00265 
00266   return insert(Offset, Tail);
00267 }
00268 
00269 
00270 /// insert - Insert the specified RopePiece into this tree node at the
00271 /// specified offset.  The offset is relative, so "0" is the start of the node.
00272 ///
00273 /// If there is no space in this subtree for the extra piece, the extra tree
00274 /// node is returned and must be inserted into a parent.
00275 RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
00276                                                const RopePiece &R) {
00277   // If this node is not full, insert the piece.
00278   if (!isFull()) {
00279     // Find the insertion point.  We are guaranteed that there is a split at the
00280     // specified offset so find it.
00281     unsigned i = 0, e = getNumPieces();
00282     if (Offset == size()) {
00283       // Fastpath for a common case.
00284       i = e;
00285     } else {
00286       unsigned SlotOffs = 0;
00287       for (; Offset > SlotOffs; ++i)
00288         SlotOffs += getPiece(i).size();
00289       assert(SlotOffs == Offset && "Split didn't occur before insertion!");
00290     }
00291 
00292     // For an insertion into a non-full leaf node, just insert the value in
00293     // its sorted position.  This requires moving later values over.
00294     for (; i != e; --e)
00295       Pieces[e] = Pieces[e-1];
00296     Pieces[i] = R;
00297     ++NumPieces;
00298     Size += R.size();
00299     return nullptr;
00300   }
00301 
00302   // Otherwise, if this is leaf is full, split it in two halves.  Since this
00303   // node is full, it contains 2*WidthFactor values.  We move the first
00304   // 'WidthFactor' values to the LHS child (which we leave in this node) and
00305   // move the last 'WidthFactor' values into the RHS child.
00306 
00307   // Create the new node.
00308   RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
00309 
00310   // Move over the last 'WidthFactor' values from here to NewNode.
00311   std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
00312             &NewNode->Pieces[0]);
00313   // Replace old pieces with null RopePieces to drop refcounts.
00314   std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor], RopePiece());
00315 
00316   // Decrease the number of values in the two nodes.
00317   NewNode->NumPieces = NumPieces = WidthFactor;
00318 
00319   // Recompute the two nodes' size.
00320   NewNode->FullRecomputeSizeLocally();
00321   FullRecomputeSizeLocally();
00322 
00323   // Update the list of leaves.
00324   NewNode->insertAfterLeafInOrder(this);
00325 
00326   // These insertions can't fail.
00327   if (this->size() >= Offset)
00328     this->insert(Offset, R);
00329   else
00330     NewNode->insert(Offset - this->size(), R);
00331   return NewNode;
00332 }
00333 
00334 /// erase - Remove NumBytes from this node at the specified offset.  We are
00335 /// guaranteed that there is a split at Offset.
00336 void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
00337   // Since we are guaranteed that there is a split at Offset, we start by
00338   // finding the Piece that starts there.
00339   unsigned PieceOffs = 0;
00340   unsigned i = 0;
00341   for (; Offset > PieceOffs; ++i)
00342     PieceOffs += getPiece(i).size();
00343   assert(PieceOffs == Offset && "Split didn't occur before erase!");
00344 
00345   unsigned StartPiece = i;
00346 
00347   // Figure out how many pieces completely cover 'NumBytes'.  We want to remove
00348   // all of them.
00349   for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i)
00350     PieceOffs += getPiece(i).size();
00351 
00352   // If we exactly include the last one, include it in the region to delete.
00353   if (Offset+NumBytes == PieceOffs+getPiece(i).size())
00354     PieceOffs += getPiece(i).size(), ++i;
00355 
00356   // If we completely cover some RopePieces, erase them now.
00357   if (i != StartPiece) {
00358     unsigned NumDeleted = i-StartPiece;
00359     for (; i != getNumPieces(); ++i)
00360       Pieces[i-NumDeleted] = Pieces[i];
00361 
00362     // Drop references to dead rope pieces.
00363     std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()],
00364               RopePiece());
00365     NumPieces -= NumDeleted;
00366 
00367     unsigned CoverBytes = PieceOffs-Offset;
00368     NumBytes -= CoverBytes;
00369     Size -= CoverBytes;
00370   }
00371 
00372   // If we completely removed some stuff, we could be done.
00373   if (NumBytes == 0) return;
00374 
00375   // Okay, now might be erasing part of some Piece.  If this is the case, then
00376   // move the start point of the piece.
00377   assert(getPiece(StartPiece).size() > NumBytes);
00378   Pieces[StartPiece].StartOffs += NumBytes;
00379 
00380   // The size of this node just shrunk by NumBytes.
00381   Size -= NumBytes;
00382 }
00383 
00384 //===----------------------------------------------------------------------===//
00385 // RopePieceBTreeInterior Class
00386 //===----------------------------------------------------------------------===//
00387 
00388 namespace {
00389   /// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
00390   /// which holds up to 2*WidthFactor pointers to child nodes.
00391   class RopePieceBTreeInterior : public RopePieceBTreeNode {
00392     /// NumChildren - This holds the number of children currently active in the
00393     /// Children array.
00394     unsigned char NumChildren;
00395     RopePieceBTreeNode *Children[2*WidthFactor];
00396   public:
00397     RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
00398 
00399     RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
00400     : RopePieceBTreeNode(false) {
00401       Children[0] = LHS;
00402       Children[1] = RHS;
00403       NumChildren = 2;
00404       Size = LHS->size() + RHS->size();
00405     }
00406 
00407     ~RopePieceBTreeInterior() {
00408       for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
00409         Children[i]->Destroy();
00410     }
00411 
00412     bool isFull() const { return NumChildren == 2*WidthFactor; }
00413 
00414     unsigned getNumChildren() const { return NumChildren; }
00415     const RopePieceBTreeNode *getChild(unsigned i) const {
00416       assert(i < NumChildren && "invalid child #");
00417       return Children[i];
00418     }
00419     RopePieceBTreeNode *getChild(unsigned i) {
00420       assert(i < NumChildren && "invalid child #");
00421       return Children[i];
00422     }
00423 
00424     /// FullRecomputeSizeLocally - Recompute the Size field of this node by
00425     /// summing up the sizes of the child nodes.
00426     void FullRecomputeSizeLocally() {
00427       Size = 0;
00428       for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
00429         Size += getChild(i)->size();
00430     }
00431 
00432 
00433     /// split - Split the range containing the specified offset so that we are
00434     /// guaranteed that there is a place to do an insertion at the specified
00435     /// offset.  The offset is relative, so "0" is the start of the node.
00436     ///
00437     /// If there is no space in this subtree for the extra piece, the extra tree
00438     /// node is returned and must be inserted into a parent.
00439     RopePieceBTreeNode *split(unsigned Offset);
00440 
00441 
00442     /// insert - Insert the specified ropepiece into this tree node at the
00443     /// specified offset.  The offset is relative, so "0" is the start of the
00444     /// node.
00445     ///
00446     /// If there is no space in this subtree for the extra piece, the extra tree
00447     /// node is returned and must be inserted into a parent.
00448     RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
00449 
00450     /// HandleChildPiece - A child propagated an insertion result up to us.
00451     /// Insert the new child, and/or propagate the result further up the tree.
00452     RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
00453 
00454     /// erase - Remove NumBytes from this node at the specified offset.  We are
00455     /// guaranteed that there is a split at Offset.
00456     void erase(unsigned Offset, unsigned NumBytes);
00457 
00458     static inline bool classof(const RopePieceBTreeNode *N) {
00459       return !N->isLeaf();
00460     }
00461   };
00462 } // end anonymous namespace
00463 
00464 /// split - Split the range containing the specified offset so that we are
00465 /// guaranteed that there is a place to do an insertion at the specified
00466 /// offset.  The offset is relative, so "0" is the start of the node.
00467 ///
00468 /// If there is no space in this subtree for the extra piece, the extra tree
00469 /// node is returned and must be inserted into a parent.
00470 RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
00471   // Figure out which child to split.
00472   if (Offset == 0 || Offset == size())
00473     return nullptr; // If we have an exact offset, we're already split.
00474 
00475   unsigned ChildOffset = 0;
00476   unsigned i = 0;
00477   for (; Offset >= ChildOffset+getChild(i)->size(); ++i)
00478     ChildOffset += getChild(i)->size();
00479 
00480   // If already split there, we're done.
00481   if (ChildOffset == Offset)
00482     return nullptr;
00483 
00484   // Otherwise, recursively split the child.
00485   if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
00486     return HandleChildPiece(i, RHS);
00487   return nullptr; // Done!
00488 }
00489 
00490 /// insert - Insert the specified ropepiece into this tree node at the
00491 /// specified offset.  The offset is relative, so "0" is the start of the
00492 /// node.
00493 ///
00494 /// If there is no space in this subtree for the extra piece, the extra tree
00495 /// node is returned and must be inserted into a parent.
00496 RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset,
00497                                                    const RopePiece &R) {
00498   // Find the insertion point.  We are guaranteed that there is a split at the
00499   // specified offset so find it.
00500   unsigned i = 0, e = getNumChildren();
00501 
00502   unsigned ChildOffs = 0;
00503   if (Offset == size()) {
00504     // Fastpath for a common case.  Insert at end of last child.
00505     i = e-1;
00506     ChildOffs = size()-getChild(i)->size();
00507   } else {
00508     for (; Offset > ChildOffs+getChild(i)->size(); ++i)
00509       ChildOffs += getChild(i)->size();
00510   }
00511 
00512   Size += R.size();
00513 
00514   // Insert at the end of this child.
00515   if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R))
00516     return HandleChildPiece(i, RHS);
00517 
00518   return nullptr;
00519 }
00520 
00521 /// HandleChildPiece - A child propagated an insertion result up to us.
00522 /// Insert the new child, and/or propagate the result further up the tree.
00523 RopePieceBTreeNode *
00524 RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) {
00525   // Otherwise the child propagated a subtree up to us as a new child.  See if
00526   // we have space for it here.
00527   if (!isFull()) {
00528     // Insert RHS after child 'i'.
00529     if (i + 1 != getNumChildren())
00530       memmove(&Children[i+2], &Children[i+1],
00531               (getNumChildren()-i-1)*sizeof(Children[0]));
00532     Children[i+1] = RHS;
00533     ++NumChildren;
00534     return nullptr;
00535   }
00536 
00537   // Okay, this node is full.  Split it in half, moving WidthFactor children to
00538   // a newly allocated interior node.
00539 
00540   // Create the new node.
00541   RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior();
00542 
00543   // Move over the last 'WidthFactor' values from here to NewNode.
00544   memcpy(&NewNode->Children[0], &Children[WidthFactor],
00545          WidthFactor*sizeof(Children[0]));
00546 
00547   // Decrease the number of values in the two nodes.
00548   NewNode->NumChildren = NumChildren = WidthFactor;
00549 
00550   // Finally, insert the two new children in the side the can (now) hold them.
00551   // These insertions can't fail.
00552   if (i < WidthFactor)
00553     this->HandleChildPiece(i, RHS);
00554   else
00555     NewNode->HandleChildPiece(i-WidthFactor, RHS);
00556 
00557   // Recompute the two nodes' size.
00558   NewNode->FullRecomputeSizeLocally();
00559   FullRecomputeSizeLocally();
00560   return NewNode;
00561 }
00562 
00563 /// erase - Remove NumBytes from this node at the specified offset.  We are
00564 /// guaranteed that there is a split at Offset.
00565 void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
00566   // This will shrink this node by NumBytes.
00567   Size -= NumBytes;
00568 
00569   // Find the first child that overlaps with Offset.
00570   unsigned i = 0;
00571   for (; Offset >= getChild(i)->size(); ++i)
00572     Offset -= getChild(i)->size();
00573 
00574   // Propagate the delete request into overlapping children, or completely
00575   // delete the children as appropriate.
00576   while (NumBytes) {
00577     RopePieceBTreeNode *CurChild = getChild(i);
00578 
00579     // If we are deleting something contained entirely in the child, pass on the
00580     // request.
00581     if (Offset+NumBytes < CurChild->size()) {
00582       CurChild->erase(Offset, NumBytes);
00583       return;
00584     }
00585 
00586     // If this deletion request starts somewhere in the middle of the child, it
00587     // must be deleting to the end of the child.
00588     if (Offset) {
00589       unsigned BytesFromChild = CurChild->size()-Offset;
00590       CurChild->erase(Offset, BytesFromChild);
00591       NumBytes -= BytesFromChild;
00592       // Start at the beginning of the next child.
00593       Offset = 0;
00594       ++i;
00595       continue;
00596     }
00597 
00598     // If the deletion request completely covers the child, delete it and move
00599     // the rest down.
00600     NumBytes -= CurChild->size();
00601     CurChild->Destroy();
00602     --NumChildren;
00603     if (i != getNumChildren())
00604       memmove(&Children[i], &Children[i+1],
00605               (getNumChildren()-i)*sizeof(Children[0]));
00606   }
00607 }
00608 
00609 //===----------------------------------------------------------------------===//
00610 // RopePieceBTreeNode Implementation
00611 //===----------------------------------------------------------------------===//
00612 
00613 void RopePieceBTreeNode::Destroy() {
00614   if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
00615     delete Leaf;
00616   else
00617     delete cast<RopePieceBTreeInterior>(this);
00618 }
00619 
00620 /// split - Split the range containing the specified offset so that we are
00621 /// guaranteed that there is a place to do an insertion at the specified
00622 /// offset.  The offset is relative, so "0" is the start of the node.
00623 ///
00624 /// If there is no space in this subtree for the extra piece, the extra tree
00625 /// node is returned and must be inserted into a parent.
00626 RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
00627   assert(Offset <= size() && "Invalid offset to split!");
00628   if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
00629     return Leaf->split(Offset);
00630   return cast<RopePieceBTreeInterior>(this)->split(Offset);
00631 }
00632 
00633 /// insert - Insert the specified ropepiece into this tree node at the
00634 /// specified offset.  The offset is relative, so "0" is the start of the
00635 /// node.
00636 ///
00637 /// If there is no space in this subtree for the extra piece, the extra tree
00638 /// node is returned and must be inserted into a parent.
00639 RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
00640                                                const RopePiece &R) {
00641   assert(Offset <= size() && "Invalid offset to insert!");
00642   if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
00643     return Leaf->insert(Offset, R);
00644   return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
00645 }
00646 
00647 /// erase - Remove NumBytes from this node at the specified offset.  We are
00648 /// guaranteed that there is a split at Offset.
00649 void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
00650   assert(Offset+NumBytes <= size() && "Invalid offset to erase!");
00651   if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
00652     return Leaf->erase(Offset, NumBytes);
00653   return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
00654 }
00655 
00656 
00657 //===----------------------------------------------------------------------===//
00658 // RopePieceBTreeIterator Implementation
00659 //===----------------------------------------------------------------------===//
00660 
00661 static const RopePieceBTreeLeaf *getCN(const void *P) {
00662   return static_cast<const RopePieceBTreeLeaf*>(P);
00663 }
00664 
00665 // begin iterator.
00666 RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
00667   const RopePieceBTreeNode *N = static_cast<const RopePieceBTreeNode*>(n);
00668 
00669   // Walk down the left side of the tree until we get to a leaf.
00670   while (const RopePieceBTreeInterior *IN = dyn_cast<RopePieceBTreeInterior>(N))
00671     N = IN->getChild(0);
00672 
00673   // We must have at least one leaf.
00674   CurNode = cast<RopePieceBTreeLeaf>(N);
00675 
00676   // If we found a leaf that happens to be empty, skip over it until we get
00677   // to something full.
00678   while (CurNode && getCN(CurNode)->getNumPieces() == 0)
00679     CurNode = getCN(CurNode)->getNextLeafInOrder();
00680 
00681   if (CurNode)
00682     CurPiece = &getCN(CurNode)->getPiece(0);
00683   else  // Empty tree, this is an end() iterator.
00684     CurPiece = nullptr;
00685   CurChar = 0;
00686 }
00687 
00688 void RopePieceBTreeIterator::MoveToNextPiece() {
00689   if (CurPiece != &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces()-1)) {
00690     CurChar = 0;
00691     ++CurPiece;
00692     return;
00693   }
00694 
00695   // Find the next non-empty leaf node.
00696   do
00697     CurNode = getCN(CurNode)->getNextLeafInOrder();
00698   while (CurNode && getCN(CurNode)->getNumPieces() == 0);
00699 
00700   if (CurNode)
00701     CurPiece = &getCN(CurNode)->getPiece(0);
00702   else // Hit end().
00703     CurPiece = nullptr;
00704   CurChar = 0;
00705 }
00706 
00707 //===----------------------------------------------------------------------===//
00708 // RopePieceBTree Implementation
00709 //===----------------------------------------------------------------------===//
00710 
00711 static RopePieceBTreeNode *getRoot(void *P) {
00712   return static_cast<RopePieceBTreeNode*>(P);
00713 }
00714 
00715 RopePieceBTree::RopePieceBTree() {
00716   Root = new RopePieceBTreeLeaf();
00717 }
00718 RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
00719   assert(RHS.empty() && "Can't copy non-empty tree yet");
00720   Root = new RopePieceBTreeLeaf();
00721 }
00722 RopePieceBTree::~RopePieceBTree() {
00723   getRoot(Root)->Destroy();
00724 }
00725 
00726 unsigned RopePieceBTree::size() const {
00727   return getRoot(Root)->size();
00728 }
00729 
00730 void RopePieceBTree::clear() {
00731   if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
00732     Leaf->clear();
00733   else {
00734     getRoot(Root)->Destroy();
00735     Root = new RopePieceBTreeLeaf();
00736   }
00737 }
00738 
00739 void RopePieceBTree::insert(unsigned Offset, const RopePiece &R) {
00740   // #1. Split at Offset.
00741   if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
00742     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
00743 
00744   // #2. Do the insertion.
00745   if (RopePieceBTreeNode *RHS = getRoot(Root)->insert(Offset, R))
00746     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
00747 }
00748 
00749 void RopePieceBTree::erase(unsigned Offset, unsigned NumBytes) {
00750   // #1. Split at Offset.
00751   if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
00752     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
00753 
00754   // #2. Do the erasing.
00755   getRoot(Root)->erase(Offset, NumBytes);
00756 }
00757 
00758 //===----------------------------------------------------------------------===//
00759 // RewriteRope Implementation
00760 //===----------------------------------------------------------------------===//
00761 
00762 /// MakeRopeString - This copies the specified byte range into some instance of
00763 /// RopeRefCountString, and return a RopePiece that represents it.  This uses
00764 /// the AllocBuffer object to aggregate requests for small strings into one
00765 /// allocation instead of doing tons of tiny allocations.
00766 RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
00767   unsigned Len = End-Start;
00768   assert(Len && "Zero length RopePiece is invalid!");
00769 
00770   // If we have space for this string in the current alloc buffer, use it.
00771   if (AllocOffs+Len <= AllocChunkSize) {
00772     memcpy(AllocBuffer->Data+AllocOffs, Start, Len);
00773     AllocOffs += Len;
00774     return RopePiece(AllocBuffer, AllocOffs-Len, AllocOffs);
00775   }
00776 
00777   // If we don't have enough room because this specific allocation is huge,
00778   // just allocate a new rope piece for it alone.
00779   if (Len > AllocChunkSize) {
00780     unsigned Size = End-Start+sizeof(RopeRefCountString)-1;
00781     RopeRefCountString *Res =
00782       reinterpret_cast<RopeRefCountString *>(new char[Size]);
00783     Res->RefCount = 0;
00784     memcpy(Res->Data, Start, End-Start);
00785     return RopePiece(Res, 0, End-Start);
00786   }
00787 
00788   // Otherwise, this was a small request but we just don't have space for it
00789   // Make a new chunk and share it with later allocations.
00790 
00791   unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
00792   RopeRefCountString *Res =
00793       reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
00794   Res->RefCount = 0;
00795   memcpy(Res->Data, Start, Len);
00796   AllocBuffer = Res;
00797   AllocOffs = Len;
00798 
00799   return RopePiece(AllocBuffer, 0, Len);
00800 }
00801 
00802