RewriteRope.cpp 30 KB

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