RewriteRope.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  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. RopePieceBTreeLeaf **PrevLeaf, *NextLeaf;
  132. public:
  133. RopePieceBTreeLeaf() : RopePieceBTreeNode(true), NumPieces(0),
  134. PrevLeaf(0), NextLeaf(0) {}
  135. ~RopePieceBTreeLeaf() {
  136. if (PrevLeaf || NextLeaf)
  137. removeFromLeafInOrder();
  138. }
  139. bool isFull() const { return NumPieces == 2*WidthFactor; }
  140. /// clear - Remove all rope pieces from this leaf.
  141. void clear() {
  142. while (NumPieces)
  143. Pieces[--NumPieces] = RopePiece();
  144. Size = 0;
  145. }
  146. unsigned getNumPieces() const { return NumPieces; }
  147. const RopePiece &getPiece(unsigned i) const {
  148. assert(i < getNumPieces() && "Invalid piece ID");
  149. return Pieces[i];
  150. }
  151. const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
  152. void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
  153. assert(PrevLeaf == 0 && NextLeaf == 0 && "Already in ordering");
  154. NextLeaf = Node->NextLeaf;
  155. if (NextLeaf)
  156. NextLeaf->PrevLeaf = &NextLeaf;
  157. PrevLeaf = &Node->NextLeaf;
  158. Node->NextLeaf = this;
  159. }
  160. void removeFromLeafInOrder() {
  161. if (PrevLeaf) {
  162. *PrevLeaf = NextLeaf;
  163. if (NextLeaf)
  164. NextLeaf->PrevLeaf = PrevLeaf;
  165. } else if (NextLeaf) {
  166. NextLeaf->PrevLeaf = 0;
  167. }
  168. }
  169. /// FullRecomputeSizeLocally - This method recomputes the 'Size' field by
  170. /// summing the size of all RopePieces.
  171. void FullRecomputeSizeLocally() {
  172. Size = 0;
  173. for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
  174. Size += getPiece(i).size();
  175. }
  176. /// split - Split the range containing the specified offset so that we are
  177. /// guaranteed that there is a place to do an insertion at the specified
  178. /// offset. The offset is relative, so "0" is the start of the node.
  179. ///
  180. /// If there is no space in this subtree for the extra piece, the extra tree
  181. /// node is returned and must be inserted into a parent.
  182. RopePieceBTreeNode *split(unsigned Offset);
  183. /// insert - Insert the specified ropepiece into this tree node at the
  184. /// specified offset. The offset is relative, so "0" is the start of the
  185. /// node.
  186. ///
  187. /// If there is no space in this subtree for the extra piece, the extra tree
  188. /// node is returned and must be inserted into a parent.
  189. RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
  190. /// erase - Remove NumBytes from this node at the specified offset. We are
  191. /// guaranteed that there is a split at Offset.
  192. void erase(unsigned Offset, unsigned NumBytes);
  193. static inline bool classof(const RopePieceBTreeLeaf *) { return true; }
  194. static inline bool classof(const RopePieceBTreeNode *N) {
  195. return N->isLeaf();
  196. }
  197. };
  198. } // end anonymous namespace
  199. /// split - Split the range containing the specified offset so that we are
  200. /// guaranteed that there is a place to do an insertion at the specified
  201. /// offset. The offset is relative, so "0" is the start of the node.
  202. ///
  203. /// If there is no space in this subtree for the extra piece, the extra tree
  204. /// node is returned and must be inserted into a parent.
  205. RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
  206. // Find the insertion point. We are guaranteed that there is a split at the
  207. // specified offset so find it.
  208. if (Offset == 0 || Offset == size()) {
  209. // Fastpath for a common case. There is already a splitpoint at the end.
  210. return 0;
  211. }
  212. // Find the piece that this offset lands in.
  213. unsigned PieceOffs = 0;
  214. unsigned i = 0;
  215. while (Offset >= PieceOffs+Pieces[i].size()) {
  216. PieceOffs += Pieces[i].size();
  217. ++i;
  218. }
  219. // If there is already a split point at the specified offset, just return
  220. // success.
  221. if (PieceOffs == Offset)
  222. return 0;
  223. // Otherwise, we need to split piece 'i' at Offset-PieceOffs. Convert Offset
  224. // to being Piece relative.
  225. unsigned IntraPieceOffset = Offset-PieceOffs;
  226. // We do this by shrinking the RopePiece and then doing an insert of the tail.
  227. RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset,
  228. Pieces[i].EndOffs);
  229. Size -= Pieces[i].size();
  230. Pieces[i].EndOffs = Pieces[i].StartOffs+IntraPieceOffset;
  231. Size += Pieces[i].size();
  232. return insert(Offset, Tail);
  233. }
  234. /// insert - Insert the specified RopePiece into this tree node at the
  235. /// specified offset. The offset is relative, so "0" is the start of the node.
  236. ///
  237. /// If there is no space in this subtree for the extra piece, the extra tree
  238. /// node is returned and must be inserted into a parent.
  239. RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
  240. const RopePiece &R) {
  241. // If this node is not full, insert the piece.
  242. if (!isFull()) {
  243. // Find the insertion point. We are guaranteed that there is a split at the
  244. // specified offset so find it.
  245. unsigned i = 0, e = getNumPieces();
  246. if (Offset == size()) {
  247. // Fastpath for a common case.
  248. i = e;
  249. } else {
  250. unsigned SlotOffs = 0;
  251. for (; Offset > SlotOffs; ++i)
  252. SlotOffs += getPiece(i).size();
  253. assert(SlotOffs == Offset && "Split didn't occur before insertion!");
  254. }
  255. // For an insertion into a non-full leaf node, just insert the value in
  256. // its sorted position. This requires moving later values over.
  257. for (; i != e; --e)
  258. Pieces[e] = Pieces[e-1];
  259. Pieces[i] = R;
  260. ++NumPieces;
  261. Size += R.size();
  262. return 0;
  263. }
  264. // Otherwise, if this is leaf is full, split it in two halves. Since this
  265. // node is full, it contains 2*WidthFactor values. We move the first
  266. // 'WidthFactor' values to the LHS child (which we leave in this node) and
  267. // move the last 'WidthFactor' values into the RHS child.
  268. // Create the new node.
  269. RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
  270. // Move over the last 'WidthFactor' values from here to NewNode.
  271. std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
  272. &NewNode->Pieces[0]);
  273. // Replace old pieces with null RopePieces to drop refcounts.
  274. std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor], RopePiece());
  275. // Decrease the number of values in the two nodes.
  276. NewNode->NumPieces = NumPieces = WidthFactor;
  277. // Recompute the two nodes' size.
  278. NewNode->FullRecomputeSizeLocally();
  279. FullRecomputeSizeLocally();
  280. // Update the list of leaves.
  281. NewNode->insertAfterLeafInOrder(this);
  282. // These insertions can't fail.
  283. if (this->size() >= Offset)
  284. this->insert(Offset, R);
  285. else
  286. NewNode->insert(Offset - this->size(), R);
  287. return NewNode;
  288. }
  289. /// erase - Remove NumBytes from this node at the specified offset. We are
  290. /// guaranteed that there is a split at Offset.
  291. void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
  292. // Since we are guaranteed that there is a split at Offset, we start by
  293. // finding the Piece that starts there.
  294. unsigned PieceOffs = 0;
  295. unsigned i = 0;
  296. for (; Offset > PieceOffs; ++i)
  297. PieceOffs += getPiece(i).size();
  298. assert(PieceOffs == Offset && "Split didn't occur before erase!");
  299. unsigned StartPiece = i;
  300. // Figure out how many pieces completely cover 'NumBytes'. We want to remove
  301. // all of them.
  302. for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i)
  303. PieceOffs += getPiece(i).size();
  304. // If we exactly include the last one, include it in the region to delete.
  305. if (Offset+NumBytes == PieceOffs+getPiece(i).size())
  306. PieceOffs += getPiece(i).size(), ++i;
  307. // If we completely cover some RopePieces, erase them now.
  308. if (i != StartPiece) {
  309. unsigned NumDeleted = i-StartPiece;
  310. for (; i != getNumPieces(); ++i)
  311. Pieces[i-NumDeleted] = Pieces[i];
  312. // Drop references to dead rope pieces.
  313. std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()],
  314. RopePiece());
  315. NumPieces -= NumDeleted;
  316. unsigned CoverBytes = PieceOffs-Offset;
  317. NumBytes -= CoverBytes;
  318. Size -= CoverBytes;
  319. }
  320. // If we completely removed some stuff, we could be done.
  321. if (NumBytes == 0) return;
  322. // Okay, now might be erasing part of some Piece. If this is the case, then
  323. // move the start point of the piece.
  324. assert(getPiece(StartPiece).size() > NumBytes);
  325. Pieces[StartPiece].StartOffs += NumBytes;
  326. // The size of this node just shrunk by NumBytes.
  327. Size -= NumBytes;
  328. }
  329. //===----------------------------------------------------------------------===//
  330. // RopePieceBTreeInterior Class
  331. //===----------------------------------------------------------------------===//
  332. namespace {
  333. /// RopePieceBTreeInterior - This represents an interior node in the B+Tree,
  334. /// which holds up to 2*WidthFactor pointers to child nodes.
  335. class RopePieceBTreeInterior : public RopePieceBTreeNode {
  336. /// NumChildren - This holds the number of children currently active in the
  337. /// Children array.
  338. unsigned char NumChildren;
  339. RopePieceBTreeNode *Children[2*WidthFactor];
  340. public:
  341. RopePieceBTreeInterior() : RopePieceBTreeNode(false), NumChildren(0) {}
  342. RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
  343. : RopePieceBTreeNode(false) {
  344. Children[0] = LHS;
  345. Children[1] = RHS;
  346. NumChildren = 2;
  347. Size = LHS->size() + RHS->size();
  348. }
  349. bool isFull() const { return NumChildren == 2*WidthFactor; }
  350. unsigned getNumChildren() const { return NumChildren; }
  351. const RopePieceBTreeNode *getChild(unsigned i) const {
  352. assert(i < NumChildren && "invalid child #");
  353. return Children[i];
  354. }
  355. RopePieceBTreeNode *getChild(unsigned i) {
  356. assert(i < NumChildren && "invalid child #");
  357. return Children[i];
  358. }
  359. /// FullRecomputeSizeLocally - Recompute the Size field of this node by
  360. /// summing up the sizes of the child nodes.
  361. void FullRecomputeSizeLocally() {
  362. Size = 0;
  363. for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
  364. Size += getChild(i)->size();
  365. }
  366. /// split - Split the range containing the specified offset so that we are
  367. /// guaranteed that there is a place to do an insertion at the specified
  368. /// offset. The offset is relative, so "0" is the start of the node.
  369. ///
  370. /// If there is no space in this subtree for the extra piece, the extra tree
  371. /// node is returned and must be inserted into a parent.
  372. RopePieceBTreeNode *split(unsigned Offset);
  373. /// insert - Insert the specified ropepiece into this tree node at the
  374. /// specified offset. The offset is relative, so "0" is the start of the
  375. /// node.
  376. ///
  377. /// If there is no space in this subtree for the extra piece, the extra tree
  378. /// node is returned and must be inserted into a parent.
  379. RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
  380. /// HandleChildPiece - A child propagated an insertion result up to us.
  381. /// Insert the new child, and/or propagate the result further up the tree.
  382. RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
  383. /// erase - Remove NumBytes from this node at the specified offset. We are
  384. /// guaranteed that there is a split at Offset.
  385. void erase(unsigned Offset, unsigned NumBytes);
  386. static inline bool classof(const RopePieceBTreeInterior *) { return true; }
  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 0; // 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 0;
  409. // Otherwise, recursively split the child.
  410. if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
  411. return HandleChildPiece(i, RHS);
  412. return 0; // 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 0;
  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 false;
  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 != 0)
  576. CurPiece = &getCN(CurNode)->getPiece(0);
  577. else // Empty tree, this is an end() iterator.
  578. CurPiece = 0;
  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 != 0)
  592. CurPiece = &getCN(CurNode)->getPiece(0);
  593. else // Hit end().
  594. CurPiece = 0;
  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. // If we had an old allocation, drop our reference to it.
  668. if (AllocBuffer && --AllocBuffer->RefCount == 0)
  669. delete [] (char*)AllocBuffer;
  670. unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
  671. AllocBuffer = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
  672. AllocBuffer->RefCount = 0;
  673. memcpy(AllocBuffer->Data, Start, Len);
  674. AllocOffs = Len;
  675. // Start out the new allocation with a refcount of 1, since we have an
  676. // internal reference to it.
  677. AllocBuffer->addRef();
  678. return RopePiece(AllocBuffer, 0, Len);
  679. }