File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_ADT_REWRITEROPE_H
0014 #define LLVM_ADT_REWRITEROPE_H
0015
0016 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include <cassert>
0019 #include <cstddef>
0020 #include <iterator>
0021 #include <utility>
0022
0023 namespace llvm {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 struct RopeRefCountString {
0034 unsigned RefCount;
0035 char Data[1];
0036
0037 void Retain() { ++RefCount; }
0038
0039 void Release() {
0040 assert(RefCount > 0 && "Reference count is already zero.");
0041 if (--RefCount == 0)
0042 delete[] (char *)this;
0043 }
0044 };
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 struct RopePiece {
0059 llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData;
0060 unsigned StartOffs = 0;
0061 unsigned EndOffs = 0;
0062
0063 RopePiece() = default;
0064 RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start,
0065 unsigned End)
0066 : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {}
0067
0068 const char &operator[](unsigned Offset) const {
0069 return StrData->Data[Offset + StartOffs];
0070 }
0071 char &operator[](unsigned Offset) {
0072 return StrData->Data[Offset + StartOffs];
0073 }
0074
0075 unsigned size() const { return EndOffs - StartOffs; }
0076 };
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 class RopePieceBTreeIterator {
0087
0088 const void *CurNode = nullptr;
0089
0090
0091
0092 const RopePiece *CurPiece = nullptr;
0093
0094
0095 unsigned CurChar = 0;
0096
0097 public:
0098 using iterator_category = std::forward_iterator_tag;
0099 using value_type = const char;
0100 using difference_type = std::ptrdiff_t;
0101 using pointer = value_type *;
0102 using reference = value_type &;
0103
0104 RopePieceBTreeIterator() = default;
0105 RopePieceBTreeIterator(const void *N);
0106
0107 char operator*() const { return (*CurPiece)[CurChar]; }
0108
0109 bool operator==(const RopePieceBTreeIterator &RHS) const {
0110 return CurPiece == RHS.CurPiece && CurChar == RHS.CurChar;
0111 }
0112 bool operator!=(const RopePieceBTreeIterator &RHS) const {
0113 return !operator==(RHS);
0114 }
0115
0116 RopePieceBTreeIterator &operator++() {
0117 if (CurChar + 1 < CurPiece->size())
0118 ++CurChar;
0119 else
0120 MoveToNextPiece();
0121 return *this;
0122 }
0123
0124 RopePieceBTreeIterator operator++(int) {
0125 RopePieceBTreeIterator tmp = *this;
0126 ++*this;
0127 return tmp;
0128 }
0129
0130 llvm::StringRef piece() const {
0131 return llvm::StringRef(&(*CurPiece)[0], CurPiece->size());
0132 }
0133
0134 void MoveToNextPiece();
0135 };
0136
0137
0138
0139
0140
0141 class RopePieceBTree {
0142 void *Root;
0143
0144 public:
0145 RopePieceBTree();
0146 RopePieceBTree(const RopePieceBTree &RHS);
0147 RopePieceBTree &operator=(const RopePieceBTree &) = delete;
0148 ~RopePieceBTree();
0149
0150 using iterator = RopePieceBTreeIterator;
0151
0152 iterator begin() const { return iterator(Root); }
0153 iterator end() const { return iterator(); }
0154 unsigned size() const;
0155 unsigned empty() const { return size() == 0; }
0156
0157 void clear();
0158
0159 void insert(unsigned Offset, const RopePiece &R);
0160
0161 void erase(unsigned Offset, unsigned NumBytes);
0162 };
0163
0164
0165
0166
0167
0168
0169
0170
0171 class RewriteRope {
0172 RopePieceBTree Chunks;
0173
0174
0175
0176 llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer;
0177 enum { AllocChunkSize = 4080 };
0178 unsigned AllocOffs = AllocChunkSize;
0179
0180 public:
0181 RewriteRope() = default;
0182 RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {}
0183
0184
0185
0186 RewriteRope &operator=(const RewriteRope &) = delete;
0187
0188 using iterator = RopePieceBTree::iterator;
0189 using const_iterator = RopePieceBTree::iterator;
0190
0191 iterator begin() const { return Chunks.begin(); }
0192 iterator end() const { return Chunks.end(); }
0193 unsigned size() const { return Chunks.size(); }
0194
0195 void clear() { Chunks.clear(); }
0196
0197 void assign(const char *Start, const char *End) {
0198 clear();
0199 if (Start != End)
0200 Chunks.insert(0, MakeRopeString(Start, End));
0201 }
0202
0203 void insert(unsigned Offset, const char *Start, const char *End) {
0204 assert(Offset <= size() && "Invalid position to insert!");
0205 if (Start == End)
0206 return;
0207 Chunks.insert(Offset, MakeRopeString(Start, End));
0208 }
0209
0210 void erase(unsigned Offset, unsigned NumBytes) {
0211 assert(Offset + NumBytes <= size() && "Invalid region to erase!");
0212 if (NumBytes == 0)
0213 return;
0214 Chunks.erase(Offset, NumBytes);
0215 }
0216
0217 private:
0218 RopePiece MakeRopeString(const char *Start, const char *End);
0219 };
0220
0221 }
0222
0223 #endif