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