Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:07

0001 //===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines the RewriteRope class, which is a powerful string class.
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 // RopeRefCountString Class
0027 //===--------------------------------------------------------------------===//
0028 
0029 /// RopeRefCountString - This struct is allocated with 'new char[]' from the
0030 /// heap, and represents a reference counted chunk of string data.  When its
0031 /// ref count drops to zero, it is delete[]'d.  This is primarily managed
0032 /// through the RopePiece class below.
0033 struct RopeRefCountString {
0034   unsigned RefCount;
0035   char Data[1]; //  Variable sized.
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 // RopePiece Class
0048 //===--------------------------------------------------------------------===//
0049 
0050 /// RopePiece - This class represents a view into a RopeRefCountString object.
0051 /// This allows references to string data to be efficiently chopped up and
0052 /// moved around without having to push around the string data itself.
0053 ///
0054 /// For example, we could have a 1M RopePiece and want to insert something
0055 /// into the middle of it.  To do this, we split it into two RopePiece objects
0056 /// that both refer to the same underlying RopeRefCountString (just with
0057 /// different offsets) which is a nice constant time operation.
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 // RopePieceBTreeIterator Class
0080 //===--------------------------------------------------------------------===//
0081 
0082 /// RopePieceBTreeIterator - This class provides read-only forward iteration
0083 /// over bytes that are in a RopePieceBTree.  This first iterates over bytes
0084 /// in a RopePiece, then iterates over RopePiece's in a RopePieceBTreeLeaf,
0085 /// then iterates over RopePieceBTreeLeaf's in a RopePieceBTree.
0086 class RopePieceBTreeIterator {
0087   /// CurNode - The current B+Tree node that we are inspecting.
0088   const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr;
0089 
0090   /// CurPiece - The current RopePiece in the B+Tree node that we're
0091   /// inspecting.
0092   const RopePiece *CurPiece = nullptr;
0093 
0094   /// CurChar - The current byte in the RopePiece we are pointing to.
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 /*RopePieceBTreeNode*/ *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++() { // Preincrement
0117     if (CurChar + 1 < CurPiece->size())
0118       ++CurChar;
0119     else
0120       MoveToNextPiece();
0121     return *this;
0122   }
0123 
0124   RopePieceBTreeIterator operator++(int) { // Postincrement
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 // RopePieceBTree Class
0139 //===--------------------------------------------------------------------===//
0140 
0141 class RopePieceBTree {
0142   void /*RopePieceBTreeNode*/ *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 // RewriteRope Class
0166 //===--------------------------------------------------------------------===//
0167 
0168 /// RewriteRope - A powerful string class.  This class supports extremely
0169 /// efficient insertions and deletions into the middle of it, even for
0170 /// ridiculously long strings.
0171 class RewriteRope {
0172   RopePieceBTree Chunks;
0173 
0174   /// We allocate space for string data out of a buffer of size AllocChunkSize.
0175   /// This keeps track of how much space is left.
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   // The copy assignment operator is defined as deleted pending further
0185   // motivation.
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 } // namespace llvm
0222 
0223 #endif // LLVM_ADT_REWRITEROPE_H