xref: /freebsd/contrib/llvm-project/llvm/lib/Support/RewriteRope.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===- RewriteRope.cpp - Rope specialized for rewriter --------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric //  This file implements the RewriteRope class, which is a powerful string.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "llvm/ADT/RewriteRope.h"
14*700637cbSDimitry Andric #include "llvm/Support/Casting.h"
15*700637cbSDimitry Andric #include <algorithm>
16*700637cbSDimitry Andric #include <cassert>
17*700637cbSDimitry Andric #include <cstring>
18*700637cbSDimitry Andric 
19*700637cbSDimitry Andric using namespace llvm;
20*700637cbSDimitry Andric 
21*700637cbSDimitry Andric /// RewriteRope is a "strong" string class, designed to make insertions and
22*700637cbSDimitry Andric /// deletions in the middle of the string nearly constant time (really, they are
23*700637cbSDimitry Andric /// O(log N), but with a very low constant factor).
24*700637cbSDimitry Andric ///
25*700637cbSDimitry Andric /// The implementation of this datastructure is a conceptual linear sequence of
26*700637cbSDimitry Andric /// RopePiece elements.  Each RopePiece represents a view on a separately
27*700637cbSDimitry Andric /// allocated and reference counted string.  This means that splitting a very
28*700637cbSDimitry Andric /// long string can be done in constant time by splitting a RopePiece that
29*700637cbSDimitry Andric /// references the whole string into two rope pieces that reference each half.
30*700637cbSDimitry Andric /// Once split, another string can be inserted in between the two halves by
31*700637cbSDimitry Andric /// inserting a RopePiece in between the two others.  All of this is very
32*700637cbSDimitry Andric /// inexpensive: it takes time proportional to the number of RopePieces, not the
33*700637cbSDimitry Andric /// length of the strings they represent.
34*700637cbSDimitry Andric ///
35*700637cbSDimitry Andric /// While a linear sequences of RopePieces is the conceptual model, the actual
36*700637cbSDimitry Andric /// implementation captures them in an adapted B+ Tree.  Using a B+ tree (which
37*700637cbSDimitry Andric /// is a tree that keeps the values in the leaves and has where each node
38*700637cbSDimitry Andric /// contains a reasonable number of pointers to children/values) allows us to
39*700637cbSDimitry Andric /// maintain efficient operation when the RewriteRope contains a *huge* number
40*700637cbSDimitry Andric /// of RopePieces.  The basic idea of the B+ Tree is that it allows us to find
41*700637cbSDimitry Andric /// the RopePiece corresponding to some offset very efficiently, and it
42*700637cbSDimitry Andric /// automatically balances itself on insertions of RopePieces (which can happen
43*700637cbSDimitry Andric /// for both insertions and erases of string ranges).
44*700637cbSDimitry Andric ///
45*700637cbSDimitry Andric /// The one wrinkle on the theory is that we don't attempt to keep the tree
46*700637cbSDimitry Andric /// properly balanced when erases happen.  Erases of string data can both insert
47*700637cbSDimitry Andric /// new RopePieces (e.g. when the middle of some other rope piece is deleted,
48*700637cbSDimitry Andric /// which results in two rope pieces, which is just like an insert) or it can
49*700637cbSDimitry Andric /// reduce the number of RopePieces maintained by the B+Tree.  In the case when
50*700637cbSDimitry Andric /// the number of RopePieces is reduced, we don't attempt to maintain the
51*700637cbSDimitry Andric /// standard 'invariant' that each node in the tree contains at least
52*700637cbSDimitry Andric /// 'WidthFactor' children/values.  For our use cases, this doesn't seem to
53*700637cbSDimitry Andric /// matter.
54*700637cbSDimitry Andric ///
55*700637cbSDimitry Andric /// The implementation below is primarily implemented in terms of three classes:
56*700637cbSDimitry Andric ///   RopePieceBTreeNode - Common base class for:
57*700637cbSDimitry Andric ///
58*700637cbSDimitry Andric ///     RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
59*700637cbSDimitry Andric ///          nodes.  This directly represents a chunk of the string with those
60*700637cbSDimitry Andric ///          RopePieces concatenated.
61*700637cbSDimitry Andric ///     RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
62*700637cbSDimitry Andric ///          up to '2*WidthFactor' other nodes in the tree.
63*700637cbSDimitry Andric 
64*700637cbSDimitry Andric namespace {
65*700637cbSDimitry Andric 
66*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
67*700637cbSDimitry Andric // RopePieceBTreeNode Class
68*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
69*700637cbSDimitry Andric 
70*700637cbSDimitry Andric /// RopePieceBTreeNode - Common base class of RopePieceBTreeLeaf and
71*700637cbSDimitry Andric /// RopePieceBTreeInterior.  This provides some 'virtual' dispatching methods
72*700637cbSDimitry Andric /// and a flag that determines which subclass the instance is.  Also
73*700637cbSDimitry Andric /// important, this node knows the full extend of the node, including any
74*700637cbSDimitry Andric /// children that it has.  This allows efficient skipping over entire subtrees
75*700637cbSDimitry Andric /// when looking for an offset in the BTree.
76*700637cbSDimitry Andric class RopePieceBTreeNode {
77*700637cbSDimitry Andric protected:
78*700637cbSDimitry Andric   /// WidthFactor - This controls the number of K/V slots held in the BTree:
79*700637cbSDimitry Andric   /// how wide it is.  Each level of the BTree is guaranteed to have at least
80*700637cbSDimitry Andric   /// 'WidthFactor' elements in it (either ropepieces or children), (except
81*700637cbSDimitry Andric   /// the root, which may have less) and may have at most 2*WidthFactor
82*700637cbSDimitry Andric   /// elements.
83*700637cbSDimitry Andric   enum { WidthFactor = 8 };
84*700637cbSDimitry Andric 
85*700637cbSDimitry Andric   /// Size - This is the number of bytes of file this node (including any
86*700637cbSDimitry Andric   /// potential children) covers.
87*700637cbSDimitry Andric   unsigned Size = 0;
88*700637cbSDimitry Andric 
89*700637cbSDimitry Andric   /// IsLeaf - True if this is an instance of RopePieceBTreeLeaf, false if it
90*700637cbSDimitry Andric   /// is an instance of RopePieceBTreeInterior.
91*700637cbSDimitry Andric   bool IsLeaf;
92*700637cbSDimitry Andric 
RopePieceBTreeNode(bool isLeaf)93*700637cbSDimitry Andric   RopePieceBTreeNode(bool isLeaf) : IsLeaf(isLeaf) {}
94*700637cbSDimitry Andric   ~RopePieceBTreeNode() = default;
95*700637cbSDimitry Andric 
96*700637cbSDimitry Andric public:
isLeaf() const97*700637cbSDimitry Andric   bool isLeaf() const { return IsLeaf; }
size() const98*700637cbSDimitry Andric   unsigned size() const { return Size; }
99*700637cbSDimitry Andric 
100*700637cbSDimitry Andric   void Destroy();
101*700637cbSDimitry Andric 
102*700637cbSDimitry Andric   /// split - Split the range containing the specified offset so that we are
103*700637cbSDimitry Andric   /// guaranteed that there is a place to do an insertion at the specified
104*700637cbSDimitry Andric   /// offset.  The offset is relative, so "0" is the start of the node.
105*700637cbSDimitry Andric   ///
106*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
107*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
108*700637cbSDimitry Andric   RopePieceBTreeNode *split(unsigned Offset);
109*700637cbSDimitry Andric 
110*700637cbSDimitry Andric   /// insert - Insert the specified ropepiece into this tree node at the
111*700637cbSDimitry Andric   /// specified offset.  The offset is relative, so "0" is the start of the
112*700637cbSDimitry Andric   /// node.
113*700637cbSDimitry Andric   ///
114*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
115*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
116*700637cbSDimitry Andric   RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
117*700637cbSDimitry Andric 
118*700637cbSDimitry Andric   /// erase - Remove NumBytes from this node at the specified offset.  We are
119*700637cbSDimitry Andric   /// guaranteed that there is a split at Offset.
120*700637cbSDimitry Andric   void erase(unsigned Offset, unsigned NumBytes);
121*700637cbSDimitry Andric };
122*700637cbSDimitry Andric 
123*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
124*700637cbSDimitry Andric // RopePieceBTreeLeaf Class
125*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
126*700637cbSDimitry Andric 
127*700637cbSDimitry Andric /// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
128*700637cbSDimitry Andric /// nodes.  This directly represents a chunk of the string with those
129*700637cbSDimitry Andric /// RopePieces concatenated.  Since this is a B+Tree, all values (in this case
130*700637cbSDimitry Andric /// instances of RopePiece) are stored in leaves like this.  To make iteration
131*700637cbSDimitry Andric /// over the leaves efficient, they maintain a singly linked list through the
132*700637cbSDimitry Andric /// NextLeaf field.  This allows the B+Tree forward iterator to be constant
133*700637cbSDimitry Andric /// time for all increments.
134*700637cbSDimitry Andric class RopePieceBTreeLeaf : public RopePieceBTreeNode {
135*700637cbSDimitry Andric   /// NumPieces - This holds the number of rope pieces currently active in the
136*700637cbSDimitry Andric   /// Pieces array.
137*700637cbSDimitry Andric   unsigned char NumPieces = 0;
138*700637cbSDimitry Andric 
139*700637cbSDimitry Andric   /// Pieces - This tracks the file chunks currently in this leaf.
140*700637cbSDimitry Andric   RopePiece Pieces[2 * WidthFactor];
141*700637cbSDimitry Andric 
142*700637cbSDimitry Andric   /// NextLeaf - This is a pointer to the next leaf in the tree, allowing
143*700637cbSDimitry Andric   /// efficient in-order forward iteration of the tree without traversal.
144*700637cbSDimitry Andric   RopePieceBTreeLeaf **PrevLeaf = nullptr;
145*700637cbSDimitry Andric   RopePieceBTreeLeaf *NextLeaf = nullptr;
146*700637cbSDimitry Andric 
147*700637cbSDimitry Andric public:
RopePieceBTreeLeaf()148*700637cbSDimitry Andric   RopePieceBTreeLeaf() : RopePieceBTreeNode(true) {}
149*700637cbSDimitry Andric 
~RopePieceBTreeLeaf()150*700637cbSDimitry Andric   ~RopePieceBTreeLeaf() {
151*700637cbSDimitry Andric     if (PrevLeaf || NextLeaf)
152*700637cbSDimitry Andric       removeFromLeafInOrder();
153*700637cbSDimitry Andric     clear();
154*700637cbSDimitry Andric   }
155*700637cbSDimitry Andric 
isFull() const156*700637cbSDimitry Andric   bool isFull() const { return NumPieces == 2 * WidthFactor; }
157*700637cbSDimitry Andric 
158*700637cbSDimitry Andric   /// clear - Remove all rope pieces from this leaf.
clear()159*700637cbSDimitry Andric   void clear() {
160*700637cbSDimitry Andric     while (NumPieces)
161*700637cbSDimitry Andric       Pieces[--NumPieces] = RopePiece();
162*700637cbSDimitry Andric     Size = 0;
163*700637cbSDimitry Andric   }
164*700637cbSDimitry Andric 
getNumPieces() const165*700637cbSDimitry Andric   unsigned getNumPieces() const { return NumPieces; }
166*700637cbSDimitry Andric 
getPiece(unsigned i) const167*700637cbSDimitry Andric   const RopePiece &getPiece(unsigned i) const {
168*700637cbSDimitry Andric     assert(i < getNumPieces() && "Invalid piece ID");
169*700637cbSDimitry Andric     return Pieces[i];
170*700637cbSDimitry Andric   }
171*700637cbSDimitry Andric 
getNextLeafInOrder() const172*700637cbSDimitry Andric   const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
173*700637cbSDimitry Andric 
insertAfterLeafInOrder(RopePieceBTreeLeaf * Node)174*700637cbSDimitry Andric   void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
175*700637cbSDimitry Andric     assert(!PrevLeaf && !NextLeaf && "Already in ordering");
176*700637cbSDimitry Andric 
177*700637cbSDimitry Andric     NextLeaf = Node->NextLeaf;
178*700637cbSDimitry Andric     if (NextLeaf)
179*700637cbSDimitry Andric       NextLeaf->PrevLeaf = &NextLeaf;
180*700637cbSDimitry Andric     PrevLeaf = &Node->NextLeaf;
181*700637cbSDimitry Andric     Node->NextLeaf = this;
182*700637cbSDimitry Andric   }
183*700637cbSDimitry Andric 
removeFromLeafInOrder()184*700637cbSDimitry Andric   void removeFromLeafInOrder() {
185*700637cbSDimitry Andric     if (PrevLeaf) {
186*700637cbSDimitry Andric       *PrevLeaf = NextLeaf;
187*700637cbSDimitry Andric       if (NextLeaf)
188*700637cbSDimitry Andric         NextLeaf->PrevLeaf = PrevLeaf;
189*700637cbSDimitry Andric     } else if (NextLeaf) {
190*700637cbSDimitry Andric       NextLeaf->PrevLeaf = nullptr;
191*700637cbSDimitry Andric     }
192*700637cbSDimitry Andric   }
193*700637cbSDimitry Andric 
194*700637cbSDimitry Andric   /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
195*700637cbSDimitry Andric   /// summing the size of all RopePieces.
FullRecomputeSizeLocally()196*700637cbSDimitry Andric   void FullRecomputeSizeLocally() {
197*700637cbSDimitry Andric     Size = 0;
198*700637cbSDimitry Andric     for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
199*700637cbSDimitry Andric       Size += getPiece(i).size();
200*700637cbSDimitry Andric   }
201*700637cbSDimitry Andric 
202*700637cbSDimitry Andric   /// split - Split the range containing the specified offset so that we are
203*700637cbSDimitry Andric   /// guaranteed that there is a place to do an insertion at the specified
204*700637cbSDimitry Andric   /// offset.  The offset is relative, so "0" is the start of the node.
205*700637cbSDimitry Andric   ///
206*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
207*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
208*700637cbSDimitry Andric   RopePieceBTreeNode *split(unsigned Offset);
209*700637cbSDimitry Andric 
210*700637cbSDimitry Andric   /// insert - Insert the specified ropepiece into this tree node at the
211*700637cbSDimitry Andric   /// specified offset.  The offset is relative, so "0" is the start of the
212*700637cbSDimitry Andric   /// node.
213*700637cbSDimitry Andric   ///
214*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
215*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
216*700637cbSDimitry Andric   RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
217*700637cbSDimitry Andric 
218*700637cbSDimitry Andric   /// erase - Remove NumBytes from this node at the specified offset.  We are
219*700637cbSDimitry Andric   /// guaranteed that there is a split at Offset.
220*700637cbSDimitry Andric   void erase(unsigned Offset, unsigned NumBytes);
221*700637cbSDimitry Andric 
classof(const RopePieceBTreeNode * N)222*700637cbSDimitry Andric   static bool classof(const RopePieceBTreeNode *N) { return N->isLeaf(); }
223*700637cbSDimitry Andric };
224*700637cbSDimitry Andric 
225*700637cbSDimitry Andric } // namespace
226*700637cbSDimitry Andric 
227*700637cbSDimitry Andric /// split - Split the range containing the specified offset so that we are
228*700637cbSDimitry Andric /// guaranteed that there is a place to do an insertion at the specified
229*700637cbSDimitry Andric /// offset.  The offset is relative, so "0" is the start of the node.
230*700637cbSDimitry Andric ///
231*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
232*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
split(unsigned Offset)233*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
234*700637cbSDimitry Andric   // Find the insertion point.  We are guaranteed that there is a split at the
235*700637cbSDimitry Andric   // specified offset so find it.
236*700637cbSDimitry Andric   if (Offset == 0 || Offset == size()) {
237*700637cbSDimitry Andric     // Fastpath for a common case.  There is already a splitpoint at the end.
238*700637cbSDimitry Andric     return nullptr;
239*700637cbSDimitry Andric   }
240*700637cbSDimitry Andric 
241*700637cbSDimitry Andric   // Find the piece that this offset lands in.
242*700637cbSDimitry Andric   unsigned PieceOffs = 0;
243*700637cbSDimitry Andric   unsigned i = 0;
244*700637cbSDimitry Andric   while (Offset >= PieceOffs + Pieces[i].size()) {
245*700637cbSDimitry Andric     PieceOffs += Pieces[i].size();
246*700637cbSDimitry Andric     ++i;
247*700637cbSDimitry Andric   }
248*700637cbSDimitry Andric 
249*700637cbSDimitry Andric   // If there is already a split point at the specified offset, just return
250*700637cbSDimitry Andric   // success.
251*700637cbSDimitry Andric   if (PieceOffs == Offset)
252*700637cbSDimitry Andric     return nullptr;
253*700637cbSDimitry Andric 
254*700637cbSDimitry Andric   // Otherwise, we need to split piece 'i' at Offset-PieceOffs.  Convert Offset
255*700637cbSDimitry Andric   // to being Piece relative.
256*700637cbSDimitry Andric   unsigned IntraPieceOffset = Offset - PieceOffs;
257*700637cbSDimitry Andric 
258*700637cbSDimitry Andric   // We do this by shrinking the RopePiece and then doing an insert of the tail.
259*700637cbSDimitry Andric   RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs + IntraPieceOffset,
260*700637cbSDimitry Andric                  Pieces[i].EndOffs);
261*700637cbSDimitry Andric   Size -= Pieces[i].size();
262*700637cbSDimitry Andric   Pieces[i].EndOffs = Pieces[i].StartOffs + IntraPieceOffset;
263*700637cbSDimitry Andric   Size += Pieces[i].size();
264*700637cbSDimitry Andric 
265*700637cbSDimitry Andric   return insert(Offset, Tail);
266*700637cbSDimitry Andric }
267*700637cbSDimitry Andric 
268*700637cbSDimitry Andric /// insert - Insert the specified RopePiece into this tree node at the
269*700637cbSDimitry Andric /// specified offset.  The offset is relative, so "0" is the start of the node.
270*700637cbSDimitry Andric ///
271*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
272*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
insert(unsigned Offset,const RopePiece & R)273*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
274*700637cbSDimitry Andric                                                const RopePiece &R) {
275*700637cbSDimitry Andric   // If this node is not full, insert the piece.
276*700637cbSDimitry Andric   if (!isFull()) {
277*700637cbSDimitry Andric     // Find the insertion point.  We are guaranteed that there is a split at the
278*700637cbSDimitry Andric     // specified offset so find it.
279*700637cbSDimitry Andric     unsigned i = 0, e = getNumPieces();
280*700637cbSDimitry Andric     if (Offset == size()) {
281*700637cbSDimitry Andric       // Fastpath for a common case.
282*700637cbSDimitry Andric       i = e;
283*700637cbSDimitry Andric     } else {
284*700637cbSDimitry Andric       unsigned SlotOffs = 0;
285*700637cbSDimitry Andric       for (; Offset > SlotOffs; ++i)
286*700637cbSDimitry Andric         SlotOffs += getPiece(i).size();
287*700637cbSDimitry Andric       assert(SlotOffs == Offset && "Split didn't occur before insertion!");
288*700637cbSDimitry Andric     }
289*700637cbSDimitry Andric 
290*700637cbSDimitry Andric     // For an insertion into a non-full leaf node, just insert the value in
291*700637cbSDimitry Andric     // its sorted position.  This requires moving later values over.
292*700637cbSDimitry Andric     for (; i != e; --e)
293*700637cbSDimitry Andric       Pieces[e] = Pieces[e - 1];
294*700637cbSDimitry Andric     Pieces[i] = R;
295*700637cbSDimitry Andric     ++NumPieces;
296*700637cbSDimitry Andric     Size += R.size();
297*700637cbSDimitry Andric     return nullptr;
298*700637cbSDimitry Andric   }
299*700637cbSDimitry Andric 
300*700637cbSDimitry Andric   // Otherwise, if this is leaf is full, split it in two halves.  Since this
301*700637cbSDimitry Andric   // node is full, it contains 2*WidthFactor values.  We move the first
302*700637cbSDimitry Andric   // 'WidthFactor' values to the LHS child (which we leave in this node) and
303*700637cbSDimitry Andric   // move the last 'WidthFactor' values into the RHS child.
304*700637cbSDimitry Andric 
305*700637cbSDimitry Andric   // Create the new node.
306*700637cbSDimitry Andric   RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
307*700637cbSDimitry Andric 
308*700637cbSDimitry Andric   // Move over the last 'WidthFactor' values from here to NewNode.
309*700637cbSDimitry Andric   std::copy(&Pieces[WidthFactor], &Pieces[2 * WidthFactor],
310*700637cbSDimitry Andric             &NewNode->Pieces[0]);
311*700637cbSDimitry Andric   // Replace old pieces with null RopePieces to drop refcounts.
312*700637cbSDimitry Andric   std::fill(&Pieces[WidthFactor], &Pieces[2 * WidthFactor], RopePiece());
313*700637cbSDimitry Andric 
314*700637cbSDimitry Andric   // Decrease the number of values in the two nodes.
315*700637cbSDimitry Andric   NewNode->NumPieces = NumPieces = WidthFactor;
316*700637cbSDimitry Andric 
317*700637cbSDimitry Andric   // Recompute the two nodes' size.
318*700637cbSDimitry Andric   NewNode->FullRecomputeSizeLocally();
319*700637cbSDimitry Andric   FullRecomputeSizeLocally();
320*700637cbSDimitry Andric 
321*700637cbSDimitry Andric   // Update the list of leaves.
322*700637cbSDimitry Andric   NewNode->insertAfterLeafInOrder(this);
323*700637cbSDimitry Andric 
324*700637cbSDimitry Andric   // These insertions can't fail.
325*700637cbSDimitry Andric   if (this->size() >= Offset)
326*700637cbSDimitry Andric     this->insert(Offset, R);
327*700637cbSDimitry Andric   else
328*700637cbSDimitry Andric     NewNode->insert(Offset - this->size(), R);
329*700637cbSDimitry Andric   return NewNode;
330*700637cbSDimitry Andric }
331*700637cbSDimitry Andric 
332*700637cbSDimitry Andric /// erase - Remove NumBytes from this node at the specified offset.  We are
333*700637cbSDimitry Andric /// guaranteed that there is a split at Offset.
erase(unsigned Offset,unsigned NumBytes)334*700637cbSDimitry Andric void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
335*700637cbSDimitry Andric   // Since we are guaranteed that there is a split at Offset, we start by
336*700637cbSDimitry Andric   // finding the Piece that starts there.
337*700637cbSDimitry Andric   unsigned PieceOffs = 0;
338*700637cbSDimitry Andric   unsigned i = 0;
339*700637cbSDimitry Andric   for (; Offset > PieceOffs; ++i)
340*700637cbSDimitry Andric     PieceOffs += getPiece(i).size();
341*700637cbSDimitry Andric   assert(PieceOffs == Offset && "Split didn't occur before erase!");
342*700637cbSDimitry Andric 
343*700637cbSDimitry Andric   unsigned StartPiece = i;
344*700637cbSDimitry Andric 
345*700637cbSDimitry Andric   // Figure out how many pieces completely cover 'NumBytes'.  We want to remove
346*700637cbSDimitry Andric   // all of them.
347*700637cbSDimitry Andric   for (; Offset + NumBytes > PieceOffs + getPiece(i).size(); ++i)
348*700637cbSDimitry Andric     PieceOffs += getPiece(i).size();
349*700637cbSDimitry Andric 
350*700637cbSDimitry Andric   // If we exactly include the last one, include it in the region to delete.
351*700637cbSDimitry Andric   if (Offset + NumBytes == PieceOffs + getPiece(i).size()) {
352*700637cbSDimitry Andric     PieceOffs += getPiece(i).size();
353*700637cbSDimitry Andric     ++i;
354*700637cbSDimitry Andric   }
355*700637cbSDimitry Andric 
356*700637cbSDimitry Andric   // If we completely cover some RopePieces, erase them now.
357*700637cbSDimitry Andric   if (i != StartPiece) {
358*700637cbSDimitry Andric     unsigned NumDeleted = i - StartPiece;
359*700637cbSDimitry Andric     for (; i != getNumPieces(); ++i)
360*700637cbSDimitry Andric       Pieces[i - NumDeleted] = Pieces[i];
361*700637cbSDimitry Andric 
362*700637cbSDimitry Andric     // Drop references to dead rope pieces.
363*700637cbSDimitry Andric     std::fill(&Pieces[getNumPieces() - NumDeleted], &Pieces[getNumPieces()],
364*700637cbSDimitry Andric               RopePiece());
365*700637cbSDimitry Andric     NumPieces -= NumDeleted;
366*700637cbSDimitry Andric 
367*700637cbSDimitry Andric     unsigned CoverBytes = PieceOffs - Offset;
368*700637cbSDimitry Andric     NumBytes -= CoverBytes;
369*700637cbSDimitry Andric     Size -= CoverBytes;
370*700637cbSDimitry Andric   }
371*700637cbSDimitry Andric 
372*700637cbSDimitry Andric   // If we completely removed some stuff, we could be done.
373*700637cbSDimitry Andric   if (NumBytes == 0)
374*700637cbSDimitry Andric     return;
375*700637cbSDimitry Andric 
376*700637cbSDimitry Andric   // Okay, now might be erasing part of some Piece.  If this is the case, then
377*700637cbSDimitry Andric   // move the start point of the piece.
378*700637cbSDimitry Andric   assert(getPiece(StartPiece).size() > NumBytes);
379*700637cbSDimitry Andric   Pieces[StartPiece].StartOffs += NumBytes;
380*700637cbSDimitry Andric 
381*700637cbSDimitry Andric   // The size of this node just shrunk by NumBytes.
382*700637cbSDimitry Andric   Size -= NumBytes;
383*700637cbSDimitry Andric }
384*700637cbSDimitry Andric 
385*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
386*700637cbSDimitry Andric // RopePieceBTreeInterior Class
387*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
388*700637cbSDimitry Andric 
389*700637cbSDimitry Andric namespace {
390*700637cbSDimitry Andric 
391*700637cbSDimitry Andric /// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
392*700637cbSDimitry Andric /// which holds up to 2*WidthFactor pointers to child nodes.
393*700637cbSDimitry Andric class RopePieceBTreeInterior : public RopePieceBTreeNode {
394*700637cbSDimitry Andric   /// NumChildren - This holds the number of children currently active in the
395*700637cbSDimitry Andric   /// Children array.
396*700637cbSDimitry Andric   unsigned char NumChildren = 0;
397*700637cbSDimitry Andric 
398*700637cbSDimitry Andric   RopePieceBTreeNode *Children[2 * WidthFactor];
399*700637cbSDimitry Andric 
400*700637cbSDimitry Andric public:
RopePieceBTreeInterior()401*700637cbSDimitry Andric   RopePieceBTreeInterior() : RopePieceBTreeNode(false) {}
402*700637cbSDimitry Andric 
RopePieceBTreeInterior(RopePieceBTreeNode * LHS,RopePieceBTreeNode * RHS)403*700637cbSDimitry Andric   RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
404*700637cbSDimitry Andric       : RopePieceBTreeNode(false) {
405*700637cbSDimitry Andric     Children[0] = LHS;
406*700637cbSDimitry Andric     Children[1] = RHS;
407*700637cbSDimitry Andric     NumChildren = 2;
408*700637cbSDimitry Andric     Size = LHS->size() + RHS->size();
409*700637cbSDimitry Andric   }
410*700637cbSDimitry Andric 
~RopePieceBTreeInterior()411*700637cbSDimitry Andric   ~RopePieceBTreeInterior() {
412*700637cbSDimitry Andric     for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
413*700637cbSDimitry Andric       Children[i]->Destroy();
414*700637cbSDimitry Andric   }
415*700637cbSDimitry Andric 
isFull() const416*700637cbSDimitry Andric   bool isFull() const { return NumChildren == 2 * WidthFactor; }
417*700637cbSDimitry Andric 
getNumChildren() const418*700637cbSDimitry Andric   unsigned getNumChildren() const { return NumChildren; }
419*700637cbSDimitry Andric 
getChild(unsigned i) const420*700637cbSDimitry Andric   const RopePieceBTreeNode *getChild(unsigned i) const {
421*700637cbSDimitry Andric     assert(i < NumChildren && "invalid child #");
422*700637cbSDimitry Andric     return Children[i];
423*700637cbSDimitry Andric   }
424*700637cbSDimitry Andric 
getChild(unsigned i)425*700637cbSDimitry Andric   RopePieceBTreeNode *getChild(unsigned i) {
426*700637cbSDimitry Andric     assert(i < NumChildren && "invalid child #");
427*700637cbSDimitry Andric     return Children[i];
428*700637cbSDimitry Andric   }
429*700637cbSDimitry Andric 
430*700637cbSDimitry Andric   /// FullRecomputeSizeLocally - Recompute the Size field of this node by
431*700637cbSDimitry Andric   /// summing up the sizes of the child nodes.
FullRecomputeSizeLocally()432*700637cbSDimitry Andric   void FullRecomputeSizeLocally() {
433*700637cbSDimitry Andric     Size = 0;
434*700637cbSDimitry Andric     for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
435*700637cbSDimitry Andric       Size += getChild(i)->size();
436*700637cbSDimitry Andric   }
437*700637cbSDimitry Andric 
438*700637cbSDimitry Andric   /// split - Split the range containing the specified offset so that we are
439*700637cbSDimitry Andric   /// guaranteed that there is a place to do an insertion at the specified
440*700637cbSDimitry Andric   /// offset.  The offset is relative, so "0" is the start of the node.
441*700637cbSDimitry Andric   ///
442*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
443*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
444*700637cbSDimitry Andric   RopePieceBTreeNode *split(unsigned Offset);
445*700637cbSDimitry Andric 
446*700637cbSDimitry Andric   /// insert - Insert the specified ropepiece into this tree node at the
447*700637cbSDimitry Andric   /// specified offset.  The offset is relative, so "0" is the start of the
448*700637cbSDimitry Andric   /// node.
449*700637cbSDimitry Andric   ///
450*700637cbSDimitry Andric   /// If there is no space in this subtree for the extra piece, the extra tree
451*700637cbSDimitry Andric   /// node is returned and must be inserted into a parent.
452*700637cbSDimitry Andric   RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
453*700637cbSDimitry Andric 
454*700637cbSDimitry Andric   /// HandleChildPiece - A child propagated an insertion result up to us.
455*700637cbSDimitry Andric   /// Insert the new child, and/or propagate the result further up the tree.
456*700637cbSDimitry Andric   RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
457*700637cbSDimitry Andric 
458*700637cbSDimitry Andric   /// erase - Remove NumBytes from this node at the specified offset.  We are
459*700637cbSDimitry Andric   /// guaranteed that there is a split at Offset.
460*700637cbSDimitry Andric   void erase(unsigned Offset, unsigned NumBytes);
461*700637cbSDimitry Andric 
classof(const RopePieceBTreeNode * N)462*700637cbSDimitry Andric   static bool classof(const RopePieceBTreeNode *N) { return !N->isLeaf(); }
463*700637cbSDimitry Andric };
464*700637cbSDimitry Andric 
465*700637cbSDimitry Andric } // namespace
466*700637cbSDimitry Andric 
467*700637cbSDimitry Andric /// split - Split the range containing the specified offset so that we are
468*700637cbSDimitry Andric /// guaranteed that there is a place to do an insertion at the specified
469*700637cbSDimitry Andric /// offset.  The offset is relative, so "0" is the start of the node.
470*700637cbSDimitry Andric ///
471*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
472*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
split(unsigned Offset)473*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
474*700637cbSDimitry Andric   // Figure out which child to split.
475*700637cbSDimitry Andric   if (Offset == 0 || Offset == size())
476*700637cbSDimitry Andric     return nullptr; // If we have an exact offset, we're already split.
477*700637cbSDimitry Andric 
478*700637cbSDimitry Andric   unsigned ChildOffset = 0;
479*700637cbSDimitry Andric   unsigned i = 0;
480*700637cbSDimitry Andric   for (; Offset >= ChildOffset + getChild(i)->size(); ++i)
481*700637cbSDimitry Andric     ChildOffset += getChild(i)->size();
482*700637cbSDimitry Andric 
483*700637cbSDimitry Andric   // If already split there, we're done.
484*700637cbSDimitry Andric   if (ChildOffset == Offset)
485*700637cbSDimitry Andric     return nullptr;
486*700637cbSDimitry Andric 
487*700637cbSDimitry Andric   // Otherwise, recursively split the child.
488*700637cbSDimitry Andric   if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset - ChildOffset))
489*700637cbSDimitry Andric     return HandleChildPiece(i, RHS);
490*700637cbSDimitry Andric   return nullptr; // Done!
491*700637cbSDimitry Andric }
492*700637cbSDimitry Andric 
493*700637cbSDimitry Andric /// insert - Insert the specified ropepiece into this tree node at the
494*700637cbSDimitry Andric /// specified offset.  The offset is relative, so "0" is the start of the
495*700637cbSDimitry Andric /// node.
496*700637cbSDimitry Andric ///
497*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
498*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
insert(unsigned Offset,const RopePiece & R)499*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset,
500*700637cbSDimitry Andric                                                    const RopePiece &R) {
501*700637cbSDimitry Andric   // Find the insertion point.  We are guaranteed that there is a split at the
502*700637cbSDimitry Andric   // specified offset so find it.
503*700637cbSDimitry Andric   unsigned i = 0, e = getNumChildren();
504*700637cbSDimitry Andric 
505*700637cbSDimitry Andric   unsigned ChildOffs = 0;
506*700637cbSDimitry Andric   if (Offset == size()) {
507*700637cbSDimitry Andric     // Fastpath for a common case.  Insert at end of last child.
508*700637cbSDimitry Andric     i = e - 1;
509*700637cbSDimitry Andric     ChildOffs = size() - getChild(i)->size();
510*700637cbSDimitry Andric   } else {
511*700637cbSDimitry Andric     for (; Offset > ChildOffs + getChild(i)->size(); ++i)
512*700637cbSDimitry Andric       ChildOffs += getChild(i)->size();
513*700637cbSDimitry Andric   }
514*700637cbSDimitry Andric 
515*700637cbSDimitry Andric   Size += R.size();
516*700637cbSDimitry Andric 
517*700637cbSDimitry Andric   // Insert at the end of this child.
518*700637cbSDimitry Andric   if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset - ChildOffs, R))
519*700637cbSDimitry Andric     return HandleChildPiece(i, RHS);
520*700637cbSDimitry Andric 
521*700637cbSDimitry Andric   return nullptr;
522*700637cbSDimitry Andric }
523*700637cbSDimitry Andric 
524*700637cbSDimitry Andric /// HandleChildPiece - A child propagated an insertion result up to us.
525*700637cbSDimitry Andric /// Insert the new child, and/or propagate the result further up the tree.
526*700637cbSDimitry Andric RopePieceBTreeNode *
HandleChildPiece(unsigned i,RopePieceBTreeNode * RHS)527*700637cbSDimitry Andric RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) {
528*700637cbSDimitry Andric   // Otherwise the child propagated a subtree up to us as a new child.  See if
529*700637cbSDimitry Andric   // we have space for it here.
530*700637cbSDimitry Andric   if (!isFull()) {
531*700637cbSDimitry Andric     // Insert RHS after child 'i'.
532*700637cbSDimitry Andric     if (i + 1 != getNumChildren())
533*700637cbSDimitry Andric       memmove(&Children[i + 2], &Children[i + 1],
534*700637cbSDimitry Andric               (getNumChildren() - i - 1) * sizeof(Children[0]));
535*700637cbSDimitry Andric     Children[i + 1] = RHS;
536*700637cbSDimitry Andric     ++NumChildren;
537*700637cbSDimitry Andric     return nullptr;
538*700637cbSDimitry Andric   }
539*700637cbSDimitry Andric 
540*700637cbSDimitry Andric   // Okay, this node is full.  Split it in half, moving WidthFactor children to
541*700637cbSDimitry Andric   // a newly allocated interior node.
542*700637cbSDimitry Andric 
543*700637cbSDimitry Andric   // Create the new node.
544*700637cbSDimitry Andric   RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior();
545*700637cbSDimitry Andric 
546*700637cbSDimitry Andric   // Move over the last 'WidthFactor' values from here to NewNode.
547*700637cbSDimitry Andric   memcpy(&NewNode->Children[0], &Children[WidthFactor],
548*700637cbSDimitry Andric          WidthFactor * sizeof(Children[0]));
549*700637cbSDimitry Andric 
550*700637cbSDimitry Andric   // Decrease the number of values in the two nodes.
551*700637cbSDimitry Andric   NewNode->NumChildren = NumChildren = WidthFactor;
552*700637cbSDimitry Andric 
553*700637cbSDimitry Andric   // Finally, insert the two new children in the side the can (now) hold them.
554*700637cbSDimitry Andric   // These insertions can't fail.
555*700637cbSDimitry Andric   if (i < WidthFactor)
556*700637cbSDimitry Andric     this->HandleChildPiece(i, RHS);
557*700637cbSDimitry Andric   else
558*700637cbSDimitry Andric     NewNode->HandleChildPiece(i - WidthFactor, RHS);
559*700637cbSDimitry Andric 
560*700637cbSDimitry Andric   // Recompute the two nodes' size.
561*700637cbSDimitry Andric   NewNode->FullRecomputeSizeLocally();
562*700637cbSDimitry Andric   FullRecomputeSizeLocally();
563*700637cbSDimitry Andric   return NewNode;
564*700637cbSDimitry Andric }
565*700637cbSDimitry Andric 
566*700637cbSDimitry Andric /// erase - Remove NumBytes from this node at the specified offset.  We are
567*700637cbSDimitry Andric /// guaranteed that there is a split at Offset.
erase(unsigned Offset,unsigned NumBytes)568*700637cbSDimitry Andric void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
569*700637cbSDimitry Andric   // This will shrink this node by NumBytes.
570*700637cbSDimitry Andric   Size -= NumBytes;
571*700637cbSDimitry Andric 
572*700637cbSDimitry Andric   // Find the first child that overlaps with Offset.
573*700637cbSDimitry Andric   unsigned i = 0;
574*700637cbSDimitry Andric   for (; Offset >= getChild(i)->size(); ++i)
575*700637cbSDimitry Andric     Offset -= getChild(i)->size();
576*700637cbSDimitry Andric 
577*700637cbSDimitry Andric   // Propagate the delete request into overlapping children, or completely
578*700637cbSDimitry Andric   // delete the children as appropriate.
579*700637cbSDimitry Andric   while (NumBytes) {
580*700637cbSDimitry Andric     RopePieceBTreeNode *CurChild = getChild(i);
581*700637cbSDimitry Andric 
582*700637cbSDimitry Andric     // If we are deleting something contained entirely in the child, pass on the
583*700637cbSDimitry Andric     // request.
584*700637cbSDimitry Andric     if (Offset + NumBytes < CurChild->size()) {
585*700637cbSDimitry Andric       CurChild->erase(Offset, NumBytes);
586*700637cbSDimitry Andric       return;
587*700637cbSDimitry Andric     }
588*700637cbSDimitry Andric 
589*700637cbSDimitry Andric     // If this deletion request starts somewhere in the middle of the child, it
590*700637cbSDimitry Andric     // must be deleting to the end of the child.
591*700637cbSDimitry Andric     if (Offset) {
592*700637cbSDimitry Andric       unsigned BytesFromChild = CurChild->size() - Offset;
593*700637cbSDimitry Andric       CurChild->erase(Offset, BytesFromChild);
594*700637cbSDimitry Andric       NumBytes -= BytesFromChild;
595*700637cbSDimitry Andric       // Start at the beginning of the next child.
596*700637cbSDimitry Andric       Offset = 0;
597*700637cbSDimitry Andric       ++i;
598*700637cbSDimitry Andric       continue;
599*700637cbSDimitry Andric     }
600*700637cbSDimitry Andric 
601*700637cbSDimitry Andric     // If the deletion request completely covers the child, delete it and move
602*700637cbSDimitry Andric     // the rest down.
603*700637cbSDimitry Andric     NumBytes -= CurChild->size();
604*700637cbSDimitry Andric     CurChild->Destroy();
605*700637cbSDimitry Andric     --NumChildren;
606*700637cbSDimitry Andric     if (i != getNumChildren())
607*700637cbSDimitry Andric       memmove(&Children[i], &Children[i + 1],
608*700637cbSDimitry Andric               (getNumChildren() - i) * sizeof(Children[0]));
609*700637cbSDimitry Andric   }
610*700637cbSDimitry Andric }
611*700637cbSDimitry Andric 
612*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
613*700637cbSDimitry Andric // RopePieceBTreeNode Implementation
614*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
615*700637cbSDimitry Andric 
Destroy()616*700637cbSDimitry Andric void RopePieceBTreeNode::Destroy() {
617*700637cbSDimitry Andric   if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
618*700637cbSDimitry Andric     delete Leaf;
619*700637cbSDimitry Andric   else
620*700637cbSDimitry Andric     delete cast<RopePieceBTreeInterior>(this);
621*700637cbSDimitry Andric }
622*700637cbSDimitry Andric 
623*700637cbSDimitry Andric /// split - Split the range containing the specified offset so that we are
624*700637cbSDimitry Andric /// guaranteed that there is a place to do an insertion at the specified
625*700637cbSDimitry Andric /// offset.  The offset is relative, so "0" is the start of the node.
626*700637cbSDimitry Andric ///
627*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
628*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
split(unsigned Offset)629*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
630*700637cbSDimitry Andric   assert(Offset <= size() && "Invalid offset to split!");
631*700637cbSDimitry Andric   if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
632*700637cbSDimitry Andric     return Leaf->split(Offset);
633*700637cbSDimitry Andric   return cast<RopePieceBTreeInterior>(this)->split(Offset);
634*700637cbSDimitry Andric }
635*700637cbSDimitry Andric 
636*700637cbSDimitry Andric /// insert - Insert the specified ropepiece into this tree node at the
637*700637cbSDimitry Andric /// specified offset.  The offset is relative, so "0" is the start of the
638*700637cbSDimitry Andric /// node.
639*700637cbSDimitry Andric ///
640*700637cbSDimitry Andric /// If there is no space in this subtree for the extra piece, the extra tree
641*700637cbSDimitry Andric /// node is returned and must be inserted into a parent.
insert(unsigned Offset,const RopePiece & R)642*700637cbSDimitry Andric RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
643*700637cbSDimitry Andric                                                const RopePiece &R) {
644*700637cbSDimitry Andric   assert(Offset <= size() && "Invalid offset to insert!");
645*700637cbSDimitry Andric   if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
646*700637cbSDimitry Andric     return Leaf->insert(Offset, R);
647*700637cbSDimitry Andric   return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
648*700637cbSDimitry Andric }
649*700637cbSDimitry Andric 
650*700637cbSDimitry Andric /// erase - Remove NumBytes from this node at the specified offset.  We are
651*700637cbSDimitry Andric /// guaranteed that there is a split at Offset.
erase(unsigned Offset,unsigned NumBytes)652*700637cbSDimitry Andric void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
653*700637cbSDimitry Andric   assert(Offset + NumBytes <= size() && "Invalid offset to erase!");
654*700637cbSDimitry Andric   if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
655*700637cbSDimitry Andric     return Leaf->erase(Offset, NumBytes);
656*700637cbSDimitry Andric   return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
657*700637cbSDimitry Andric }
658*700637cbSDimitry Andric 
659*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
660*700637cbSDimitry Andric // RopePieceBTreeIterator Implementation
661*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
662*700637cbSDimitry Andric 
getCN(const void * P)663*700637cbSDimitry Andric static const RopePieceBTreeLeaf *getCN(const void *P) {
664*700637cbSDimitry Andric   return static_cast<const RopePieceBTreeLeaf *>(P);
665*700637cbSDimitry Andric }
666*700637cbSDimitry Andric 
667*700637cbSDimitry Andric // begin iterator.
RopePieceBTreeIterator(const void * n)668*700637cbSDimitry Andric RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
669*700637cbSDimitry Andric   const auto *N = static_cast<const RopePieceBTreeNode *>(n);
670*700637cbSDimitry Andric 
671*700637cbSDimitry Andric   // Walk down the left side of the tree until we get to a leaf.
672*700637cbSDimitry Andric   while (const auto *IN = dyn_cast<RopePieceBTreeInterior>(N))
673*700637cbSDimitry Andric     N = IN->getChild(0);
674*700637cbSDimitry Andric 
675*700637cbSDimitry Andric   // We must have at least one leaf.
676*700637cbSDimitry Andric   CurNode = cast<RopePieceBTreeLeaf>(N);
677*700637cbSDimitry Andric 
678*700637cbSDimitry Andric   // If we found a leaf that happens to be empty, skip over it until we get
679*700637cbSDimitry Andric   // to something full.
680*700637cbSDimitry Andric   while (CurNode && getCN(CurNode)->getNumPieces() == 0)
681*700637cbSDimitry Andric     CurNode = getCN(CurNode)->getNextLeafInOrder();
682*700637cbSDimitry Andric 
683*700637cbSDimitry Andric   if (CurNode)
684*700637cbSDimitry Andric     CurPiece = &getCN(CurNode)->getPiece(0);
685*700637cbSDimitry Andric   else // Empty tree, this is an end() iterator.
686*700637cbSDimitry Andric     CurPiece = nullptr;
687*700637cbSDimitry Andric   CurChar = 0;
688*700637cbSDimitry Andric }
689*700637cbSDimitry Andric 
MoveToNextPiece()690*700637cbSDimitry Andric void RopePieceBTreeIterator::MoveToNextPiece() {
691*700637cbSDimitry Andric   if (CurPiece !=
692*700637cbSDimitry Andric       &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces() - 1)) {
693*700637cbSDimitry Andric     CurChar = 0;
694*700637cbSDimitry Andric     ++CurPiece;
695*700637cbSDimitry Andric     return;
696*700637cbSDimitry Andric   }
697*700637cbSDimitry Andric 
698*700637cbSDimitry Andric   // Find the next non-empty leaf node.
699*700637cbSDimitry Andric   do
700*700637cbSDimitry Andric     CurNode = getCN(CurNode)->getNextLeafInOrder();
701*700637cbSDimitry Andric   while (CurNode && getCN(CurNode)->getNumPieces() == 0);
702*700637cbSDimitry Andric 
703*700637cbSDimitry Andric   if (CurNode)
704*700637cbSDimitry Andric     CurPiece = &getCN(CurNode)->getPiece(0);
705*700637cbSDimitry Andric   else // Hit end().
706*700637cbSDimitry Andric     CurPiece = nullptr;
707*700637cbSDimitry Andric   CurChar = 0;
708*700637cbSDimitry Andric }
709*700637cbSDimitry Andric 
710*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
711*700637cbSDimitry Andric // RopePieceBTree Implementation
712*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
713*700637cbSDimitry Andric 
getRoot(void * P)714*700637cbSDimitry Andric static RopePieceBTreeNode *getRoot(void *P) {
715*700637cbSDimitry Andric   return static_cast<RopePieceBTreeNode *>(P);
716*700637cbSDimitry Andric }
717*700637cbSDimitry Andric 
RopePieceBTree()718*700637cbSDimitry Andric RopePieceBTree::RopePieceBTree() { Root = new RopePieceBTreeLeaf(); }
719*700637cbSDimitry Andric 
RopePieceBTree(const RopePieceBTree & RHS)720*700637cbSDimitry Andric RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
721*700637cbSDimitry Andric   assert(RHS.empty() && "Can't copy non-empty tree yet");
722*700637cbSDimitry Andric   Root = new RopePieceBTreeLeaf();
723*700637cbSDimitry Andric }
724*700637cbSDimitry Andric 
~RopePieceBTree()725*700637cbSDimitry Andric RopePieceBTree::~RopePieceBTree() { getRoot(Root)->Destroy(); }
726*700637cbSDimitry Andric 
size() const727*700637cbSDimitry Andric unsigned RopePieceBTree::size() const { return getRoot(Root)->size(); }
728*700637cbSDimitry Andric 
clear()729*700637cbSDimitry Andric void RopePieceBTree::clear() {
730*700637cbSDimitry Andric   if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
731*700637cbSDimitry Andric     Leaf->clear();
732*700637cbSDimitry Andric   else {
733*700637cbSDimitry Andric     getRoot(Root)->Destroy();
734*700637cbSDimitry Andric     Root = new RopePieceBTreeLeaf();
735*700637cbSDimitry Andric   }
736*700637cbSDimitry Andric }
737*700637cbSDimitry Andric 
insert(unsigned Offset,const RopePiece & R)738*700637cbSDimitry Andric void RopePieceBTree::insert(unsigned Offset, const RopePiece &R) {
739*700637cbSDimitry Andric   // #1. Split at Offset.
740*700637cbSDimitry Andric   if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
741*700637cbSDimitry Andric     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
742*700637cbSDimitry Andric 
743*700637cbSDimitry Andric   // #2. Do the insertion.
744*700637cbSDimitry Andric   if (RopePieceBTreeNode *RHS = getRoot(Root)->insert(Offset, R))
745*700637cbSDimitry Andric     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
746*700637cbSDimitry Andric }
747*700637cbSDimitry Andric 
erase(unsigned Offset,unsigned NumBytes)748*700637cbSDimitry Andric void RopePieceBTree::erase(unsigned Offset, unsigned NumBytes) {
749*700637cbSDimitry Andric   // #1. Split at Offset.
750*700637cbSDimitry Andric   if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
751*700637cbSDimitry Andric     Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
752*700637cbSDimitry Andric 
753*700637cbSDimitry Andric   // #2. Do the erasing.
754*700637cbSDimitry Andric   getRoot(Root)->erase(Offset, NumBytes);
755*700637cbSDimitry Andric }
756*700637cbSDimitry Andric 
757*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
758*700637cbSDimitry Andric // RewriteRope Implementation
759*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
760*700637cbSDimitry Andric 
761*700637cbSDimitry Andric /// MakeRopeString - This copies the specified byte range into some instance of
762*700637cbSDimitry Andric /// RopeRefCountString, and return a RopePiece that represents it.  This uses
763*700637cbSDimitry Andric /// the AllocBuffer object to aggregate requests for small strings into one
764*700637cbSDimitry Andric /// allocation instead of doing tons of tiny allocations.
MakeRopeString(const char * Start,const char * End)765*700637cbSDimitry Andric RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
766*700637cbSDimitry Andric   unsigned Len = End - Start;
767*700637cbSDimitry Andric   assert(Len && "Zero length RopePiece is invalid!");
768*700637cbSDimitry Andric 
769*700637cbSDimitry Andric   // If we have space for this string in the current alloc buffer, use it.
770*700637cbSDimitry Andric   if (AllocOffs + Len <= AllocChunkSize) {
771*700637cbSDimitry Andric     memcpy(AllocBuffer->Data + AllocOffs, Start, Len);
772*700637cbSDimitry Andric     AllocOffs += Len;
773*700637cbSDimitry Andric     return RopePiece(AllocBuffer, AllocOffs - Len, AllocOffs);
774*700637cbSDimitry Andric   }
775*700637cbSDimitry Andric 
776*700637cbSDimitry Andric   // If we don't have enough room because this specific allocation is huge,
777*700637cbSDimitry Andric   // just allocate a new rope piece for it alone.
778*700637cbSDimitry Andric   if (Len > AllocChunkSize) {
779*700637cbSDimitry Andric     unsigned Size = End - Start + sizeof(RopeRefCountString) - 1;
780*700637cbSDimitry Andric     auto *Res = reinterpret_cast<RopeRefCountString *>(new char[Size]);
781*700637cbSDimitry Andric     Res->RefCount = 0;
782*700637cbSDimitry Andric     memcpy(Res->Data, Start, End - Start);
783*700637cbSDimitry Andric     return RopePiece(Res, 0, End - Start);
784*700637cbSDimitry Andric   }
785*700637cbSDimitry Andric 
786*700637cbSDimitry Andric   // Otherwise, this was a small request but we just don't have space for it
787*700637cbSDimitry Andric   // Make a new chunk and share it with later allocations.
788*700637cbSDimitry Andric 
789*700637cbSDimitry Andric   unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
790*700637cbSDimitry Andric   auto *Res = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
791*700637cbSDimitry Andric   Res->RefCount = 0;
792*700637cbSDimitry Andric   memcpy(Res->Data, Start, Len);
793*700637cbSDimitry Andric   AllocBuffer = Res;
794*700637cbSDimitry Andric   AllocOffs = Len;
795*700637cbSDimitry Andric 
796*700637cbSDimitry Andric   return RopePiece(AllocBuffer, 0, Len);
797*700637cbSDimitry Andric }
798