RewriteRope.cpp 30 KB

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