16 #include "llvm/Support/Casting.h" 21 using namespace clang;
78 class RopePieceBTreeNode {
85 enum { WidthFactor = 8 };
95 RopePieceBTreeNode(
bool isLeaf) : IsLeaf(isLeaf) {}
96 ~RopePieceBTreeNode() =
default;
99 bool isLeaf()
const {
return IsLeaf; }
100 unsigned size()
const {
return Size; }
110 RopePieceBTreeNode *split(
unsigned Offset);
122 void erase(
unsigned Offset,
unsigned NumBytes);
136 class RopePieceBTreeLeaf :
public RopePieceBTreeNode {
139 unsigned char NumPieces = 0;
146 RopePieceBTreeLeaf **PrevLeaf =
nullptr;
147 RopePieceBTreeLeaf *NextLeaf =
nullptr;
150 RopePieceBTreeLeaf() : RopePieceBTreeNode(
true) {}
152 ~RopePieceBTreeLeaf() {
153 if (PrevLeaf || NextLeaf)
154 removeFromLeafInOrder();
158 bool isFull()
const {
return NumPieces == 2*WidthFactor; }
167 unsigned getNumPieces()
const {
return NumPieces; }
169 const RopePiece &getPiece(
unsigned i)
const {
170 assert(i < getNumPieces() &&
"Invalid piece ID");
174 const RopePieceBTreeLeaf *getNextLeafInOrder()
const {
return NextLeaf; }
176 void insertAfterLeafInOrder(RopePieceBTreeLeaf *
Node) {
177 assert(!PrevLeaf && !NextLeaf &&
"Already in ordering");
179 NextLeaf = Node->NextLeaf;
181 NextLeaf->PrevLeaf = &NextLeaf;
182 PrevLeaf = &Node->NextLeaf;
183 Node->NextLeaf =
this;
186 void removeFromLeafInOrder() {
188 *PrevLeaf = NextLeaf;
190 NextLeaf->PrevLeaf = PrevLeaf;
191 }
else if (NextLeaf) {
192 NextLeaf->PrevLeaf =
nullptr;
198 void FullRecomputeSizeLocally() {
200 for (
unsigned i = 0, e = getNumPieces(); i != e; ++i)
201 Size += getPiece(i).size();
210 RopePieceBTreeNode *split(
unsigned Offset);
222 void erase(
unsigned Offset,
unsigned NumBytes);
224 static bool classof(
const RopePieceBTreeNode *N) {
237 RopePieceBTreeNode *RopePieceBTreeLeaf::split(
unsigned Offset) {
240 if (Offset == 0 || Offset == size()) {
246 unsigned PieceOffs = 0;
248 while (Offset >= PieceOffs+Pieces[i].size()) {
249 PieceOffs += Pieces[i].
size();
255 if (PieceOffs == Offset)
260 unsigned IntraPieceOffset = Offset-PieceOffs;
263 RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs+IntraPieceOffset,
265 Size -= Pieces[i].
size();
267 Size += Pieces[i].
size();
269 return insert(Offset, Tail);
277 RopePieceBTreeNode *RopePieceBTreeLeaf::insert(
unsigned Offset,
283 unsigned i = 0, e = getNumPieces();
284 if (Offset == size()) {
288 unsigned SlotOffs = 0;
289 for (; Offset > SlotOffs; ++i)
290 SlotOffs += getPiece(i).size();
291 assert(SlotOffs == Offset &&
"Split didn't occur before insertion!");
297 Pieces[e] = Pieces[e-1];
310 RopePieceBTreeLeaf *NewNode =
new RopePieceBTreeLeaf();
313 std::copy(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
314 &NewNode->Pieces[0]);
316 std::fill(&Pieces[WidthFactor], &Pieces[2*WidthFactor],
RopePiece());
319 NewNode->NumPieces = NumPieces = WidthFactor;
322 NewNode->FullRecomputeSizeLocally();
323 FullRecomputeSizeLocally();
326 NewNode->insertAfterLeafInOrder(
this);
329 if (this->size() >= Offset)
330 this->insert(Offset, R);
332 NewNode->insert(Offset - this->size(), R);
338 void RopePieceBTreeLeaf::erase(
unsigned Offset,
unsigned NumBytes) {
341 unsigned PieceOffs = 0;
343 for (; Offset > PieceOffs; ++i)
344 PieceOffs += getPiece(i).size();
345 assert(PieceOffs == Offset &&
"Split didn't occur before erase!");
347 unsigned StartPiece = i;
351 for (; Offset+NumBytes > PieceOffs+getPiece(i).size(); ++i)
352 PieceOffs += getPiece(i).size();
355 if (Offset+NumBytes == PieceOffs+getPiece(i).size()) {
356 PieceOffs += getPiece(i).size();
361 if (i != StartPiece) {
362 unsigned NumDeleted = i-StartPiece;
363 for (; i != getNumPieces(); ++i)
364 Pieces[i-NumDeleted] = Pieces[i];
367 std::fill(&Pieces[getNumPieces()-NumDeleted], &Pieces[getNumPieces()],
369 NumPieces -= NumDeleted;
371 unsigned CoverBytes = PieceOffs-
Offset;
372 NumBytes -= CoverBytes;
377 if (NumBytes == 0)
return;
381 assert(getPiece(StartPiece).size() > NumBytes);
382 Pieces[StartPiece].
StartOffs += NumBytes;
396 class RopePieceBTreeInterior :
public RopePieceBTreeNode {
399 unsigned char NumChildren = 0;
401 RopePieceBTreeNode *Children[2*WidthFactor];
404 RopePieceBTreeInterior() : RopePieceBTreeNode(
false) {}
406 RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
407 : RopePieceBTreeNode(
false) {
411 Size = LHS->size() + RHS->size();
414 ~RopePieceBTreeInterior() {
415 for (
unsigned i = 0, e = getNumChildren(); i != e; ++i)
416 Children[i]->Destroy();
419 bool isFull()
const {
return NumChildren == 2*WidthFactor; }
421 unsigned getNumChildren()
const {
return NumChildren; }
423 const RopePieceBTreeNode *getChild(
unsigned i)
const {
424 assert(i < NumChildren &&
"invalid child #");
428 RopePieceBTreeNode *getChild(
unsigned i) {
429 assert(i < NumChildren &&
"invalid child #");
435 void FullRecomputeSizeLocally() {
437 for (
unsigned i = 0, e = getNumChildren(); i != e; ++i)
438 Size += getChild(i)->size();
447 RopePieceBTreeNode *split(
unsigned Offset);
455 RopePieceBTreeNode *insert(
unsigned Offset,
const RopePiece &R);
459 RopePieceBTreeNode *HandleChildPiece(
unsigned i, RopePieceBTreeNode *RHS);
463 void erase(
unsigned Offset,
unsigned NumBytes);
465 static bool classof(
const RopePieceBTreeNode *N) {
478 RopePieceBTreeNode *RopePieceBTreeInterior::split(
unsigned Offset) {
480 if (Offset == 0 || Offset == size())
483 unsigned ChildOffset = 0;
485 for (; Offset >= ChildOffset+getChild(i)->size(); ++i)
486 ChildOffset += getChild(i)->size();
489 if (ChildOffset == Offset)
493 if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset-ChildOffset))
494 return HandleChildPiece(i, RHS);
504 RopePieceBTreeNode *RopePieceBTreeInterior::insert(
unsigned Offset,
508 unsigned i = 0, e = getNumChildren();
510 unsigned ChildOffs = 0;
511 if (Offset == size()) {
514 ChildOffs = size()-getChild(i)->size();
516 for (; Offset > ChildOffs+getChild(i)->size(); ++i)
517 ChildOffs += getChild(i)->size();
523 if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset-ChildOffs, R))
524 return HandleChildPiece(i, RHS);
532 RopePieceBTreeInterior::HandleChildPiece(
unsigned i, RopePieceBTreeNode *RHS) {
537 if (i + 1 != getNumChildren())
538 memmove(&Children[i+2], &Children[i+1],
539 (getNumChildren()-i-1)*
sizeof(Children[0]));
549 RopePieceBTreeInterior *NewNode =
new RopePieceBTreeInterior();
552 memcpy(&NewNode->Children[0], &Children[WidthFactor],
553 WidthFactor*
sizeof(Children[0]));
556 NewNode->NumChildren = NumChildren = WidthFactor;
561 this->HandleChildPiece(i, RHS);
563 NewNode->HandleChildPiece(i-WidthFactor, RHS);
566 NewNode->FullRecomputeSizeLocally();
567 FullRecomputeSizeLocally();
573 void RopePieceBTreeInterior::erase(
unsigned Offset,
unsigned NumBytes) {
579 for (; Offset >= getChild(i)->size(); ++i)
580 Offset -= getChild(i)->size();
585 RopePieceBTreeNode *CurChild = getChild(i);
589 if (Offset+NumBytes < CurChild->size()) {
590 CurChild->erase(Offset, NumBytes);
597 unsigned BytesFromChild = CurChild->size()-
Offset;
598 CurChild->erase(Offset, BytesFromChild);
599 NumBytes -= BytesFromChild;
608 NumBytes -= CurChild->size();
611 if (i != getNumChildren())
612 memmove(&Children[i], &Children[i+1],
613 (getNumChildren()-i)*
sizeof(Children[0]));
621 void RopePieceBTreeNode::Destroy() {
622 if (
auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(
this))
625 delete cast<RopePieceBTreeInterior>(
this);
634 RopePieceBTreeNode *RopePieceBTreeNode::split(
unsigned Offset) {
635 assert(Offset <= size() &&
"Invalid offset to split!");
636 if (
auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(
this))
637 return Leaf->split(Offset);
638 return cast<RopePieceBTreeInterior>(
this)->split(Offset);
647 RopePieceBTreeNode *RopePieceBTreeNode::insert(
unsigned Offset,
649 assert(Offset <= size() &&
"Invalid offset to insert!");
650 if (
auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(
this))
651 return Leaf->insert(Offset, R);
652 return cast<RopePieceBTreeInterior>(
this)->insert(Offset, R);
657 void RopePieceBTreeNode::erase(
unsigned Offset,
unsigned NumBytes) {
658 assert(Offset+NumBytes <= size() &&
"Invalid offset to erase!");
659 if (
auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(
this))
660 return Leaf->erase(Offset, NumBytes);
661 return cast<RopePieceBTreeInterior>(
this)->erase(Offset, NumBytes);
668 static const RopePieceBTreeLeaf *
getCN(
const void *
P) {
669 return static_cast<const RopePieceBTreeLeaf*
>(
P);
674 const auto *N =
static_cast<const RopePieceBTreeNode *
>(n);
677 while (
const auto *IN = dyn_cast<RopePieceBTreeInterior>(N))
681 CurNode = cast<RopePieceBTreeLeaf>(N);
685 while (CurNode &&
getCN(CurNode)->getNumPieces() == 0)
686 CurNode =
getCN(CurNode)->getNextLeafInOrder();
689 CurPiece = &
getCN(CurNode)->getPiece(0);
696 if (CurPiece != &
getCN(CurNode)->getPiece(
getCN(CurNode)->getNumPieces()-1)) {
704 CurNode =
getCN(CurNode)->getNextLeafInOrder();
705 while (CurNode &&
getCN(CurNode)->getNumPieces() == 0);
708 CurPiece = &
getCN(CurNode)->getPiece(0);
719 return static_cast<RopePieceBTreeNode*
>(
P);
723 Root =
new RopePieceBTreeLeaf();
727 assert(RHS.
empty() &&
"Can't copy non-empty tree yet");
728 Root =
new RopePieceBTreeLeaf();
740 if (
auto *Leaf = dyn_cast<RopePieceBTreeLeaf>(
getRoot(Root)))
744 Root =
new RopePieceBTreeLeaf();
750 if (RopePieceBTreeNode *RHS =
getRoot(Root)->split(Offset))
751 Root =
new RopePieceBTreeInterior(
getRoot(Root), RHS);
754 if (RopePieceBTreeNode *RHS =
getRoot(Root)->insert(Offset, R))
755 Root =
new RopePieceBTreeInterior(
getRoot(Root), RHS);
760 if (RopePieceBTreeNode *RHS =
getRoot(Root)->split(Offset))
761 Root =
new RopePieceBTreeInterior(
getRoot(Root), RHS);
764 getRoot(Root)->erase(Offset, NumBytes);
775 RopePiece RewriteRope::MakeRopeString(
const char *Start,
const char *
End) {
776 unsigned Len = End-Start;
777 assert(Len &&
"Zero length RopePiece is invalid!");
780 if (AllocOffs+Len <= AllocChunkSize) {
781 memcpy(AllocBuffer->Data+AllocOffs, Start, Len);
783 return RopePiece(AllocBuffer, AllocOffs-Len, AllocOffs);
788 if (Len > AllocChunkSize) {
792 memcpy(Res->Data, Start, End-Start);
802 memcpy(Res->Data, Start, Len);
void insert(unsigned Offset, const RopePiece &R)
RopeRefCountString - This struct is allocated with 'new char[]' from the heap, and represents a refer...
RopePiece - This class represents a view into a RopeRefCountString object.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
void erase(unsigned Offset, unsigned NumBytes)
RopePieceBTreeIterator()=default
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
static RopePieceBTreeNode * getRoot(void *P)
ast_type_traits::DynTypedNode Node
Dataflow Directional Tag Classes.
static bool classof(const OMPClause *T)
static const RopePieceBTreeLeaf * getCN(const void *P)