RewriteRope.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  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/RewriteRope.h"
  14. #include "llvm/Support/Casting.h"
  15. #include <algorithm>
  16. using namespace clang;
  17. using llvm::dyn_cast;
  18. using llvm::cast;
  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 contatenated.
  59. /// RopePieceBTreeInterior - An interior node in the B+ Tree, which manages
  60. /// up to '2*WidthFactor' other nodes in the tree.
  61. //===----------------------------------------------------------------------===//
  62. // RopePieceBTreeNode Class
  63. //===----------------------------------------------------------------------===//
  64. namespace {
  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;
  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) : Size(0), IsLeaf(isLeaf) {}
  86. ~RopePieceBTreeNode() {}
  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. static inline bool classof(const RopePieceBTreeNode *) { return true; }
  109. };
  110. } // end anonymous namespace
  111. //===----------------------------------------------------------------------===//
  112. // RopePieceBTreeLeaf Class
  113. //===----------------------------------------------------------------------===//
  114. namespace {
  115. /// RopePieceBTreeLeaf - Directly manages up to '2*WidthFactor' RopePiece
  116. /// nodes. This directly represents a chunk of the string with those
  117. /// RopePieces contatenated. Since this is a B+Tree, all values (in this case
  118. /// instances of RopePiece) are stored in leaves like this. To make iteration
  119. /// over the leaves efficient, they maintain a singly linked list through the
  120. /// NextLeaf field. This allows the B+Tree forward iterator to be constant
  121. /// time for all increments.
  122. class RopePieceBTreeLeaf : public RopePieceBTreeNode {
  123. /// NumPieces - This holds the number of rope pieces currently active in the
  124. /// Pieces array.
  125. unsigned char NumPieces;
  126. /// Pieces - This tracks the file chunks currently in this leaf.
  127. ///
  128. RopePiece Pieces[2*WidthFactor];
  129. /// NextLeaf - This is a pointer to the next leaf in the tree, allowing
  130. /// efficient in-order forward iteration of the tree without traversal.
  131. const RopePieceBTreeLeaf *NextLeaf;
  132. public:
  133. RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0), NextLeaf(0){}
  134. bool isFull() const { return NumPieces == 2*WidthFactor; }
  135. /// clear - Remove all rope pieces from this leaf.
  136. void clear() {
  137. while (NumPieces)
  138. Pieces[--NumPieces] = RopePiece();
  139. Size = 0;
  140. }
  141. unsigned getNumPieces() const { return NumPieces; }
  142. const RopePiece &getPiece(unsigned i) const {
  143. assert(i < getNumPieces() && "Invalid piece ID");
  144. return Pieces[i];
  145. }
  146. const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
  147. void setNextLeafInOrder(const RopePieceBTreeLeaf *NL) { NextLeaf = NL; }
  148. /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
  149. /// summing the size of all RopePieces.
  150. void FullRecomputeSizeLocally() {
  151. Size = 0;
  152. for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
  153. Size += getPiece(i).size();
  154. }
  155. /// split - Split the range containing the specified offset so that we are
  156. /// guaranteed that there is a place to do an insertion at the specified
  157. /// offset. The offset is relative, so "0" is the start of the node.
  158. ///
  159. /// If there is no space in this subtree for the extra piece, the extra tree
  160. /// node is returned and must be inserted into a parent.
  161. RopePieceBTreeNode *split(unsigned Offset);
  162. /// insert - Insert the specified ropepiece into this tree node at the
  163. /// specified offset. The offset is relative, so "0" is the start of the
  164. /// node.
  165. ///
  166. /// If there is no space in this subtree for the extra piece, the extra tree
  167. /// node is returned and must be inserted into a parent.
  168. RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
  169. /// erase - Remove NumBytes from this node at the specified offset. We are
  170. /// guaranteed that there is a split at Offset.
  171. void erase(unsigned Offset, unsigned NumBytes);
  172. static inline bool classof(const RopePieceBTreeLeaf *) { return true; }
  173. static inline bool classof(const RopePieceBTreeNode *N) {
  174. return N->isLeaf();
  175. }
  176. };
  177. } // end anonymous namespace
  178. /// split - Split the range containing the specified offset so that we are
  179. /// guaranteed that there is a place to do an insertion at the specified
  180. /// offset. The offset is relative, so "0" is the start of the node.
  181. ///
  182. /// If there is no space in this subtree for the extra piece, the extra tree
  183. /// node is returned and must be inserted into a parent.
  184. RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
  185. // Find the insertion point. We are guaranteed that there is a split at the
  186. // specified offset so find it.
  187. if (Offset == 0 || Offset == size()) {
  188. // Fastpath for a common case. There is already a splitpoint at the end.
  189. return 0;
  190. }
  191. // Find the piece that this offset lands in.
  192. unsigned PieceOffs = 0;
  193. unsigned i = 0;
  194. while (Offset >= PieceOffs+Pieces[i].size()) {
  195. PieceOffs += Pieces[i].size();
  196. ++i;
  197. }
  198. // If there is already a split point at the specified offset, just return
  199. // success.
  200. if (PieceOffs == Offset)
  201. return 0;
  202. // Otherwise, we need to split piece 'i' at Offset-PieceOffs. Convert Offset
  203. // to being Piece relative.
  204. unsigned IntraPieceOffset = Offset-PieceOffs;
  205. // We do this by shrinking the RopePiece and then doing an insert of the tail.
  206. RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset,
  207. Pieces[i].EndOffs);
  208. Size -= Pieces[i].size();
  209. Pieces[i].EndOffs = Pieces[i].StartOffs+IntraPieceOffset;
  210. Size += Pieces[i].size();
  211. return insert(Offset, Tail);
  212. }
  213. /// insert - Insert the specified RopePiece into this tree node at the
  214. /// specified offset. The offset is relative, so "0" is the start of the node.
  215. ///
  216. /// If there is no space in this subtree for the extra piece, the extra tree
  217. /// node is returned and must be inserted into a parent.
  218. RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
  219. const RopePiece &R) {
  220. // If this node is not full, insert the piece.
  221. if (!isFull()) {
  222. // Find the insertion point. We are guaranteed that there is a split at the
  223. // specified offset so find it.
  224. unsigned i = 0, e = getNumPieces();
  225. if (Offset == size()) {
  226. // Fastpath for a common case.
  227. i = e;
  228. } else {
  229. unsigned SlotOffs = 0;
  230. for (; Offset > SlotOffs; ++i)
  231. SlotOffs += getPiece(i).size();
  232. assert(SlotOffs == Offset && "Split didn't occur before insertion!");
  233. }
  234. // For an insertion into a non-full leaf node, just insert the value in
  235. // its sorted position. This requires moving later values over.
  236. for (; i != e; --e)
  237. Pieces[e] = Pieces[e-1];
  238. Pieces[i] = R;
  239. ++NumPieces;
  240. Size += R.size();
  241. return 0;
  242. }
  243. // Otherwise, if this is leaf is full, split it in two halves. Since this
  244. // node is full, it contains 2*WidthFactor values. We move the first
  245. // 'WidthFactor' values to the LHS child (which we leave in this node) and
  246. // move the last 'WidthFactor' values into the RHS child.
  247. // Create the new node.
  248. RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
  249. // Move over the last 'WidthFactor' values from here to NewNode.
  250. std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
  251. &NewNode->Pieces[0]);
  252. // Replace old pieces with null RopePieces to drop refcounts.
  253. std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor], RopePiece());
  254. // Decrease the number of values in the two nodes.
  255. NewNode->NumPieces = NumPieces = WidthFactor;
  256. // Recompute the two nodes' size.
  257. NewNode->FullRecomputeSizeLocally();
  258. FullRecomputeSizeLocally();
  259. // Update the list of leaves.
  260. NewNode->setNextLeafInOrder(this->getNextLeafInOrder());
  261. this->setNextLeafInOrder(NewNode);
  262. // These insertions can't fail.
  263. if (this->size() >= Offset)
  264. this->insert(Offset, R);
  265. else
  266. NewNode->insert(Offset - this->size(), R);
  267. return NewNode;
  268. }
  269. /// erase - Remove NumBytes from this node at the specified offset. We are
  270. /// guaranteed that there is a split at Offset.
  271. void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
  272. // Since we are guaranteed that there is a split at Offset, we start by
  273. // finding the Piece that starts there.
  274. unsigned PieceOffs = 0;
  275. unsigned i = 0;
  276. for (; Offset > PieceOffs; ++i)
  277. PieceOffs += getPiece(i).size();
  278. assert(PieceOffs == Offset && "Split didn't occur before erase!");
  279. unsigned StartPiece = i;
  280. // Figure out how many pieces completely cover 'NumBytes'. We want to remove
  281. // all of them.
  282. for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i)
  283. PieceOffs += getPiece(i).size();
  284. // If we exactly include the last one, include it in the region to delete.
  285. if (Offset+NumBytes == PieceOffs+getPiece(i).size())
  286. PieceOffs += getPiece(i).size(), ++i;
  287. // If we completely cover some RopePieces, erase them now.
  288. if (i != StartPiece) {
  289. unsigned NumDeleted = i-StartPiece;
  290. for (; i != getNumPieces(); ++i)
  291. Pieces[i-NumDeleted] = Pieces[i];
  292. // Drop references to dead rope pieces.
  293. std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()],
  294. RopePiece());
  295. NumPieces -= NumDeleted;
  296. unsigned CoverBytes = PieceOffs-Offset;
  297. NumBytes -= CoverBytes;
  298. Size -= CoverBytes;
  299. }
  300. // If we completely removed some stuff, we could be done.
  301. if (NumBytes == 0) return;
  302. // Okay, now might be erasing part of some Piece. If this is the case, then
  303. // move the start point of the piece.
  304. assert(getPiece(StartPiece).size() > NumBytes);
  305. Pieces[StartPiece].StartOffs += NumBytes;
  306. // The size of this node just shrunk by NumBytes.
  307. Size -= NumBytes;
  308. }
  309. //===----------------------------------------------------------------------===//
  310. // RopePieceBTreeInterior Class
  311. //===----------------------------------------------------------------------===//
  312. namespace {
  313. /// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
  314. /// which holds up to 2*WidthFactor pointers to child nodes.
  315. class RopePieceBTreeInterior : public RopePieceBTreeNode {
  316. /// NumChildren - This holds the number of children currently active in the
  317. /// Children array.
  318. unsigned char NumChildren;
  319. RopePieceBTreeNode *Children[2*WidthFactor];
  320. public:
  321. RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
  322. RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
  323. : RopePieceBTreeNode(false) {
  324. Children[0] = LHS;
  325. Children[1] = RHS;
  326. NumChildren = 2;
  327. Size = LHS->size() + RHS->size();
  328. }
  329. bool isFull() const { return NumChildren == 2*WidthFactor; }
  330. unsigned getNumChildren() const { return NumChildren; }
  331. const RopePieceBTreeNode *getChild(unsigned i) const {
  332. assert(i < NumChildren && "invalid child #");
  333. return Children[i];
  334. }
  335. RopePieceBTreeNode *getChild(unsigned i) {
  336. assert(i < NumChildren && "invalid child #");
  337. return Children[i];
  338. }
  339. /// FullRecomputeSizeLocally - Recompute the Size field of this node by
  340. /// summing up the sizes of the child nodes.
  341. void FullRecomputeSizeLocally() {
  342. Size = 0;
  343. for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
  344. Size += getChild(i)->size();
  345. }
  346. /// split - Split the range containing the specified offset so that we are
  347. /// guaranteed that there is a place to do an insertion at the specified
  348. /// offset. The offset is relative, so "0" is the start of the node.
  349. ///
  350. /// If there is no space in this subtree for the extra piece, the extra tree
  351. /// node is returned and must be inserted into a parent.
  352. RopePieceBTreeNode *split(unsigned Offset);
  353. /// insert - Insert the specified ropepiece into this tree node at the
  354. /// specified offset. The offset is relative, so "0" is the start of the
  355. /// node.
  356. ///
  357. /// If there is no space in this subtree for the extra piece, the extra tree
  358. /// node is returned and must be inserted into a parent.
  359. RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
  360. /// HandleChildPiece - A child propagated an insertion result up to us.
  361. /// Insert the new child, and/or propagate the result further up the tree.
  362. RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
  363. /// erase - Remove NumBytes from this node at the specified offset. We are
  364. /// guaranteed that there is a split at Offset.
  365. void erase(unsigned Offset, unsigned NumBytes);
  366. static inline bool classof(const RopePieceBTreeInterior *) { return true; }
  367. static inline bool classof(const RopePieceBTreeNode *N) {
  368. return !N->isLeaf();
  369. }
  370. };
  371. } // end anonymous namespace
  372. /// split - Split the range containing the specified offset so that we are
  373. /// guaranteed that there is a place to do an insertion at the specified
  374. /// offset. The offset is relative, so "0" is the start of the node.
  375. ///
  376. /// If there is no space in this subtree for the extra piece, the extra tree
  377. /// node is returned and must be inserted into a parent.
  378. RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
  379. // Figure out which child to split.
  380. if (Offset == 0 || Offset == size())
  381. return 0; // If we have an exact offset, we're already split.
  382. unsigned ChildOffset = 0;
  383. unsigned i = 0;
  384. for (; Offset >= ChildOffset+getChild(i)->size(); ++i)
  385. ChildOffset += getChild(i)->size();
  386. // If already split there, we're done.
  387. if (ChildOffset == Offset)
  388. return 0;
  389. // Otherwise, recursively split the child.
  390. if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
  391. return HandleChildPiece(i, RHS);
  392. return 0; // Done!
  393. }
  394. /// insert - Insert the specified ropepiece into this tree node at the
  395. /// specified offset. The offset is relative, so "0" is the start of the
  396. /// node.
  397. ///
  398. /// If there is no space in this subtree for the extra piece, the extra tree
  399. /// node is returned and must be inserted into a parent.
  400. RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset,
  401. const RopePiece &R) {
  402. // Find the insertion point. We are guaranteed that there is a split at the
  403. // specified offset so find it.
  404. unsigned i = 0, e = getNumChildren();
  405. unsigned ChildOffs = 0;
  406. if (Offset == size()) {
  407. // Fastpath for a common case. Insert at end of last child.
  408. i = e-1;
  409. ChildOffs = size()-getChild(i)->size();
  410. } else {
  411. for (; Offset > ChildOffs+getChild(i)->size(); ++i)
  412. ChildOffs += getChild(i)->size();
  413. }
  414. Size += R.size();
  415. // Insert at the end of this child.
  416. if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R))
  417. return HandleChildPiece(i, RHS);
  418. return 0;
  419. }
  420. /// HandleChildPiece - A child propagated an insertion result up to us.
  421. /// Insert the new child, and/or propagate the result further up the tree.
  422. RopePieceBTreeNode *
  423. RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) {
  424. // Otherwise the child propagated a subtree up to us as a new child. See if
  425. // we have space for it here.
  426. if (!isFull()) {
  427. // Insert RHS after child 'i'.
  428. if (i + 1 != getNumChildren())
  429. memmove(&Children[i+2], &Children[i+1],
  430. (getNumChildren()-i-1)*sizeof(Children[0]));
  431. Children[i+1] = RHS;
  432. ++NumChildren;
  433. return false;
  434. }
  435. // Okay, this node is full. Split it in half, moving WidthFactor children to
  436. // a newly allocated interior node.
  437. // Create the new node.
  438. RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior();
  439. // Move over the last 'WidthFactor' values from here to NewNode.
  440. memcpy(&NewNode->Children[0], &Children[WidthFactor],
  441. WidthFactor*sizeof(Children[0]));
  442. // Decrease the number of values in the two nodes.
  443. NewNode->NumChildren = NumChildren = WidthFactor;
  444. // Finally, insert the two new children in the side the can (now) hold them.
  445. // These insertions can't fail.
  446. if (i < WidthFactor)
  447. this->HandleChildPiece(i, RHS);
  448. else
  449. NewNode->HandleChildPiece(i-WidthFactor, RHS);
  450. // Recompute the two nodes' size.
  451. NewNode->FullRecomputeSizeLocally();
  452. FullRecomputeSizeLocally();
  453. return NewNode;
  454. }
  455. /// erase - Remove NumBytes from this node at the specified offset. We are
  456. /// guaranteed that there is a split at Offset.
  457. void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
  458. // This will shrink this node by NumBytes.
  459. Size -= NumBytes;
  460. // Find the first child that overlaps with Offset.
  461. unsigned i = 0;
  462. for (; Offset >= getChild(i)->size(); ++i)
  463. Offset -= getChild(i)->size();
  464. // Propagate the delete request into overlapping children, or completely
  465. // delete the children as appropriate.
  466. while (NumBytes) {
  467. RopePieceBTreeNode *CurChild = getChild(i);
  468. // If we are deleting something contained entirely in the child, pass on the
  469. // request.
  470. if (Offset+NumBytes < CurChild->size()) {
  471. CurChild->erase(Offset, NumBytes);
  472. return;
  473. }
  474. // If this deletion request starts somewhere in the middle of the child, it
  475. // must be deleting to the end of the child.
  476. if (Offset) {
  477. unsigned BytesFromChild = CurChild->size()-Offset;
  478. CurChild->erase(Offset, BytesFromChild);
  479. NumBytes -= BytesFromChild;
  480. ++i;
  481. continue;
  482. }
  483. // If the deletion request completely covers the child, delete it and move
  484. // the rest down.
  485. NumBytes -= CurChild->size();
  486. CurChild->Destroy();
  487. --NumChildren;
  488. if (i+1 != getNumChildren())
  489. memmove(&Children[i], &Children[i+1],
  490. (getNumChildren()-i)*sizeof(Children[0]));
  491. }
  492. }
  493. //===----------------------------------------------------------------------===//
  494. // RopePieceBTreeNode Implementation
  495. //===----------------------------------------------------------------------===//
  496. void RopePieceBTreeNode::Destroy() {
  497. if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
  498. delete Leaf;
  499. else
  500. delete cast<RopePieceBTreeInterior>(this);
  501. }
  502. /// split - Split the range containing the specified offset so that we are
  503. /// guaranteed that there is a place to do an insertion at the specified
  504. /// offset. The offset is relative, so "0" is the start of the node.
  505. ///
  506. /// If there is no space in this subtree for the extra piece, the extra tree
  507. /// node is returned and must be inserted into a parent.
  508. RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
  509. assert(Offset <= size() && "Invalid offset to split!");
  510. if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
  511. return Leaf->split(Offset);
  512. return cast<RopePieceBTreeInterior>(this)->split(Offset);
  513. }
  514. /// insert - Insert the specified ropepiece into this tree node at the
  515. /// specified offset. The offset is relative, so "0" is the start of the
  516. /// node.
  517. ///
  518. /// If there is no space in this subtree for the extra piece, the extra tree
  519. /// node is returned and must be inserted into a parent.
  520. RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
  521. const RopePiece &R) {
  522. assert(Offset <= size() && "Invalid offset to insert!");
  523. if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
  524. return Leaf->insert(Offset, R);
  525. return cast<RopePieceBTreeInterior>(this)->insert(Offset, R);
  526. }
  527. /// erase - Remove NumBytes from this node at the specified offset. We are
  528. /// guaranteed that there is a split at Offset.
  529. void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
  530. assert(Offset+NumBytes <= size() && "Invalid offset to erase!");
  531. if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(this))
  532. return Leaf->erase(Offset, NumBytes);
  533. return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes);
  534. }
  535. //===----------------------------------------------------------------------===//
  536. // RopePieceBTreeIterator Implementation
  537. //===----------------------------------------------------------------------===//
  538. static const RopePieceBTreeLeaf *getCN(const void *P) {
  539. return static_cast<const RopePieceBTreeLeaf*>(P);
  540. }
  541. // begin iterator.
  542. RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) {
  543. const RopePieceBTreeNode *N = static_cast<const RopePieceBTreeNode*>(n);
  544. // Walk down the left side of the tree until we get to a leaf.
  545. while (const RopePieceBTreeInterior *IN = dyn_cast<RopePieceBTreeInterior>(N))
  546. N = IN->getChild(0);
  547. // We must have at least one leaf.
  548. CurNode = cast<RopePieceBTreeLeaf>(N);
  549. // If we found a leaf that happens to be empty, skip over it until we get
  550. // to something full.
  551. while (CurNode && getCN(CurNode)->getNumPieces() == 0)
  552. CurNode = getCN(CurNode)->getNextLeafInOrder();
  553. if (CurNode != 0)
  554. CurPiece = &getCN(CurNode)->getPiece(0);
  555. else // Empty tree, this is an end() iterator.
  556. CurPiece = 0;
  557. CurChar = 0;
  558. }
  559. void RopePieceBTreeIterator::MoveToNextPiece() {
  560. if (CurPiece != &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces()-1)) {
  561. CurChar = 0;
  562. ++CurPiece;
  563. return;
  564. }
  565. // Find the next non-empty leaf node.
  566. do
  567. CurNode = getCN(CurNode)->getNextLeafInOrder();
  568. while (CurNode && getCN(CurNode)->getNumPieces() == 0);
  569. if (CurNode != 0)
  570. CurPiece = &getCN(CurNode)->getPiece(0);
  571. else // Hit end().
  572. CurPiece = 0;
  573. CurChar = 0;
  574. }
  575. //===----------------------------------------------------------------------===//
  576. // RopePieceBTree Implementation
  577. //===----------------------------------------------------------------------===//
  578. static RopePieceBTreeNode *getRoot(void *P) {
  579. return static_cast<RopePieceBTreeNode*>(P);
  580. }
  581. RopePieceBTree::RopePieceBTree() {
  582. Root = new RopePieceBTreeLeaf();
  583. }
  584. RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) {
  585. assert(RHS.empty() && "Can't copy non-empty tree yet");
  586. Root = new RopePieceBTreeLeaf();
  587. }
  588. RopePieceBTree::~RopePieceBTree() {
  589. getRoot(Root)->Destroy();
  590. }
  591. unsigned RopePieceBTree::size() const {
  592. return getRoot(Root)->size();
  593. }
  594. void RopePieceBTree::clear() {
  595. if (RopePieceBTreeLeaf *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root)))
  596. Leaf->clear();
  597. else {
  598. getRoot(Root)->Destroy();
  599. Root = new RopePieceBTreeLeaf();
  600. }
  601. }
  602. void RopePieceBTree::insert(unsigned Offset, const RopePiece &R) {
  603. // #1. Split at Offset.
  604. if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
  605. Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
  606. // #2. Do the insertion.
  607. if (RopePieceBTreeNode *RHS = getRoot(Root)->insert(Offset, R))
  608. Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
  609. }
  610. void RopePieceBTree::erase(unsigned Offset, unsigned NumBytes) {
  611. // #1. Split at Offset.
  612. if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset))
  613. Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
  614. // #2. Do the erasing.
  615. getRoot(Root)->erase(Offset, NumBytes);
  616. }
  617. //===----------------------------------------------------------------------===//
  618. // RewriteRope Implementation
  619. //===----------------------------------------------------------------------===//
  620. /// MakeRopeString - This copies the specified byte range into some instance of
  621. /// RopeRefCountString, and return a RopePiece that represents it. This uses
  622. /// the AllocBuffer object to aggregate requests for small strings into one
  623. /// allocation instead of doing tons of tiny allocations.
  624. RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
  625. unsigned Len = End-Start;
  626. // If we have space for this string in the current alloc buffer, use it.
  627. if (AllocOffs+Len <= AllocChunkSize) {
  628. memcpy(AllocBuffer->Data+AllocOffs, Start, Len);
  629. AllocOffs += Len;
  630. return RopePiece(AllocBuffer, AllocOffs-Len, AllocOffs);
  631. }
  632. // If we don't have enough room because this specific allocation is huge,
  633. // just allocate a new rope piece for it alone.
  634. if (Len > AllocChunkSize) {
  635. unsigned Size = End-Start+sizeof(RopeRefCountString)-1;
  636. RopeRefCountString *Res =
  637. reinterpret_cast<RopeRefCountString *>(new char[Size]);
  638. Res->RefCount = 0;
  639. memcpy(Res->Data, Start, End-Start);
  640. return RopePiece(Res, 0, End-Start);
  641. }
  642. // Otherwise, this was a small request but we just don't have space for it
  643. // Make a new chunk and share it with later allocations.
  644. // If we had an old allocation, drop our reference to it.
  645. if (AllocBuffer && --AllocBuffer->RefCount == 0)
  646. delete [] (char*)AllocBuffer;
  647. unsigned AllocSize = sizeof(RopeRefCountString)-1+AllocChunkSize;
  648. AllocBuffer = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
  649. AllocBuffer->RefCount = 0;
  650. memcpy(AllocBuffer->Data, Start, Len);
  651. AllocOffs = Len;
  652. // Start out the new allocation with a refcount of 1, since we have an
  653. // internal reference to it.
  654. AllocBuffer->addRef();
  655. return RopePiece(AllocBuffer, 0, Len);
  656. }