1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Rewrite/Core/RewriteRope.h" |
14 | #include "clang/Basic/LLVM.h" |
15 | #include "llvm/Support/Casting.h" |
16 | #include <algorithm> |
17 | #include <cassert> |
18 | #include <cstring> |
19 | |
20 | using namespace clang; |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | namespace { |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | class RopePieceBTreeNode { |
78 | protected: |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | enum { WidthFactor = 8 }; |
85 | |
86 | |
87 | |
88 | unsigned Size = 0; |
89 | |
90 | |
91 | |
92 | bool IsLeaf; |
93 | |
94 | RopePieceBTreeNode(bool isLeaf) : IsLeaf(isLeaf) {} |
95 | ~RopePieceBTreeNode() = default; |
96 | |
97 | public: |
98 | bool isLeaf() const { return IsLeaf; } |
99 | unsigned size() const { return Size; } |
100 | |
101 | void Destroy(); |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | RopePieceBTreeNode *split(unsigned Offset); |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R); |
118 | |
119 | |
120 | |
121 | void erase(unsigned Offset, unsigned NumBytes); |
122 | }; |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | class RopePieceBTreeLeaf : public RopePieceBTreeNode { |
136 | |
137 | |
138 | unsigned char NumPieces = 0; |
139 | |
140 | |
141 | RopePiece Pieces[2*WidthFactor]; |
142 | |
143 | |
144 | |
145 | RopePieceBTreeLeaf **PrevLeaf = nullptr; |
146 | RopePieceBTreeLeaf *NextLeaf = nullptr; |
147 | |
148 | public: |
149 | RopePieceBTreeLeaf() : RopePieceBTreeNode(true) {} |
150 | |
151 | ~RopePieceBTreeLeaf() { |
152 | if (PrevLeaf || NextLeaf) |
153 | removeFromLeafInOrder(); |
154 | clear(); |
155 | } |
156 | |
157 | bool isFull() const { return NumPieces == 2*WidthFactor; } |
158 | |
159 | |
160 | void clear() { |
161 | while (NumPieces) |
162 | Pieces[--NumPieces] = RopePiece(); |
163 | Size = 0; |
164 | } |
165 | |
166 | unsigned getNumPieces() const { return NumPieces; } |
167 | |
168 | const RopePiece &getPiece(unsigned i) const { |
169 | (0) . __assert_fail ("i < getNumPieces() && \"Invalid piece ID\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 169, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(i < getNumPieces() && "Invalid piece ID"); |
170 | return Pieces[i]; |
171 | } |
172 | |
173 | const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; } |
174 | |
175 | void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) { |
176 | (0) . __assert_fail ("!PrevLeaf && !NextLeaf && \"Already in ordering\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 176, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!PrevLeaf && !NextLeaf && "Already in ordering"); |
177 | |
178 | NextLeaf = Node->NextLeaf; |
179 | if (NextLeaf) |
180 | NextLeaf->PrevLeaf = &NextLeaf; |
181 | PrevLeaf = &Node->NextLeaf; |
182 | Node->NextLeaf = this; |
183 | } |
184 | |
185 | void removeFromLeafInOrder() { |
186 | if (PrevLeaf) { |
187 | *PrevLeaf = NextLeaf; |
188 | if (NextLeaf) |
189 | NextLeaf->PrevLeaf = PrevLeaf; |
190 | } else if (NextLeaf) { |
191 | NextLeaf->PrevLeaf = nullptr; |
192 | } |
193 | } |
194 | |
195 | |
196 | |
197 | void FullRecomputeSizeLocally() { |
198 | Size = 0; |
199 | for (unsigned i = 0, e = getNumPieces(); i != e; ++i) |
200 | Size += getPiece(i).size(); |
201 | } |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | RopePieceBTreeNode *split(unsigned Offset); |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R); |
218 | |
219 | |
220 | |
221 | void erase(unsigned Offset, unsigned NumBytes); |
222 | |
223 | static bool classof(const RopePieceBTreeNode *N) { |
224 | return N->isLeaf(); |
225 | } |
226 | }; |
227 | |
228 | } |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) { |
237 | |
238 | |
239 | if (Offset == 0 || Offset == size()) { |
240 | |
241 | return nullptr; |
242 | } |
243 | |
244 | |
245 | unsigned PieceOffs = 0; |
246 | unsigned i = 0; |
247 | while (Offset >= PieceOffs+Pieces[i].size()) { |
248 | PieceOffs += Pieces[i].size(); |
249 | ++i; |
250 | } |
251 | |
252 | |
253 | |
254 | if (PieceOffs == Offset) |
255 | return nullptr; |
256 | |
257 | |
258 | |
259 | unsigned IntraPieceOffset = Offset-PieceOffs; |
260 | |
261 | |
262 | RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset, |
263 | Pieces[i].EndOffs); |
264 | Size -= Pieces[i].size(); |
265 | Pieces[i].EndOffs = Pieces[i].StartOffs+IntraPieceOffset; |
266 | Size += Pieces[i].size(); |
267 | |
268 | return insert(Offset, Tail); |
269 | } |
270 | |
271 | |
272 | |
273 | |
274 | |
275 | |
276 | RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset, |
277 | const RopePiece &R) { |
278 | |
279 | if (!isFull()) { |
280 | |
281 | |
282 | unsigned i = 0, e = getNumPieces(); |
283 | if (Offset == size()) { |
284 | |
285 | i = e; |
286 | } else { |
287 | unsigned SlotOffs = 0; |
288 | for (; Offset > SlotOffs; ++i) |
289 | SlotOffs += getPiece(i).size(); |
290 | (0) . __assert_fail ("SlotOffs == Offset && \"Split didn't occur before insertion!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 290, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(SlotOffs == Offset && "Split didn't occur before insertion!"); |
291 | } |
292 | |
293 | |
294 | |
295 | for (; i != e; --e) |
296 | Pieces[e] = Pieces[e-1]; |
297 | Pieces[i] = R; |
298 | ++NumPieces; |
299 | Size += R.size(); |
300 | return nullptr; |
301 | } |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf(); |
310 | |
311 | |
312 | std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor], |
313 | &NewNode->Pieces[0]); |
314 | |
315 | std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor], RopePiece()); |
316 | |
317 | |
318 | NewNode->NumPieces = NumPieces = WidthFactor; |
319 | |
320 | |
321 | NewNode->FullRecomputeSizeLocally(); |
322 | FullRecomputeSizeLocally(); |
323 | |
324 | |
325 | NewNode->insertAfterLeafInOrder(this); |
326 | |
327 | |
328 | if (this->size() >= Offset) |
329 | this->insert(Offset, R); |
330 | else |
331 | NewNode->insert(Offset - this->size(), R); |
332 | return NewNode; |
333 | } |
334 | |
335 | |
336 | |
337 | void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) { |
338 | |
339 | |
340 | unsigned PieceOffs = 0; |
341 | unsigned i = 0; |
342 | for (; Offset > PieceOffs; ++i) |
343 | PieceOffs += getPiece(i).size(); |
344 | (0) . __assert_fail ("PieceOffs == Offset && \"Split didn't occur before erase!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 344, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PieceOffs == Offset && "Split didn't occur before erase!"); |
345 | |
346 | unsigned StartPiece = i; |
347 | |
348 | |
349 | |
350 | for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i) |
351 | PieceOffs += getPiece(i).size(); |
352 | |
353 | |
354 | if (Offset+NumBytes == PieceOffs+getPiece(i).size()) { |
355 | PieceOffs += getPiece(i).size(); |
356 | ++i; |
357 | } |
358 | |
359 | |
360 | if (i != StartPiece) { |
361 | unsigned NumDeleted = i-StartPiece; |
362 | for (; i != getNumPieces(); ++i) |
363 | Pieces[i-NumDeleted] = Pieces[i]; |
364 | |
365 | |
366 | std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()], |
367 | RopePiece()); |
368 | NumPieces -= NumDeleted; |
369 | |
370 | unsigned CoverBytes = PieceOffs-Offset; |
371 | NumBytes -= CoverBytes; |
372 | Size -= CoverBytes; |
373 | } |
374 | |
375 | |
376 | if (NumBytes == 0) return; |
377 | |
378 | |
379 | |
380 | NumBytes", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 380, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(getPiece(StartPiece).size() > NumBytes); |
381 | Pieces[StartPiece].StartOffs += NumBytes; |
382 | |
383 | |
384 | Size -= NumBytes; |
385 | } |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | namespace { |
392 | |
393 | |
394 | |
395 | class RopePieceBTreeInterior : public RopePieceBTreeNode { |
396 | |
397 | |
398 | unsigned char NumChildren = 0; |
399 | |
400 | RopePieceBTreeNode *Children[2*WidthFactor]; |
401 | |
402 | public: |
403 | RopePieceBTreeInterior() : RopePieceBTreeNode(false) {} |
404 | |
405 | RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS) |
406 | : RopePieceBTreeNode(false) { |
407 | Children[0] = LHS; |
408 | Children[1] = RHS; |
409 | NumChildren = 2; |
410 | Size = LHS->size() + RHS->size(); |
411 | } |
412 | |
413 | ~RopePieceBTreeInterior() { |
414 | for (unsigned i = 0, e = getNumChildren(); i != e; ++i) |
415 | Children[i]->Destroy(); |
416 | } |
417 | |
418 | bool isFull() const { return NumChildren == 2*WidthFactor; } |
419 | |
420 | unsigned getNumChildren() const { return NumChildren; } |
421 | |
422 | const RopePieceBTreeNode *getChild(unsigned i) const { |
423 | (0) . __assert_fail ("i < NumChildren && \"invalid child #\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 423, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(i < NumChildren && "invalid child #"); |
424 | return Children[i]; |
425 | } |
426 | |
427 | RopePieceBTreeNode *getChild(unsigned i) { |
428 | (0) . __assert_fail ("i < NumChildren && \"invalid child #\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 428, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(i < NumChildren && "invalid child #"); |
429 | return Children[i]; |
430 | } |
431 | |
432 | |
433 | |
434 | void FullRecomputeSizeLocally() { |
435 | Size = 0; |
436 | for (unsigned i = 0, e = getNumChildren(); i != e; ++i) |
437 | Size += getChild(i)->size(); |
438 | } |
439 | |
440 | |
441 | |
442 | |
443 | |
444 | |
445 | |
446 | RopePieceBTreeNode *split(unsigned Offset); |
447 | |
448 | |
449 | |
450 | |
451 | |
452 | |
453 | |
454 | RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R); |
455 | |
456 | |
457 | |
458 | RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS); |
459 | |
460 | |
461 | |
462 | void erase(unsigned Offset, unsigned NumBytes); |
463 | |
464 | static bool classof(const RopePieceBTreeNode *N) { |
465 | return !N->isLeaf(); |
466 | } |
467 | }; |
468 | |
469 | } |
470 | |
471 | |
472 | |
473 | |
474 | |
475 | |
476 | |
477 | RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) { |
478 | |
479 | if (Offset == 0 || Offset == size()) |
480 | return nullptr; |
481 | |
482 | unsigned ChildOffset = 0; |
483 | unsigned i = 0; |
484 | for (; Offset >= ChildOffset+getChild(i)->size(); ++i) |
485 | ChildOffset += getChild(i)->size(); |
486 | |
487 | |
488 | if (ChildOffset == Offset) |
489 | return nullptr; |
490 | |
491 | |
492 | if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset)) |
493 | return HandleChildPiece(i, RHS); |
494 | return nullptr; |
495 | } |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset, |
504 | const RopePiece &R) { |
505 | |
506 | |
507 | unsigned i = 0, e = getNumChildren(); |
508 | |
509 | unsigned ChildOffs = 0; |
510 | if (Offset == size()) { |
511 | |
512 | i = e-1; |
513 | ChildOffs = size()-getChild(i)->size(); |
514 | } else { |
515 | for (; Offset > ChildOffs+getChild(i)->size(); ++i) |
516 | ChildOffs += getChild(i)->size(); |
517 | } |
518 | |
519 | Size += R.size(); |
520 | |
521 | |
522 | if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R)) |
523 | return HandleChildPiece(i, RHS); |
524 | |
525 | return nullptr; |
526 | } |
527 | |
528 | |
529 | |
530 | RopePieceBTreeNode * |
531 | RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) { |
532 | |
533 | |
534 | if (!isFull()) { |
535 | |
536 | if (i + 1 != getNumChildren()) |
537 | memmove(&Children[i+2], &Children[i+1], |
538 | (getNumChildren()-i-1)*sizeof(Children[0])); |
539 | Children[i+1] = RHS; |
540 | ++NumChildren; |
541 | return nullptr; |
542 | } |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior(); |
549 | |
550 | |
551 | memcpy(&NewNode->Children[0], &Children[WidthFactor], |
552 | WidthFactor*sizeof(Children[0])); |
553 | |
554 | |
555 | NewNode->NumChildren = NumChildren = WidthFactor; |
556 | |
557 | |
558 | |
559 | if (i < WidthFactor) |
560 | this->HandleChildPiece(i, RHS); |
561 | else |
562 | NewNode->HandleChildPiece(i-WidthFactor, RHS); |
563 | |
564 | |
565 | NewNode->FullRecomputeSizeLocally(); |
566 | FullRecomputeSizeLocally(); |
567 | return NewNode; |
568 | } |
569 | |
570 | |
571 | |
572 | void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) { |
573 | |
574 | Size -= NumBytes; |
575 | |
576 | |
577 | unsigned i = 0; |
578 | for (; Offset >= getChild(i)->size(); ++i) |
579 | Offset -= getChild(i)->size(); |
580 | |
581 | |
582 | |
583 | while (NumBytes) { |
584 | RopePieceBTreeNode *CurChild = getChild(i); |
585 | |
586 | |
587 | |
588 | if (Offset+NumBytes < CurChild->size()) { |
589 | CurChild->erase(Offset, NumBytes); |
590 | return; |
591 | } |
592 | |
593 | |
594 | |
595 | if (Offset) { |
596 | unsigned BytesFromChild = CurChild->size()-Offset; |
597 | CurChild->erase(Offset, BytesFromChild); |
598 | NumBytes -= BytesFromChild; |
599 | |
600 | Offset = 0; |
601 | ++i; |
602 | continue; |
603 | } |
604 | |
605 | |
606 | |
607 | NumBytes -= CurChild->size(); |
608 | CurChild->Destroy(); |
609 | --NumChildren; |
610 | if (i != getNumChildren()) |
611 | memmove(&Children[i], &Children[i+1], |
612 | (getNumChildren()-i)*sizeof(Children[0])); |
613 | } |
614 | } |
615 | |
616 | |
617 | |
618 | |
619 | |
620 | void RopePieceBTreeNode::Destroy() { |
621 | if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this)) |
622 | delete Leaf; |
623 | else |
624 | delete cast<RopePieceBTreeInterior>(this); |
625 | } |
626 | |
627 | |
628 | |
629 | |
630 | |
631 | |
632 | |
633 | RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) { |
634 | (0) . __assert_fail ("Offset <= size() && \"Invalid offset to split!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 634, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Offset <= size() && "Invalid offset to split!"); |
635 | if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this)) |
636 | return Leaf->split(Offset); |
637 | return cast<RopePieceBTreeInterior>(this)->split(Offset); |
638 | } |
639 | |
640 | |
641 | |
642 | |
643 | |
644 | |
645 | |
646 | RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset, |
647 | const RopePiece &R) { |
648 | (0) . __assert_fail ("Offset <= size() && \"Invalid offset to insert!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 648, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Offset <= size() && "Invalid offset to insert!"); |
649 | if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this)) |
650 | return Leaf->insert(Offset, R); |
651 | return cast<RopePieceBTreeInterior>(this)->insert(Offset, R); |
652 | } |
653 | |
654 | |
655 | |
656 | void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) { |
657 | (0) . __assert_fail ("Offset+NumBytes <= size() && \"Invalid offset to erase!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 657, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Offset+NumBytes <= size() && "Invalid offset to erase!"); |
658 | if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(this)) |
659 | return Leaf->erase(Offset, NumBytes); |
660 | return cast<RopePieceBTreeInterior>(this)->erase(Offset, NumBytes); |
661 | } |
662 | |
663 | |
664 | |
665 | |
666 | |
667 | static const RopePieceBTreeLeaf *getCN(const void *P) { |
668 | return static_cast<const RopePieceBTreeLeaf*>(P); |
669 | } |
670 | |
671 | |
672 | RopePieceBTreeIterator::RopePieceBTreeIterator(const void *n) { |
673 | const auto *N = static_cast<const RopePieceBTreeNode *>(n); |
674 | |
675 | |
676 | while (const auto *IN = dyn_cast<RopePieceBTreeInterior>(N)) |
677 | N = IN->getChild(0); |
678 | |
679 | |
680 | CurNode = cast<RopePieceBTreeLeaf>(N); |
681 | |
682 | |
683 | |
684 | while (CurNode && getCN(CurNode)->getNumPieces() == 0) |
685 | CurNode = getCN(CurNode)->getNextLeafInOrder(); |
686 | |
687 | if (CurNode) |
688 | CurPiece = &getCN(CurNode)->getPiece(0); |
689 | else |
690 | CurPiece = nullptr; |
691 | CurChar = 0; |
692 | } |
693 | |
694 | void RopePieceBTreeIterator::MoveToNextPiece() { |
695 | if (CurPiece != &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces()-1)) { |
696 | CurChar = 0; |
697 | ++CurPiece; |
698 | return; |
699 | } |
700 | |
701 | |
702 | do |
703 | CurNode = getCN(CurNode)->getNextLeafInOrder(); |
704 | while (CurNode && getCN(CurNode)->getNumPieces() == 0); |
705 | |
706 | if (CurNode) |
707 | CurPiece = &getCN(CurNode)->getPiece(0); |
708 | else |
709 | CurPiece = nullptr; |
710 | CurChar = 0; |
711 | } |
712 | |
713 | |
714 | |
715 | |
716 | |
717 | static RopePieceBTreeNode *getRoot(void *P) { |
718 | return static_cast<RopePieceBTreeNode*>(P); |
719 | } |
720 | |
721 | RopePieceBTree::RopePieceBTree() { |
722 | Root = new RopePieceBTreeLeaf(); |
723 | } |
724 | |
725 | RopePieceBTree::RopePieceBTree(const RopePieceBTree &RHS) { |
726 | (0) . __assert_fail ("RHS.empty() && \"Can't copy non-empty tree yet\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 726, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(RHS.empty() && "Can't copy non-empty tree yet"); |
727 | Root = new RopePieceBTreeLeaf(); |
728 | } |
729 | |
730 | RopePieceBTree::~RopePieceBTree() { |
731 | getRoot(Root)->Destroy(); |
732 | } |
733 | |
734 | unsigned RopePieceBTree::size() const { |
735 | return getRoot(Root)->size(); |
736 | } |
737 | |
738 | void RopePieceBTree::clear() { |
739 | if (auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(getRoot(Root))) |
740 | Leaf->clear(); |
741 | else { |
742 | getRoot(Root)->Destroy(); |
743 | Root = new RopePieceBTreeLeaf(); |
744 | } |
745 | } |
746 | |
747 | void RopePieceBTree::insert(unsigned Offset, const RopePiece &R) { |
748 | |
749 | if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset)) |
750 | Root = new RopePieceBTreeInterior(getRoot(Root), RHS); |
751 | |
752 | |
753 | if (RopePieceBTreeNode *RHS = getRoot(Root)->insert(Offset, R)) |
754 | Root = new RopePieceBTreeInterior(getRoot(Root), RHS); |
755 | } |
756 | |
757 | void RopePieceBTree::erase(unsigned Offset, unsigned NumBytes) { |
758 | |
759 | if (RopePieceBTreeNode *RHS = getRoot(Root)->split(Offset)) |
760 | Root = new RopePieceBTreeInterior(getRoot(Root), RHS); |
761 | |
762 | |
763 | getRoot(Root)->erase(Offset, NumBytes); |
764 | } |
765 | |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | |
773 | |
774 | RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) { |
775 | unsigned Len = End-Start; |
776 | (0) . __assert_fail ("Len && \"Zero length RopePiece is invalid!\"", "/home/seafit/code_projects/clang_source/clang/lib/Rewrite/RewriteRope.cpp", 776, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Len && "Zero length RopePiece is invalid!"); |
777 | |
778 | |
779 | if (AllocOffs+Len <= AllocChunkSize) { |
780 | memcpy(AllocBuffer->Data+AllocOffs, Start, Len); |
781 | AllocOffs += Len; |
782 | return RopePiece(AllocBuffer, AllocOffs-Len, AllocOffs); |
783 | } |
784 | |
785 | |
786 | |
787 | if (Len > AllocChunkSize) { |
788 | unsigned Size = End-Start+sizeof(RopeRefCountString)-1; |
789 | auto *Res = reinterpret_cast<RopeRefCountString *>(new char[Size]); |
790 | Res->RefCount = 0; |
791 | memcpy(Res->Data, Start, End-Start); |
792 | return RopePiece(Res, 0, End-Start); |
793 | } |
794 | |
795 | |
796 | |
797 | |
798 | unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize; |
799 | auto *Res = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]); |
800 | Res->RefCount = 0; |
801 | memcpy(Res->Data, Start, Len); |
802 | AllocBuffer = Res; |
803 | AllocOffs = Len; |
804 | |
805 | return RopePiece(AllocBuffer, 0, Len); |
806 | } |
807 | |