xref: /minix3/external/bsd/llvm/dist/clang/lib/Rewrite/DeltaTree.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc //===--- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ----------------===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc //                     The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // This file implements the DeltaTree and related classes.
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
13*0a6a1f1dSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc #include "clang/Rewrite/Core/DeltaTree.h"
15*0a6a1f1dSLionel Sambuc #include "clang/Basic/LLVM.h"
16*0a6a1f1dSLionel Sambuc #include <cstdio>
17*0a6a1f1dSLionel Sambuc #include <cstring>
18*0a6a1f1dSLionel Sambuc using namespace clang;
19*0a6a1f1dSLionel Sambuc 
20*0a6a1f1dSLionel Sambuc /// The DeltaTree class is a multiway search tree (BTree) structure with some
21*0a6a1f1dSLionel Sambuc /// fancy features.  B-Trees are generally more memory and cache efficient
22*0a6a1f1dSLionel Sambuc /// than binary trees, because they store multiple keys/values in each node.
23*0a6a1f1dSLionel Sambuc ///
24*0a6a1f1dSLionel Sambuc /// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
25*0a6a1f1dSLionel Sambuc /// fast lookup by FileIndex.  However, an added (important) bonus is that it
26*0a6a1f1dSLionel Sambuc /// can also efficiently tell us the full accumulated delta for a specific
27*0a6a1f1dSLionel Sambuc /// file offset as well, without traversing the whole tree.
28*0a6a1f1dSLionel Sambuc ///
29*0a6a1f1dSLionel Sambuc /// The nodes of the tree are made up of instances of two classes:
30*0a6a1f1dSLionel Sambuc /// DeltaTreeNode and DeltaTreeInteriorNode.  The later subclasses the
31*0a6a1f1dSLionel Sambuc /// former and adds children pointers.  Each node knows the full delta of all
32*0a6a1f1dSLionel Sambuc /// entries (recursively) contained inside of it, which allows us to get the
33*0a6a1f1dSLionel Sambuc /// full delta implied by a whole subtree in constant time.
34*0a6a1f1dSLionel Sambuc 
35*0a6a1f1dSLionel Sambuc namespace {
36*0a6a1f1dSLionel Sambuc   /// SourceDelta - As code in the original input buffer is added and deleted,
37*0a6a1f1dSLionel Sambuc   /// SourceDelta records are used to keep track of how the input SourceLocation
38*0a6a1f1dSLionel Sambuc   /// object is mapped into the output buffer.
39*0a6a1f1dSLionel Sambuc   struct SourceDelta {
40*0a6a1f1dSLionel Sambuc     unsigned FileLoc;
41*0a6a1f1dSLionel Sambuc     int Delta;
42*0a6a1f1dSLionel Sambuc 
get__anon4129d9b80111::SourceDelta43*0a6a1f1dSLionel Sambuc     static SourceDelta get(unsigned Loc, int D) {
44*0a6a1f1dSLionel Sambuc       SourceDelta Delta;
45*0a6a1f1dSLionel Sambuc       Delta.FileLoc = Loc;
46*0a6a1f1dSLionel Sambuc       Delta.Delta = D;
47*0a6a1f1dSLionel Sambuc       return Delta;
48*0a6a1f1dSLionel Sambuc     }
49*0a6a1f1dSLionel Sambuc   };
50*0a6a1f1dSLionel Sambuc 
51*0a6a1f1dSLionel Sambuc   /// DeltaTreeNode - The common part of all nodes.
52*0a6a1f1dSLionel Sambuc   ///
53*0a6a1f1dSLionel Sambuc   class DeltaTreeNode {
54*0a6a1f1dSLionel Sambuc   public:
55*0a6a1f1dSLionel Sambuc     struct InsertResult {
56*0a6a1f1dSLionel Sambuc       DeltaTreeNode *LHS, *RHS;
57*0a6a1f1dSLionel Sambuc       SourceDelta Split;
58*0a6a1f1dSLionel Sambuc     };
59*0a6a1f1dSLionel Sambuc 
60*0a6a1f1dSLionel Sambuc   private:
61*0a6a1f1dSLionel Sambuc     friend class DeltaTreeInteriorNode;
62*0a6a1f1dSLionel Sambuc 
63*0a6a1f1dSLionel Sambuc     /// WidthFactor - This controls the number of K/V slots held in the BTree:
64*0a6a1f1dSLionel Sambuc     /// how wide it is.  Each level of the BTree is guaranteed to have at least
65*0a6a1f1dSLionel Sambuc     /// WidthFactor-1 K/V pairs (except the root) and may have at most
66*0a6a1f1dSLionel Sambuc     /// 2*WidthFactor-1 K/V pairs.
67*0a6a1f1dSLionel Sambuc     enum { WidthFactor = 8 };
68*0a6a1f1dSLionel Sambuc 
69*0a6a1f1dSLionel Sambuc     /// Values - This tracks the SourceDelta's currently in this node.
70*0a6a1f1dSLionel Sambuc     ///
71*0a6a1f1dSLionel Sambuc     SourceDelta Values[2*WidthFactor-1];
72*0a6a1f1dSLionel Sambuc 
73*0a6a1f1dSLionel Sambuc     /// NumValuesUsed - This tracks the number of values this node currently
74*0a6a1f1dSLionel Sambuc     /// holds.
75*0a6a1f1dSLionel Sambuc     unsigned char NumValuesUsed;
76*0a6a1f1dSLionel Sambuc 
77*0a6a1f1dSLionel Sambuc     /// IsLeaf - This is true if this is a leaf of the btree.  If false, this is
78*0a6a1f1dSLionel Sambuc     /// an interior node, and is actually an instance of DeltaTreeInteriorNode.
79*0a6a1f1dSLionel Sambuc     bool IsLeaf;
80*0a6a1f1dSLionel Sambuc 
81*0a6a1f1dSLionel Sambuc     /// FullDelta - This is the full delta of all the values in this node and
82*0a6a1f1dSLionel Sambuc     /// all children nodes.
83*0a6a1f1dSLionel Sambuc     int FullDelta;
84*0a6a1f1dSLionel Sambuc   public:
DeltaTreeNode(bool isLeaf=true)85*0a6a1f1dSLionel Sambuc     DeltaTreeNode(bool isLeaf = true)
86*0a6a1f1dSLionel Sambuc       : NumValuesUsed(0), IsLeaf(isLeaf), FullDelta(0) {}
87*0a6a1f1dSLionel Sambuc 
isLeaf() const88*0a6a1f1dSLionel Sambuc     bool isLeaf() const { return IsLeaf; }
getFullDelta() const89*0a6a1f1dSLionel Sambuc     int getFullDelta() const { return FullDelta; }
isFull() const90*0a6a1f1dSLionel Sambuc     bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
91*0a6a1f1dSLionel Sambuc 
getNumValuesUsed() const92*0a6a1f1dSLionel Sambuc     unsigned getNumValuesUsed() const { return NumValuesUsed; }
getValue(unsigned i) const93*0a6a1f1dSLionel Sambuc     const SourceDelta &getValue(unsigned i) const {
94*0a6a1f1dSLionel Sambuc       assert(i < NumValuesUsed && "Invalid value #");
95*0a6a1f1dSLionel Sambuc       return Values[i];
96*0a6a1f1dSLionel Sambuc     }
getValue(unsigned i)97*0a6a1f1dSLionel Sambuc     SourceDelta &getValue(unsigned i) {
98*0a6a1f1dSLionel Sambuc       assert(i < NumValuesUsed && "Invalid value #");
99*0a6a1f1dSLionel Sambuc       return Values[i];
100*0a6a1f1dSLionel Sambuc     }
101*0a6a1f1dSLionel Sambuc 
102*0a6a1f1dSLionel Sambuc     /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
103*0a6a1f1dSLionel Sambuc     /// this node.  If insertion is easy, do it and return false.  Otherwise,
104*0a6a1f1dSLionel Sambuc     /// split the node, populate InsertRes with info about the split, and return
105*0a6a1f1dSLionel Sambuc     /// true.
106*0a6a1f1dSLionel Sambuc     bool DoInsertion(unsigned FileIndex, int Delta, InsertResult *InsertRes);
107*0a6a1f1dSLionel Sambuc 
108*0a6a1f1dSLionel Sambuc     void DoSplit(InsertResult &InsertRes);
109*0a6a1f1dSLionel Sambuc 
110*0a6a1f1dSLionel Sambuc 
111*0a6a1f1dSLionel Sambuc     /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
112*0a6a1f1dSLionel Sambuc     /// local walk over our contained deltas.
113*0a6a1f1dSLionel Sambuc     void RecomputeFullDeltaLocally();
114*0a6a1f1dSLionel Sambuc 
115*0a6a1f1dSLionel Sambuc     void Destroy();
116*0a6a1f1dSLionel Sambuc   };
117*0a6a1f1dSLionel Sambuc } // end anonymous namespace
118*0a6a1f1dSLionel Sambuc 
119*0a6a1f1dSLionel Sambuc namespace {
120*0a6a1f1dSLionel Sambuc   /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
121*0a6a1f1dSLionel Sambuc   /// This class tracks them.
122*0a6a1f1dSLionel Sambuc   class DeltaTreeInteriorNode : public DeltaTreeNode {
123*0a6a1f1dSLionel Sambuc     DeltaTreeNode *Children[2*WidthFactor];
~DeltaTreeInteriorNode()124*0a6a1f1dSLionel Sambuc     ~DeltaTreeInteriorNode() {
125*0a6a1f1dSLionel Sambuc       for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
126*0a6a1f1dSLionel Sambuc         Children[i]->Destroy();
127*0a6a1f1dSLionel Sambuc     }
128*0a6a1f1dSLionel Sambuc     friend class DeltaTreeNode;
129*0a6a1f1dSLionel Sambuc   public:
DeltaTreeInteriorNode()130*0a6a1f1dSLionel Sambuc     DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
131*0a6a1f1dSLionel Sambuc 
DeltaTreeInteriorNode(const InsertResult & IR)132*0a6a1f1dSLionel Sambuc     DeltaTreeInteriorNode(const InsertResult &IR)
133*0a6a1f1dSLionel Sambuc       : DeltaTreeNode(false /*nonleaf*/) {
134*0a6a1f1dSLionel Sambuc       Children[0] = IR.LHS;
135*0a6a1f1dSLionel Sambuc       Children[1] = IR.RHS;
136*0a6a1f1dSLionel Sambuc       Values[0] = IR.Split;
137*0a6a1f1dSLionel Sambuc       FullDelta = IR.LHS->getFullDelta()+IR.RHS->getFullDelta()+IR.Split.Delta;
138*0a6a1f1dSLionel Sambuc       NumValuesUsed = 1;
139*0a6a1f1dSLionel Sambuc     }
140*0a6a1f1dSLionel Sambuc 
getChild(unsigned i) const141*0a6a1f1dSLionel Sambuc     const DeltaTreeNode *getChild(unsigned i) const {
142*0a6a1f1dSLionel Sambuc       assert(i < getNumValuesUsed()+1 && "Invalid child");
143*0a6a1f1dSLionel Sambuc       return Children[i];
144*0a6a1f1dSLionel Sambuc     }
getChild(unsigned i)145*0a6a1f1dSLionel Sambuc     DeltaTreeNode *getChild(unsigned i) {
146*0a6a1f1dSLionel Sambuc       assert(i < getNumValuesUsed()+1 && "Invalid child");
147*0a6a1f1dSLionel Sambuc       return Children[i];
148*0a6a1f1dSLionel Sambuc     }
149*0a6a1f1dSLionel Sambuc 
classof(const DeltaTreeNode * N)150*0a6a1f1dSLionel Sambuc     static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
151*0a6a1f1dSLionel Sambuc   };
152*0a6a1f1dSLionel Sambuc }
153*0a6a1f1dSLionel Sambuc 
154*0a6a1f1dSLionel Sambuc 
155*0a6a1f1dSLionel Sambuc /// Destroy - A 'virtual' destructor.
Destroy()156*0a6a1f1dSLionel Sambuc void DeltaTreeNode::Destroy() {
157*0a6a1f1dSLionel Sambuc   if (isLeaf())
158*0a6a1f1dSLionel Sambuc     delete this;
159*0a6a1f1dSLionel Sambuc   else
160*0a6a1f1dSLionel Sambuc     delete cast<DeltaTreeInteriorNode>(this);
161*0a6a1f1dSLionel Sambuc }
162*0a6a1f1dSLionel Sambuc 
163*0a6a1f1dSLionel Sambuc /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
164*0a6a1f1dSLionel Sambuc /// local walk over our contained deltas.
RecomputeFullDeltaLocally()165*0a6a1f1dSLionel Sambuc void DeltaTreeNode::RecomputeFullDeltaLocally() {
166*0a6a1f1dSLionel Sambuc   int NewFullDelta = 0;
167*0a6a1f1dSLionel Sambuc   for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
168*0a6a1f1dSLionel Sambuc     NewFullDelta += Values[i].Delta;
169*0a6a1f1dSLionel Sambuc   if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this))
170*0a6a1f1dSLionel Sambuc     for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
171*0a6a1f1dSLionel Sambuc       NewFullDelta += IN->getChild(i)->getFullDelta();
172*0a6a1f1dSLionel Sambuc   FullDelta = NewFullDelta;
173*0a6a1f1dSLionel Sambuc }
174*0a6a1f1dSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
176*0a6a1f1dSLionel Sambuc /// this node.  If insertion is easy, do it and return false.  Otherwise,
177*0a6a1f1dSLionel Sambuc /// split the node, populate InsertRes with info about the split, and return
178*0a6a1f1dSLionel Sambuc /// true.
DoInsertion(unsigned FileIndex,int Delta,InsertResult * InsertRes)179*0a6a1f1dSLionel Sambuc bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta,
180*0a6a1f1dSLionel Sambuc                                 InsertResult *InsertRes) {
181*0a6a1f1dSLionel Sambuc   // Maintain full delta for this node.
182*0a6a1f1dSLionel Sambuc   FullDelta += Delta;
183*0a6a1f1dSLionel Sambuc 
184*0a6a1f1dSLionel Sambuc   // Find the insertion point, the first delta whose index is >= FileIndex.
185*0a6a1f1dSLionel Sambuc   unsigned i = 0, e = getNumValuesUsed();
186*0a6a1f1dSLionel Sambuc   while (i != e && FileIndex > getValue(i).FileLoc)
187*0a6a1f1dSLionel Sambuc     ++i;
188*0a6a1f1dSLionel Sambuc 
189*0a6a1f1dSLionel Sambuc   // If we found an a record for exactly this file index, just merge this
190*0a6a1f1dSLionel Sambuc   // value into the pre-existing record and finish early.
191*0a6a1f1dSLionel Sambuc   if (i != e && getValue(i).FileLoc == FileIndex) {
192*0a6a1f1dSLionel Sambuc     // NOTE: Delta could drop to zero here.  This means that the delta entry is
193*0a6a1f1dSLionel Sambuc     // useless and could be removed.  Supporting erases is more complex than
194*0a6a1f1dSLionel Sambuc     // leaving an entry with Delta=0, so we just leave an entry with Delta=0 in
195*0a6a1f1dSLionel Sambuc     // the tree.
196*0a6a1f1dSLionel Sambuc     Values[i].Delta += Delta;
197*0a6a1f1dSLionel Sambuc     return false;
198*0a6a1f1dSLionel Sambuc   }
199*0a6a1f1dSLionel Sambuc 
200*0a6a1f1dSLionel Sambuc   // Otherwise, we found an insertion point, and we know that the value at the
201*0a6a1f1dSLionel Sambuc   // specified index is > FileIndex.  Handle the leaf case first.
202*0a6a1f1dSLionel Sambuc   if (isLeaf()) {
203*0a6a1f1dSLionel Sambuc     if (!isFull()) {
204*0a6a1f1dSLionel Sambuc       // For an insertion into a non-full leaf node, just insert the value in
205*0a6a1f1dSLionel Sambuc       // its sorted position.  This requires moving later values over.
206*0a6a1f1dSLionel Sambuc       if (i != e)
207*0a6a1f1dSLionel Sambuc         memmove(&Values[i+1], &Values[i], sizeof(Values[0])*(e-i));
208*0a6a1f1dSLionel Sambuc       Values[i] = SourceDelta::get(FileIndex, Delta);
209*0a6a1f1dSLionel Sambuc       ++NumValuesUsed;
210*0a6a1f1dSLionel Sambuc       return false;
211*0a6a1f1dSLionel Sambuc     }
212*0a6a1f1dSLionel Sambuc 
213*0a6a1f1dSLionel Sambuc     // Otherwise, if this is leaf is full, split the node at its median, insert
214*0a6a1f1dSLionel Sambuc     // the value into one of the children, and return the result.
215*0a6a1f1dSLionel Sambuc     assert(InsertRes && "No result location specified");
216*0a6a1f1dSLionel Sambuc     DoSplit(*InsertRes);
217*0a6a1f1dSLionel Sambuc 
218*0a6a1f1dSLionel Sambuc     if (InsertRes->Split.FileLoc > FileIndex)
219*0a6a1f1dSLionel Sambuc       InsertRes->LHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
220*0a6a1f1dSLionel Sambuc     else
221*0a6a1f1dSLionel Sambuc       InsertRes->RHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
222*0a6a1f1dSLionel Sambuc     return true;
223*0a6a1f1dSLionel Sambuc   }
224*0a6a1f1dSLionel Sambuc 
225*0a6a1f1dSLionel Sambuc   // Otherwise, this is an interior node.  Send the request down the tree.
226*0a6a1f1dSLionel Sambuc   DeltaTreeInteriorNode *IN = cast<DeltaTreeInteriorNode>(this);
227*0a6a1f1dSLionel Sambuc   if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
228*0a6a1f1dSLionel Sambuc     return false; // If there was space in the child, just return.
229*0a6a1f1dSLionel Sambuc 
230*0a6a1f1dSLionel Sambuc   // Okay, this split the subtree, producing a new value and two children to
231*0a6a1f1dSLionel Sambuc   // insert here.  If this node is non-full, we can just insert it directly.
232*0a6a1f1dSLionel Sambuc   if (!isFull()) {
233*0a6a1f1dSLionel Sambuc     // Now that we have two nodes and a new element, insert the perclated value
234*0a6a1f1dSLionel Sambuc     // into ourself by moving all the later values/children down, then inserting
235*0a6a1f1dSLionel Sambuc     // the new one.
236*0a6a1f1dSLionel Sambuc     if (i != e)
237*0a6a1f1dSLionel Sambuc       memmove(&IN->Children[i+2], &IN->Children[i+1],
238*0a6a1f1dSLionel Sambuc               (e-i)*sizeof(IN->Children[0]));
239*0a6a1f1dSLionel Sambuc     IN->Children[i] = InsertRes->LHS;
240*0a6a1f1dSLionel Sambuc     IN->Children[i+1] = InsertRes->RHS;
241*0a6a1f1dSLionel Sambuc 
242*0a6a1f1dSLionel Sambuc     if (e != i)
243*0a6a1f1dSLionel Sambuc       memmove(&Values[i+1], &Values[i], (e-i)*sizeof(Values[0]));
244*0a6a1f1dSLionel Sambuc     Values[i] = InsertRes->Split;
245*0a6a1f1dSLionel Sambuc     ++NumValuesUsed;
246*0a6a1f1dSLionel Sambuc     return false;
247*0a6a1f1dSLionel Sambuc   }
248*0a6a1f1dSLionel Sambuc 
249*0a6a1f1dSLionel Sambuc   // Finally, if this interior node was full and a node is percolated up, split
250*0a6a1f1dSLionel Sambuc   // ourself and return that up the chain.  Start by saving all our info to
251*0a6a1f1dSLionel Sambuc   // avoid having the split clobber it.
252*0a6a1f1dSLionel Sambuc   IN->Children[i] = InsertRes->LHS;
253*0a6a1f1dSLionel Sambuc   DeltaTreeNode *SubRHS = InsertRes->RHS;
254*0a6a1f1dSLionel Sambuc   SourceDelta SubSplit = InsertRes->Split;
255*0a6a1f1dSLionel Sambuc 
256*0a6a1f1dSLionel Sambuc   // Do the split.
257*0a6a1f1dSLionel Sambuc   DoSplit(*InsertRes);
258*0a6a1f1dSLionel Sambuc 
259*0a6a1f1dSLionel Sambuc   // Figure out where to insert SubRHS/NewSplit.
260*0a6a1f1dSLionel Sambuc   DeltaTreeInteriorNode *InsertSide;
261*0a6a1f1dSLionel Sambuc   if (SubSplit.FileLoc < InsertRes->Split.FileLoc)
262*0a6a1f1dSLionel Sambuc     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS);
263*0a6a1f1dSLionel Sambuc   else
264*0a6a1f1dSLionel Sambuc     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS);
265*0a6a1f1dSLionel Sambuc 
266*0a6a1f1dSLionel Sambuc   // We now have a non-empty interior node 'InsertSide' to insert
267*0a6a1f1dSLionel Sambuc   // SubRHS/SubSplit into.  Find out where to insert SubSplit.
268*0a6a1f1dSLionel Sambuc 
269*0a6a1f1dSLionel Sambuc   // Find the insertion point, the first delta whose index is >SubSplit.FileLoc.
270*0a6a1f1dSLionel Sambuc   i = 0; e = InsertSide->getNumValuesUsed();
271*0a6a1f1dSLionel Sambuc   while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc)
272*0a6a1f1dSLionel Sambuc     ++i;
273*0a6a1f1dSLionel Sambuc 
274*0a6a1f1dSLionel Sambuc   // Now we know that i is the place to insert the split value into.  Insert it
275*0a6a1f1dSLionel Sambuc   // and the child right after it.
276*0a6a1f1dSLionel Sambuc   if (i != e)
277*0a6a1f1dSLionel Sambuc     memmove(&InsertSide->Children[i+2], &InsertSide->Children[i+1],
278*0a6a1f1dSLionel Sambuc             (e-i)*sizeof(IN->Children[0]));
279*0a6a1f1dSLionel Sambuc   InsertSide->Children[i+1] = SubRHS;
280*0a6a1f1dSLionel Sambuc 
281*0a6a1f1dSLionel Sambuc   if (e != i)
282*0a6a1f1dSLionel Sambuc     memmove(&InsertSide->Values[i+1], &InsertSide->Values[i],
283*0a6a1f1dSLionel Sambuc             (e-i)*sizeof(Values[0]));
284*0a6a1f1dSLionel Sambuc   InsertSide->Values[i] = SubSplit;
285*0a6a1f1dSLionel Sambuc   ++InsertSide->NumValuesUsed;
286*0a6a1f1dSLionel Sambuc   InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta();
287*0a6a1f1dSLionel Sambuc   return true;
288*0a6a1f1dSLionel Sambuc }
289*0a6a1f1dSLionel Sambuc 
290*0a6a1f1dSLionel Sambuc /// DoSplit - Split the currently full node (which has 2*WidthFactor-1 values)
291*0a6a1f1dSLionel Sambuc /// into two subtrees each with "WidthFactor-1" values and a pivot value.
292*0a6a1f1dSLionel Sambuc /// Return the pieces in InsertRes.
DoSplit(InsertResult & InsertRes)293*0a6a1f1dSLionel Sambuc void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
294*0a6a1f1dSLionel Sambuc   assert(isFull() && "Why split a non-full node?");
295*0a6a1f1dSLionel Sambuc 
296*0a6a1f1dSLionel Sambuc   // Since this node is full, it contains 2*WidthFactor-1 values.  We move
297*0a6a1f1dSLionel Sambuc   // the first 'WidthFactor-1' values to the LHS child (which we leave in this
298*0a6a1f1dSLionel Sambuc   // node), propagate one value up, and move the last 'WidthFactor-1' values
299*0a6a1f1dSLionel Sambuc   // into the RHS child.
300*0a6a1f1dSLionel Sambuc 
301*0a6a1f1dSLionel Sambuc   // Create the new child node.
302*0a6a1f1dSLionel Sambuc   DeltaTreeNode *NewNode;
303*0a6a1f1dSLionel Sambuc   if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
304*0a6a1f1dSLionel Sambuc     // If this is an interior node, also move over 'WidthFactor' children
305*0a6a1f1dSLionel Sambuc     // into the new node.
306*0a6a1f1dSLionel Sambuc     DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
307*0a6a1f1dSLionel Sambuc     memcpy(&New->Children[0], &IN->Children[WidthFactor],
308*0a6a1f1dSLionel Sambuc            WidthFactor*sizeof(IN->Children[0]));
309*0a6a1f1dSLionel Sambuc     NewNode = New;
310*0a6a1f1dSLionel Sambuc   } else {
311*0a6a1f1dSLionel Sambuc     // Just create the new leaf node.
312*0a6a1f1dSLionel Sambuc     NewNode = new DeltaTreeNode();
313*0a6a1f1dSLionel Sambuc   }
314*0a6a1f1dSLionel Sambuc 
315*0a6a1f1dSLionel Sambuc   // Move over the last 'WidthFactor-1' values from here to NewNode.
316*0a6a1f1dSLionel Sambuc   memcpy(&NewNode->Values[0], &Values[WidthFactor],
317*0a6a1f1dSLionel Sambuc          (WidthFactor-1)*sizeof(Values[0]));
318*0a6a1f1dSLionel Sambuc 
319*0a6a1f1dSLionel Sambuc   // Decrease the number of values in the two nodes.
320*0a6a1f1dSLionel Sambuc   NewNode->NumValuesUsed = NumValuesUsed = WidthFactor-1;
321*0a6a1f1dSLionel Sambuc 
322*0a6a1f1dSLionel Sambuc   // Recompute the two nodes' full delta.
323*0a6a1f1dSLionel Sambuc   NewNode->RecomputeFullDeltaLocally();
324*0a6a1f1dSLionel Sambuc   RecomputeFullDeltaLocally();
325*0a6a1f1dSLionel Sambuc 
326*0a6a1f1dSLionel Sambuc   InsertRes.LHS = this;
327*0a6a1f1dSLionel Sambuc   InsertRes.RHS = NewNode;
328*0a6a1f1dSLionel Sambuc   InsertRes.Split = Values[WidthFactor-1];
329*0a6a1f1dSLionel Sambuc }
330*0a6a1f1dSLionel Sambuc 
331*0a6a1f1dSLionel Sambuc 
332*0a6a1f1dSLionel Sambuc 
333*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
334*0a6a1f1dSLionel Sambuc //                        DeltaTree Implementation
335*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
336*0a6a1f1dSLionel Sambuc 
337*0a6a1f1dSLionel Sambuc //#define VERIFY_TREE
338*0a6a1f1dSLionel Sambuc 
339*0a6a1f1dSLionel Sambuc #ifdef VERIFY_TREE
340*0a6a1f1dSLionel Sambuc /// VerifyTree - Walk the btree performing assertions on various properties to
341*0a6a1f1dSLionel Sambuc /// verify consistency.  This is useful for debugging new changes to the tree.
VerifyTree(const DeltaTreeNode * N)342*0a6a1f1dSLionel Sambuc static void VerifyTree(const DeltaTreeNode *N) {
343*0a6a1f1dSLionel Sambuc   const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(N);
344*0a6a1f1dSLionel Sambuc   if (IN == 0) {
345*0a6a1f1dSLionel Sambuc     // Verify leaves, just ensure that FullDelta matches up and the elements
346*0a6a1f1dSLionel Sambuc     // are in proper order.
347*0a6a1f1dSLionel Sambuc     int FullDelta = 0;
348*0a6a1f1dSLionel Sambuc     for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
349*0a6a1f1dSLionel Sambuc       if (i)
350*0a6a1f1dSLionel Sambuc         assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
351*0a6a1f1dSLionel Sambuc       FullDelta += N->getValue(i).Delta;
352*0a6a1f1dSLionel Sambuc     }
353*0a6a1f1dSLionel Sambuc     assert(FullDelta == N->getFullDelta());
354*0a6a1f1dSLionel Sambuc     return;
355*0a6a1f1dSLionel Sambuc   }
356*0a6a1f1dSLionel Sambuc 
357*0a6a1f1dSLionel Sambuc   // Verify interior nodes: Ensure that FullDelta matches up and the
358*0a6a1f1dSLionel Sambuc   // elements are in proper order and the children are in proper order.
359*0a6a1f1dSLionel Sambuc   int FullDelta = 0;
360*0a6a1f1dSLionel Sambuc   for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
361*0a6a1f1dSLionel Sambuc     const SourceDelta &IVal = N->getValue(i);
362*0a6a1f1dSLionel Sambuc     const DeltaTreeNode *IChild = IN->getChild(i);
363*0a6a1f1dSLionel Sambuc     if (i)
364*0a6a1f1dSLionel Sambuc       assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
365*0a6a1f1dSLionel Sambuc     FullDelta += IVal.Delta;
366*0a6a1f1dSLionel Sambuc     FullDelta += IChild->getFullDelta();
367*0a6a1f1dSLionel Sambuc 
368*0a6a1f1dSLionel Sambuc     // The largest value in child #i should be smaller than FileLoc.
369*0a6a1f1dSLionel Sambuc     assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
370*0a6a1f1dSLionel Sambuc            IVal.FileLoc);
371*0a6a1f1dSLionel Sambuc 
372*0a6a1f1dSLionel Sambuc     // The smallest value in child #i+1 should be larger than FileLoc.
373*0a6a1f1dSLionel Sambuc     assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
374*0a6a1f1dSLionel Sambuc     VerifyTree(IChild);
375*0a6a1f1dSLionel Sambuc   }
376*0a6a1f1dSLionel Sambuc 
377*0a6a1f1dSLionel Sambuc   FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
378*0a6a1f1dSLionel Sambuc 
379*0a6a1f1dSLionel Sambuc   assert(FullDelta == N->getFullDelta());
380*0a6a1f1dSLionel Sambuc }
381*0a6a1f1dSLionel Sambuc #endif  // VERIFY_TREE
382*0a6a1f1dSLionel Sambuc 
getRoot(void * Root)383*0a6a1f1dSLionel Sambuc static DeltaTreeNode *getRoot(void *Root) {
384*0a6a1f1dSLionel Sambuc   return (DeltaTreeNode*)Root;
385*0a6a1f1dSLionel Sambuc }
386*0a6a1f1dSLionel Sambuc 
DeltaTree()387*0a6a1f1dSLionel Sambuc DeltaTree::DeltaTree() {
388*0a6a1f1dSLionel Sambuc   Root = new DeltaTreeNode();
389*0a6a1f1dSLionel Sambuc }
DeltaTree(const DeltaTree & RHS)390*0a6a1f1dSLionel Sambuc DeltaTree::DeltaTree(const DeltaTree &RHS) {
391*0a6a1f1dSLionel Sambuc   // Currently we only support copying when the RHS is empty.
392*0a6a1f1dSLionel Sambuc   assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
393*0a6a1f1dSLionel Sambuc          "Can only copy empty tree");
394*0a6a1f1dSLionel Sambuc   Root = new DeltaTreeNode();
395*0a6a1f1dSLionel Sambuc }
396*0a6a1f1dSLionel Sambuc 
~DeltaTree()397*0a6a1f1dSLionel Sambuc DeltaTree::~DeltaTree() {
398*0a6a1f1dSLionel Sambuc   getRoot(Root)->Destroy();
399*0a6a1f1dSLionel Sambuc }
400*0a6a1f1dSLionel Sambuc 
401*0a6a1f1dSLionel Sambuc /// getDeltaAt - Return the accumulated delta at the specified file offset.
402*0a6a1f1dSLionel Sambuc /// This includes all insertions or delections that occurred *before* the
403*0a6a1f1dSLionel Sambuc /// specified file index.
getDeltaAt(unsigned FileIndex) const404*0a6a1f1dSLionel Sambuc int DeltaTree::getDeltaAt(unsigned FileIndex) const {
405*0a6a1f1dSLionel Sambuc   const DeltaTreeNode *Node = getRoot(Root);
406*0a6a1f1dSLionel Sambuc 
407*0a6a1f1dSLionel Sambuc   int Result = 0;
408*0a6a1f1dSLionel Sambuc 
409*0a6a1f1dSLionel Sambuc   // Walk down the tree.
410*0a6a1f1dSLionel Sambuc   while (1) {
411*0a6a1f1dSLionel Sambuc     // For all nodes, include any local deltas before the specified file
412*0a6a1f1dSLionel Sambuc     // index by summing them up directly.  Keep track of how many were
413*0a6a1f1dSLionel Sambuc     // included.
414*0a6a1f1dSLionel Sambuc     unsigned NumValsGreater = 0;
415*0a6a1f1dSLionel Sambuc     for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e;
416*0a6a1f1dSLionel Sambuc          ++NumValsGreater) {
417*0a6a1f1dSLionel Sambuc       const SourceDelta &Val = Node->getValue(NumValsGreater);
418*0a6a1f1dSLionel Sambuc 
419*0a6a1f1dSLionel Sambuc       if (Val.FileLoc >= FileIndex)
420*0a6a1f1dSLionel Sambuc         break;
421*0a6a1f1dSLionel Sambuc       Result += Val.Delta;
422*0a6a1f1dSLionel Sambuc     }
423*0a6a1f1dSLionel Sambuc 
424*0a6a1f1dSLionel Sambuc     // If we have an interior node, include information about children and
425*0a6a1f1dSLionel Sambuc     // recurse.  Otherwise, if we have a leaf, we're done.
426*0a6a1f1dSLionel Sambuc     const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
427*0a6a1f1dSLionel Sambuc     if (!IN) return Result;
428*0a6a1f1dSLionel Sambuc 
429*0a6a1f1dSLionel Sambuc     // Include any children to the left of the values we skipped, all of
430*0a6a1f1dSLionel Sambuc     // their deltas should be included as well.
431*0a6a1f1dSLionel Sambuc     for (unsigned i = 0; i != NumValsGreater; ++i)
432*0a6a1f1dSLionel Sambuc       Result += IN->getChild(i)->getFullDelta();
433*0a6a1f1dSLionel Sambuc 
434*0a6a1f1dSLionel Sambuc     // If we found exactly the value we were looking for, break off the
435*0a6a1f1dSLionel Sambuc     // search early.  There is no need to search the RHS of the value for
436*0a6a1f1dSLionel Sambuc     // partial results.
437*0a6a1f1dSLionel Sambuc     if (NumValsGreater != Node->getNumValuesUsed() &&
438*0a6a1f1dSLionel Sambuc         Node->getValue(NumValsGreater).FileLoc == FileIndex)
439*0a6a1f1dSLionel Sambuc       return Result+IN->getChild(NumValsGreater)->getFullDelta();
440*0a6a1f1dSLionel Sambuc 
441*0a6a1f1dSLionel Sambuc     // Otherwise, traverse down the tree.  The selected subtree may be
442*0a6a1f1dSLionel Sambuc     // partially included in the range.
443*0a6a1f1dSLionel Sambuc     Node = IN->getChild(NumValsGreater);
444*0a6a1f1dSLionel Sambuc   }
445*0a6a1f1dSLionel Sambuc   // NOT REACHED.
446*0a6a1f1dSLionel Sambuc }
447*0a6a1f1dSLionel Sambuc 
448*0a6a1f1dSLionel Sambuc /// AddDelta - When a change is made that shifts around the text buffer,
449*0a6a1f1dSLionel Sambuc /// this method is used to record that info.  It inserts a delta of 'Delta'
450*0a6a1f1dSLionel Sambuc /// into the current DeltaTree at offset FileIndex.
AddDelta(unsigned FileIndex,int Delta)451*0a6a1f1dSLionel Sambuc void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
452*0a6a1f1dSLionel Sambuc   assert(Delta && "Adding a noop?");
453*0a6a1f1dSLionel Sambuc   DeltaTreeNode *MyRoot = getRoot(Root);
454*0a6a1f1dSLionel Sambuc 
455*0a6a1f1dSLionel Sambuc   DeltaTreeNode::InsertResult InsertRes;
456*0a6a1f1dSLionel Sambuc   if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
457*0a6a1f1dSLionel Sambuc     Root = MyRoot = new DeltaTreeInteriorNode(InsertRes);
458*0a6a1f1dSLionel Sambuc   }
459*0a6a1f1dSLionel Sambuc 
460*0a6a1f1dSLionel Sambuc #ifdef VERIFY_TREE
461*0a6a1f1dSLionel Sambuc   VerifyTree(MyRoot);
462*0a6a1f1dSLionel Sambuc #endif
463*0a6a1f1dSLionel Sambuc }
464*0a6a1f1dSLionel Sambuc 
465