xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Rewrite/DeltaTree.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the DeltaTree and related classes.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/Rewrite/Core/DeltaTree.h"
147330f729Sjoerg #include "clang/Basic/LLVM.h"
157330f729Sjoerg #include "llvm/Support/Casting.h"
167330f729Sjoerg #include <cassert>
177330f729Sjoerg #include <cstring>
187330f729Sjoerg 
197330f729Sjoerg using namespace clang;
207330f729Sjoerg 
217330f729Sjoerg /// The DeltaTree class is a multiway search tree (BTree) structure with some
227330f729Sjoerg /// fancy features.  B-Trees are generally more memory and cache efficient
237330f729Sjoerg /// than binary trees, because they store multiple keys/values in each node.
247330f729Sjoerg ///
257330f729Sjoerg /// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
267330f729Sjoerg /// fast lookup by FileIndex.  However, an added (important) bonus is that it
277330f729Sjoerg /// can also efficiently tell us the full accumulated delta for a specific
287330f729Sjoerg /// file offset as well, without traversing the whole tree.
297330f729Sjoerg ///
307330f729Sjoerg /// The nodes of the tree are made up of instances of two classes:
317330f729Sjoerg /// DeltaTreeNode and DeltaTreeInteriorNode.  The later subclasses the
327330f729Sjoerg /// former and adds children pointers.  Each node knows the full delta of all
337330f729Sjoerg /// entries (recursively) contained inside of it, which allows us to get the
347330f729Sjoerg /// full delta implied by a whole subtree in constant time.
357330f729Sjoerg 
367330f729Sjoerg namespace {
377330f729Sjoerg 
387330f729Sjoerg   /// SourceDelta - As code in the original input buffer is added and deleted,
397330f729Sjoerg   /// SourceDelta records are used to keep track of how the input SourceLocation
407330f729Sjoerg   /// object is mapped into the output buffer.
417330f729Sjoerg   struct SourceDelta {
427330f729Sjoerg     unsigned FileLoc;
437330f729Sjoerg     int Delta;
447330f729Sjoerg 
get__anonb6a907500111::SourceDelta457330f729Sjoerg     static SourceDelta get(unsigned Loc, int D) {
467330f729Sjoerg       SourceDelta Delta;
477330f729Sjoerg       Delta.FileLoc = Loc;
487330f729Sjoerg       Delta.Delta = D;
497330f729Sjoerg       return Delta;
507330f729Sjoerg     }
517330f729Sjoerg   };
527330f729Sjoerg 
537330f729Sjoerg   /// DeltaTreeNode - The common part of all nodes.
547330f729Sjoerg   ///
557330f729Sjoerg   class DeltaTreeNode {
567330f729Sjoerg   public:
577330f729Sjoerg     struct InsertResult {
587330f729Sjoerg       DeltaTreeNode *LHS, *RHS;
597330f729Sjoerg       SourceDelta Split;
607330f729Sjoerg     };
617330f729Sjoerg 
627330f729Sjoerg   private:
637330f729Sjoerg     friend class DeltaTreeInteriorNode;
647330f729Sjoerg 
657330f729Sjoerg     /// WidthFactor - This controls the number of K/V slots held in the BTree:
667330f729Sjoerg     /// how wide it is.  Each level of the BTree is guaranteed to have at least
677330f729Sjoerg     /// WidthFactor-1 K/V pairs (except the root) and may have at most
687330f729Sjoerg     /// 2*WidthFactor-1 K/V pairs.
697330f729Sjoerg     enum { WidthFactor = 8 };
707330f729Sjoerg 
717330f729Sjoerg     /// Values - This tracks the SourceDelta's currently in this node.
727330f729Sjoerg     SourceDelta Values[2*WidthFactor-1];
737330f729Sjoerg 
747330f729Sjoerg     /// NumValuesUsed - This tracks the number of values this node currently
757330f729Sjoerg     /// holds.
767330f729Sjoerg     unsigned char NumValuesUsed = 0;
777330f729Sjoerg 
787330f729Sjoerg     /// IsLeaf - This is true if this is a leaf of the btree.  If false, this is
797330f729Sjoerg     /// an interior node, and is actually an instance of DeltaTreeInteriorNode.
807330f729Sjoerg     bool IsLeaf;
817330f729Sjoerg 
827330f729Sjoerg     /// FullDelta - This is the full delta of all the values in this node and
837330f729Sjoerg     /// all children nodes.
847330f729Sjoerg     int FullDelta = 0;
857330f729Sjoerg 
867330f729Sjoerg   public:
DeltaTreeNode(bool isLeaf=true)877330f729Sjoerg     DeltaTreeNode(bool isLeaf = true) : IsLeaf(isLeaf) {}
887330f729Sjoerg 
isLeaf() const897330f729Sjoerg     bool isLeaf() const { return IsLeaf; }
getFullDelta() const907330f729Sjoerg     int getFullDelta() const { return FullDelta; }
isFull() const917330f729Sjoerg     bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
927330f729Sjoerg 
getNumValuesUsed() const937330f729Sjoerg     unsigned getNumValuesUsed() const { return NumValuesUsed; }
947330f729Sjoerg 
getValue(unsigned i) const957330f729Sjoerg     const SourceDelta &getValue(unsigned i) const {
967330f729Sjoerg       assert(i < NumValuesUsed && "Invalid value #");
977330f729Sjoerg       return Values[i];
987330f729Sjoerg     }
997330f729Sjoerg 
getValue(unsigned i)1007330f729Sjoerg     SourceDelta &getValue(unsigned i) {
1017330f729Sjoerg       assert(i < NumValuesUsed && "Invalid value #");
1027330f729Sjoerg       return Values[i];
1037330f729Sjoerg     }
1047330f729Sjoerg 
1057330f729Sjoerg     /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
1067330f729Sjoerg     /// this node.  If insertion is easy, do it and return false.  Otherwise,
1077330f729Sjoerg     /// split the node, populate InsertRes with info about the split, and return
1087330f729Sjoerg     /// true.
1097330f729Sjoerg     bool DoInsertion(unsigned FileIndex, int Delta, InsertResult *InsertRes);
1107330f729Sjoerg 
1117330f729Sjoerg     void DoSplit(InsertResult &InsertRes);
1127330f729Sjoerg 
1137330f729Sjoerg 
1147330f729Sjoerg     /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
1157330f729Sjoerg     /// local walk over our contained deltas.
1167330f729Sjoerg     void RecomputeFullDeltaLocally();
1177330f729Sjoerg 
1187330f729Sjoerg     void Destroy();
1197330f729Sjoerg   };
1207330f729Sjoerg 
1217330f729Sjoerg   /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
1227330f729Sjoerg   /// This class tracks them.
1237330f729Sjoerg   class DeltaTreeInteriorNode : public DeltaTreeNode {
1247330f729Sjoerg     friend class DeltaTreeNode;
1257330f729Sjoerg 
1267330f729Sjoerg     DeltaTreeNode *Children[2*WidthFactor];
1277330f729Sjoerg 
~DeltaTreeInteriorNode()1287330f729Sjoerg     ~DeltaTreeInteriorNode() {
1297330f729Sjoerg       for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
1307330f729Sjoerg         Children[i]->Destroy();
1317330f729Sjoerg     }
1327330f729Sjoerg 
1337330f729Sjoerg   public:
DeltaTreeInteriorNode()1347330f729Sjoerg     DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
1357330f729Sjoerg 
DeltaTreeInteriorNode(const InsertResult & IR)1367330f729Sjoerg     DeltaTreeInteriorNode(const InsertResult &IR)
1377330f729Sjoerg         : DeltaTreeNode(false /*nonleaf*/) {
1387330f729Sjoerg       Children[0] = IR.LHS;
1397330f729Sjoerg       Children[1] = IR.RHS;
1407330f729Sjoerg       Values[0] = IR.Split;
1417330f729Sjoerg       FullDelta = IR.LHS->getFullDelta()+IR.RHS->getFullDelta()+IR.Split.Delta;
1427330f729Sjoerg       NumValuesUsed = 1;
1437330f729Sjoerg     }
1447330f729Sjoerg 
getChild(unsigned i) const1457330f729Sjoerg     const DeltaTreeNode *getChild(unsigned i) const {
1467330f729Sjoerg       assert(i < getNumValuesUsed()+1 && "Invalid child");
1477330f729Sjoerg       return Children[i];
1487330f729Sjoerg     }
1497330f729Sjoerg 
getChild(unsigned i)1507330f729Sjoerg     DeltaTreeNode *getChild(unsigned i) {
1517330f729Sjoerg       assert(i < getNumValuesUsed()+1 && "Invalid child");
1527330f729Sjoerg       return Children[i];
1537330f729Sjoerg     }
1547330f729Sjoerg 
classof(const DeltaTreeNode * N)1557330f729Sjoerg     static bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
1567330f729Sjoerg   };
1577330f729Sjoerg 
1587330f729Sjoerg } // namespace
1597330f729Sjoerg 
1607330f729Sjoerg /// Destroy - A 'virtual' destructor.
Destroy()1617330f729Sjoerg void DeltaTreeNode::Destroy() {
1627330f729Sjoerg   if (isLeaf())
1637330f729Sjoerg     delete this;
1647330f729Sjoerg   else
1657330f729Sjoerg     delete cast<DeltaTreeInteriorNode>(this);
1667330f729Sjoerg }
1677330f729Sjoerg 
1687330f729Sjoerg /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
1697330f729Sjoerg /// local walk over our contained deltas.
RecomputeFullDeltaLocally()1707330f729Sjoerg void DeltaTreeNode::RecomputeFullDeltaLocally() {
1717330f729Sjoerg   int NewFullDelta = 0;
1727330f729Sjoerg   for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
1737330f729Sjoerg     NewFullDelta += Values[i].Delta;
1747330f729Sjoerg   if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this))
1757330f729Sjoerg     for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
1767330f729Sjoerg       NewFullDelta += IN->getChild(i)->getFullDelta();
1777330f729Sjoerg   FullDelta = NewFullDelta;
1787330f729Sjoerg }
1797330f729Sjoerg 
1807330f729Sjoerg /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
1817330f729Sjoerg /// this node.  If insertion is easy, do it and return false.  Otherwise,
1827330f729Sjoerg /// split the node, populate InsertRes with info about the split, and return
1837330f729Sjoerg /// true.
DoInsertion(unsigned FileIndex,int Delta,InsertResult * InsertRes)1847330f729Sjoerg bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta,
1857330f729Sjoerg                                 InsertResult *InsertRes) {
1867330f729Sjoerg   // Maintain full delta for this node.
1877330f729Sjoerg   FullDelta += Delta;
1887330f729Sjoerg 
1897330f729Sjoerg   // Find the insertion point, the first delta whose index is >= FileIndex.
1907330f729Sjoerg   unsigned i = 0, e = getNumValuesUsed();
1917330f729Sjoerg   while (i != e && FileIndex > getValue(i).FileLoc)
1927330f729Sjoerg     ++i;
1937330f729Sjoerg 
1947330f729Sjoerg   // If we found an a record for exactly this file index, just merge this
1957330f729Sjoerg   // value into the pre-existing record and finish early.
1967330f729Sjoerg   if (i != e && getValue(i).FileLoc == FileIndex) {
1977330f729Sjoerg     // NOTE: Delta could drop to zero here.  This means that the delta entry is
1987330f729Sjoerg     // useless and could be removed.  Supporting erases is more complex than
1997330f729Sjoerg     // leaving an entry with Delta=0, so we just leave an entry with Delta=0 in
2007330f729Sjoerg     // the tree.
2017330f729Sjoerg     Values[i].Delta += Delta;
2027330f729Sjoerg     return false;
2037330f729Sjoerg   }
2047330f729Sjoerg 
2057330f729Sjoerg   // Otherwise, we found an insertion point, and we know that the value at the
2067330f729Sjoerg   // specified index is > FileIndex.  Handle the leaf case first.
2077330f729Sjoerg   if (isLeaf()) {
2087330f729Sjoerg     if (!isFull()) {
2097330f729Sjoerg       // For an insertion into a non-full leaf node, just insert the value in
2107330f729Sjoerg       // its sorted position.  This requires moving later values over.
2117330f729Sjoerg       if (i != e)
2127330f729Sjoerg         memmove(&Values[i+1], &Values[i], sizeof(Values[0])*(e-i));
2137330f729Sjoerg       Values[i] = SourceDelta::get(FileIndex, Delta);
2147330f729Sjoerg       ++NumValuesUsed;
2157330f729Sjoerg       return false;
2167330f729Sjoerg     }
2177330f729Sjoerg 
2187330f729Sjoerg     // Otherwise, if this is leaf is full, split the node at its median, insert
2197330f729Sjoerg     // the value into one of the children, and return the result.
2207330f729Sjoerg     assert(InsertRes && "No result location specified");
2217330f729Sjoerg     DoSplit(*InsertRes);
2227330f729Sjoerg 
2237330f729Sjoerg     if (InsertRes->Split.FileLoc > FileIndex)
2247330f729Sjoerg       InsertRes->LHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
2257330f729Sjoerg     else
2267330f729Sjoerg       InsertRes->RHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
2277330f729Sjoerg     return true;
2287330f729Sjoerg   }
2297330f729Sjoerg 
2307330f729Sjoerg   // Otherwise, this is an interior node.  Send the request down the tree.
2317330f729Sjoerg   auto *IN = cast<DeltaTreeInteriorNode>(this);
2327330f729Sjoerg   if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
2337330f729Sjoerg     return false; // If there was space in the child, just return.
2347330f729Sjoerg 
2357330f729Sjoerg   // Okay, this split the subtree, producing a new value and two children to
2367330f729Sjoerg   // insert here.  If this node is non-full, we can just insert it directly.
2377330f729Sjoerg   if (!isFull()) {
2387330f729Sjoerg     // Now that we have two nodes and a new element, insert the perclated value
2397330f729Sjoerg     // into ourself by moving all the later values/children down, then inserting
2407330f729Sjoerg     // the new one.
2417330f729Sjoerg     if (i != e)
2427330f729Sjoerg       memmove(&IN->Children[i+2], &IN->Children[i+1],
2437330f729Sjoerg               (e-i)*sizeof(IN->Children[0]));
2447330f729Sjoerg     IN->Children[i] = InsertRes->LHS;
2457330f729Sjoerg     IN->Children[i+1] = InsertRes->RHS;
2467330f729Sjoerg 
2477330f729Sjoerg     if (e != i)
2487330f729Sjoerg       memmove(&Values[i+1], &Values[i], (e-i)*sizeof(Values[0]));
2497330f729Sjoerg     Values[i] = InsertRes->Split;
2507330f729Sjoerg     ++NumValuesUsed;
2517330f729Sjoerg     return false;
2527330f729Sjoerg   }
2537330f729Sjoerg 
2547330f729Sjoerg   // Finally, if this interior node was full and a node is percolated up, split
2557330f729Sjoerg   // ourself and return that up the chain.  Start by saving all our info to
2567330f729Sjoerg   // avoid having the split clobber it.
2577330f729Sjoerg   IN->Children[i] = InsertRes->LHS;
2587330f729Sjoerg   DeltaTreeNode *SubRHS = InsertRes->RHS;
2597330f729Sjoerg   SourceDelta SubSplit = InsertRes->Split;
2607330f729Sjoerg 
2617330f729Sjoerg   // Do the split.
2627330f729Sjoerg   DoSplit(*InsertRes);
2637330f729Sjoerg 
2647330f729Sjoerg   // Figure out where to insert SubRHS/NewSplit.
2657330f729Sjoerg   DeltaTreeInteriorNode *InsertSide;
2667330f729Sjoerg   if (SubSplit.FileLoc < InsertRes->Split.FileLoc)
2677330f729Sjoerg     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS);
2687330f729Sjoerg   else
2697330f729Sjoerg     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS);
2707330f729Sjoerg 
2717330f729Sjoerg   // We now have a non-empty interior node 'InsertSide' to insert
2727330f729Sjoerg   // SubRHS/SubSplit into.  Find out where to insert SubSplit.
2737330f729Sjoerg 
2747330f729Sjoerg   // Find the insertion point, the first delta whose index is >SubSplit.FileLoc.
2757330f729Sjoerg   i = 0; e = InsertSide->getNumValuesUsed();
2767330f729Sjoerg   while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc)
2777330f729Sjoerg     ++i;
2787330f729Sjoerg 
2797330f729Sjoerg   // Now we know that i is the place to insert the split value into.  Insert it
2807330f729Sjoerg   // and the child right after it.
2817330f729Sjoerg   if (i != e)
2827330f729Sjoerg     memmove(&InsertSide->Children[i+2], &InsertSide->Children[i+1],
2837330f729Sjoerg             (e-i)*sizeof(IN->Children[0]));
2847330f729Sjoerg   InsertSide->Children[i+1] = SubRHS;
2857330f729Sjoerg 
2867330f729Sjoerg   if (e != i)
2877330f729Sjoerg     memmove(&InsertSide->Values[i+1], &InsertSide->Values[i],
2887330f729Sjoerg             (e-i)*sizeof(Values[0]));
2897330f729Sjoerg   InsertSide->Values[i] = SubSplit;
2907330f729Sjoerg   ++InsertSide->NumValuesUsed;
2917330f729Sjoerg   InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta();
2927330f729Sjoerg   return true;
2937330f729Sjoerg }
2947330f729Sjoerg 
2957330f729Sjoerg /// DoSplit - Split the currently full node (which has 2*WidthFactor-1 values)
2967330f729Sjoerg /// into two subtrees each with "WidthFactor-1" values and a pivot value.
2977330f729Sjoerg /// Return the pieces in InsertRes.
DoSplit(InsertResult & InsertRes)2987330f729Sjoerg void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
2997330f729Sjoerg   assert(isFull() && "Why split a non-full node?");
3007330f729Sjoerg 
3017330f729Sjoerg   // Since this node is full, it contains 2*WidthFactor-1 values.  We move
3027330f729Sjoerg   // the first 'WidthFactor-1' values to the LHS child (which we leave in this
3037330f729Sjoerg   // node), propagate one value up, and move the last 'WidthFactor-1' values
3047330f729Sjoerg   // into the RHS child.
3057330f729Sjoerg 
3067330f729Sjoerg   // Create the new child node.
3077330f729Sjoerg   DeltaTreeNode *NewNode;
3087330f729Sjoerg   if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
3097330f729Sjoerg     // If this is an interior node, also move over 'WidthFactor' children
3107330f729Sjoerg     // into the new node.
3117330f729Sjoerg     DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
3127330f729Sjoerg     memcpy(&New->Children[0], &IN->Children[WidthFactor],
3137330f729Sjoerg            WidthFactor*sizeof(IN->Children[0]));
3147330f729Sjoerg     NewNode = New;
3157330f729Sjoerg   } else {
3167330f729Sjoerg     // Just create the new leaf node.
3177330f729Sjoerg     NewNode = new DeltaTreeNode();
3187330f729Sjoerg   }
3197330f729Sjoerg 
3207330f729Sjoerg   // Move over the last 'WidthFactor-1' values from here to NewNode.
3217330f729Sjoerg   memcpy(&NewNode->Values[0], &Values[WidthFactor],
3227330f729Sjoerg          (WidthFactor-1)*sizeof(Values[0]));
3237330f729Sjoerg 
3247330f729Sjoerg   // Decrease the number of values in the two nodes.
3257330f729Sjoerg   NewNode->NumValuesUsed = NumValuesUsed = WidthFactor-1;
3267330f729Sjoerg 
3277330f729Sjoerg   // Recompute the two nodes' full delta.
3287330f729Sjoerg   NewNode->RecomputeFullDeltaLocally();
3297330f729Sjoerg   RecomputeFullDeltaLocally();
3307330f729Sjoerg 
3317330f729Sjoerg   InsertRes.LHS = this;
3327330f729Sjoerg   InsertRes.RHS = NewNode;
3337330f729Sjoerg   InsertRes.Split = Values[WidthFactor-1];
3347330f729Sjoerg }
3357330f729Sjoerg 
3367330f729Sjoerg //===----------------------------------------------------------------------===//
3377330f729Sjoerg //                        DeltaTree Implementation
3387330f729Sjoerg //===----------------------------------------------------------------------===//
3397330f729Sjoerg 
3407330f729Sjoerg //#define VERIFY_TREE
3417330f729Sjoerg 
3427330f729Sjoerg #ifdef VERIFY_TREE
3437330f729Sjoerg /// VerifyTree - Walk the btree performing assertions on various properties to
3447330f729Sjoerg /// verify consistency.  This is useful for debugging new changes to the tree.
VerifyTree(const DeltaTreeNode * N)3457330f729Sjoerg static void VerifyTree(const DeltaTreeNode *N) {
3467330f729Sjoerg   const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N);
3477330f729Sjoerg   if (IN == 0) {
3487330f729Sjoerg     // Verify leaves, just ensure that FullDelta matches up and the elements
3497330f729Sjoerg     // are in proper order.
3507330f729Sjoerg     int FullDelta = 0;
3517330f729Sjoerg     for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
3527330f729Sjoerg       if (i)
3537330f729Sjoerg         assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
3547330f729Sjoerg       FullDelta += N->getValue(i).Delta;
3557330f729Sjoerg     }
3567330f729Sjoerg     assert(FullDelta == N->getFullDelta());
3577330f729Sjoerg     return;
3587330f729Sjoerg   }
3597330f729Sjoerg 
3607330f729Sjoerg   // Verify interior nodes: Ensure that FullDelta matches up and the
3617330f729Sjoerg   // elements are in proper order and the children are in proper order.
3627330f729Sjoerg   int FullDelta = 0;
3637330f729Sjoerg   for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
3647330f729Sjoerg     const SourceDelta &IVal = N->getValue(i);
3657330f729Sjoerg     const DeltaTreeNode *IChild = IN->getChild(i);
3667330f729Sjoerg     if (i)
3677330f729Sjoerg       assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
3687330f729Sjoerg     FullDelta += IVal.Delta;
3697330f729Sjoerg     FullDelta += IChild->getFullDelta();
3707330f729Sjoerg 
3717330f729Sjoerg     // The largest value in child #i should be smaller than FileLoc.
3727330f729Sjoerg     assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
3737330f729Sjoerg            IVal.FileLoc);
3747330f729Sjoerg 
3757330f729Sjoerg     // The smallest value in child #i+1 should be larger than FileLoc.
3767330f729Sjoerg     assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
3777330f729Sjoerg     VerifyTree(IChild);
3787330f729Sjoerg   }
3797330f729Sjoerg 
3807330f729Sjoerg   FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
3817330f729Sjoerg 
3827330f729Sjoerg   assert(FullDelta == N->getFullDelta());
3837330f729Sjoerg }
3847330f729Sjoerg #endif  // VERIFY_TREE
3857330f729Sjoerg 
getRoot(void * Root)3867330f729Sjoerg static DeltaTreeNode *getRoot(void *Root) {
3877330f729Sjoerg   return (DeltaTreeNode*)Root;
3887330f729Sjoerg }
3897330f729Sjoerg 
DeltaTree()3907330f729Sjoerg DeltaTree::DeltaTree() {
3917330f729Sjoerg   Root = new DeltaTreeNode();
3927330f729Sjoerg }
3937330f729Sjoerg 
DeltaTree(const DeltaTree & RHS)3947330f729Sjoerg DeltaTree::DeltaTree(const DeltaTree &RHS) {
3957330f729Sjoerg   // Currently we only support copying when the RHS is empty.
3967330f729Sjoerg   assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
3977330f729Sjoerg          "Can only copy empty tree");
3987330f729Sjoerg   Root = new DeltaTreeNode();
3997330f729Sjoerg }
4007330f729Sjoerg 
~DeltaTree()4017330f729Sjoerg DeltaTree::~DeltaTree() {
4027330f729Sjoerg   getRoot(Root)->Destroy();
4037330f729Sjoerg }
4047330f729Sjoerg 
4057330f729Sjoerg /// getDeltaAt - Return the accumulated delta at the specified file offset.
4067330f729Sjoerg /// This includes all insertions or delections that occurred *before* the
4077330f729Sjoerg /// specified file index.
getDeltaAt(unsigned FileIndex) const4087330f729Sjoerg int DeltaTree::getDeltaAt(unsigned FileIndex) const {
4097330f729Sjoerg   const DeltaTreeNode *Node = getRoot(Root);
4107330f729Sjoerg 
4117330f729Sjoerg   int Result = 0;
4127330f729Sjoerg 
4137330f729Sjoerg   // Walk down the tree.
4147330f729Sjoerg   while (true) {
4157330f729Sjoerg     // For all nodes, include any local deltas before the specified file
4167330f729Sjoerg     // index by summing them up directly.  Keep track of how many were
4177330f729Sjoerg     // included.
4187330f729Sjoerg     unsigned NumValsGreater = 0;
4197330f729Sjoerg     for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e;
4207330f729Sjoerg          ++NumValsGreater) {
4217330f729Sjoerg       const SourceDelta &Val = Node->getValue(NumValsGreater);
4227330f729Sjoerg 
4237330f729Sjoerg       if (Val.FileLoc >= FileIndex)
4247330f729Sjoerg         break;
4257330f729Sjoerg       Result += Val.Delta;
4267330f729Sjoerg     }
4277330f729Sjoerg 
4287330f729Sjoerg     // If we have an interior node, include information about children and
4297330f729Sjoerg     // recurse.  Otherwise, if we have a leaf, we're done.
4307330f729Sjoerg     const auto *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
4317330f729Sjoerg     if (!IN) return Result;
4327330f729Sjoerg 
4337330f729Sjoerg     // Include any children to the left of the values we skipped, all of
4347330f729Sjoerg     // their deltas should be included as well.
4357330f729Sjoerg     for (unsigned i = 0; i != NumValsGreater; ++i)
4367330f729Sjoerg       Result += IN->getChild(i)->getFullDelta();
4377330f729Sjoerg 
4387330f729Sjoerg     // If we found exactly the value we were looking for, break off the
4397330f729Sjoerg     // search early.  There is no need to search the RHS of the value for
4407330f729Sjoerg     // partial results.
4417330f729Sjoerg     if (NumValsGreater != Node->getNumValuesUsed() &&
4427330f729Sjoerg         Node->getValue(NumValsGreater).FileLoc == FileIndex)
4437330f729Sjoerg       return Result+IN->getChild(NumValsGreater)->getFullDelta();
4447330f729Sjoerg 
4457330f729Sjoerg     // Otherwise, traverse down the tree.  The selected subtree may be
4467330f729Sjoerg     // partially included in the range.
4477330f729Sjoerg     Node = IN->getChild(NumValsGreater);
4487330f729Sjoerg   }
4497330f729Sjoerg   // NOT REACHED.
4507330f729Sjoerg }
4517330f729Sjoerg 
4527330f729Sjoerg /// AddDelta - When a change is made that shifts around the text buffer,
4537330f729Sjoerg /// this method is used to record that info.  It inserts a delta of 'Delta'
4547330f729Sjoerg /// into the current DeltaTree at offset FileIndex.
AddDelta(unsigned FileIndex,int Delta)4557330f729Sjoerg void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
4567330f729Sjoerg   assert(Delta && "Adding a noop?");
4577330f729Sjoerg   DeltaTreeNode *MyRoot = getRoot(Root);
4587330f729Sjoerg 
4597330f729Sjoerg   DeltaTreeNode::InsertResult InsertRes;
4607330f729Sjoerg   if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
461*e038c9c4Sjoerg     Root = new DeltaTreeInteriorNode(InsertRes);
462*e038c9c4Sjoerg #ifdef VERIFY_TREE
463*e038c9c4Sjoerg     MyRoot = Root;
464*e038c9c4Sjoerg #endif
4657330f729Sjoerg   }
4667330f729Sjoerg 
4677330f729Sjoerg #ifdef VERIFY_TREE
4687330f729Sjoerg   VerifyTree(MyRoot);
4697330f729Sjoerg #endif
4707330f729Sjoerg }
471