Utility.h (4962B)
1 //===--- Utility.h ----------------------------------------------*- 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 // This file is copied from llvm/lib/Demangle/Utility.h. 10 //===----------------------------------------------------------------------===// 11 12 #ifndef LIBCXX_DEMANGLE_UTILITY_H 13 #define LIBCXX_DEMANGLE_UTILITY_H 14 15 #include "StringView.h" 16 17 #include <cstdint> 18 #include <cstdlib> 19 #include <cstring> 20 #include <iterator> 21 #include <limits> 22 23 namespace { 24 // Stream that AST nodes write their string representation into after the AST 25 // has been parsed. 26 class OutputStream { 27 char *Buffer; 28 size_t CurrentPosition; 29 size_t BufferCapacity; 30 31 // Ensure there is at least n more positions in buffer. 32 void grow(size_t N) { 33 if (N + CurrentPosition >= BufferCapacity) { 34 BufferCapacity *= 2; 35 if (BufferCapacity < N + CurrentPosition) 36 BufferCapacity = N + CurrentPosition; 37 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); 38 if (Buffer == nullptr) 39 std::terminate(); 40 } 41 } 42 43 void writeUnsigned(uint64_t N, bool isNeg = false) { 44 // Handle special case... 45 if (N == 0) { 46 *this << '0'; 47 return; 48 } 49 50 char Temp[21]; 51 char *TempPtr = std::end(Temp); 52 53 while (N) { 54 *--TempPtr = '0' + char(N % 10); 55 N /= 10; 56 } 57 58 // Add negative sign... 59 if (isNeg) 60 *--TempPtr = '-'; 61 this->operator<<(StringView(TempPtr, std::end(Temp))); 62 } 63 64 public: 65 OutputStream(char *StartBuf, size_t Size) 66 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {} 67 OutputStream() = default; 68 void reset(char *Buffer_, size_t BufferCapacity_) { 69 CurrentPosition = 0; 70 Buffer = Buffer_; 71 BufferCapacity = BufferCapacity_; 72 } 73 74 /// If a ParameterPackExpansion (or similar type) is encountered, the offset 75 /// into the pack that we're currently printing. 76 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); 77 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); 78 79 OutputStream &operator+=(StringView R) { 80 size_t Size = R.size(); 81 if (Size == 0) 82 return *this; 83 grow(Size); 84 std::memmove(Buffer + CurrentPosition, R.begin(), Size); 85 CurrentPosition += Size; 86 return *this; 87 } 88 89 OutputStream &operator+=(char C) { 90 grow(1); 91 Buffer[CurrentPosition++] = C; 92 return *this; 93 } 94 95 OutputStream &operator<<(StringView R) { return (*this += R); } 96 97 OutputStream &operator<<(char C) { return (*this += C); } 98 99 OutputStream &operator<<(long long N) { 100 if (N < 0) 101 writeUnsigned(static_cast<unsigned long long>(-N), true); 102 else 103 writeUnsigned(static_cast<unsigned long long>(N)); 104 return *this; 105 } 106 107 OutputStream &operator<<(unsigned long long N) { 108 writeUnsigned(N, false); 109 return *this; 110 } 111 112 OutputStream &operator<<(long N) { 113 return this->operator<<(static_cast<long long>(N)); 114 } 115 116 OutputStream &operator<<(unsigned long N) { 117 return this->operator<<(static_cast<unsigned long long>(N)); 118 } 119 120 OutputStream &operator<<(int N) { 121 return this->operator<<(static_cast<long long>(N)); 122 } 123 124 OutputStream &operator<<(unsigned int N) { 125 return this->operator<<(static_cast<unsigned long long>(N)); 126 } 127 128 size_t getCurrentPosition() const { return CurrentPosition; } 129 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } 130 131 char back() const { 132 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0'; 133 } 134 135 bool empty() const { return CurrentPosition == 0; } 136 137 char *getBuffer() { return Buffer; } 138 char *getBufferEnd() { return Buffer + CurrentPosition - 1; } 139 size_t getBufferCapacity() { return BufferCapacity; } 140 }; 141 142 template <class T> class SwapAndRestore { 143 T &Restore; 144 T OriginalValue; 145 bool ShouldRestore = true; 146 147 public: 148 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {} 149 150 SwapAndRestore(T &Restore_, T NewVal) 151 : Restore(Restore_), OriginalValue(Restore) { 152 Restore = std::move(NewVal); 153 } 154 ~SwapAndRestore() { 155 if (ShouldRestore) 156 Restore = std::move(OriginalValue); 157 } 158 159 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; } 160 161 void restoreNow(bool Force) { 162 if (!Force && !ShouldRestore) 163 return; 164 165 Restore = std::move(OriginalValue); 166 ShouldRestore = false; 167 } 168 169 SwapAndRestore(const SwapAndRestore &) = delete; 170 SwapAndRestore &operator=(const SwapAndRestore &) = delete; 171 }; 172 173 inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, 174 size_t InitSize) { 175 size_t BufferSize; 176 if (Buf == nullptr) { 177 Buf = static_cast<char *>(std::malloc(InitSize)); 178 if (Buf == nullptr) 179 return false; 180 BufferSize = InitSize; 181 } else 182 BufferSize = *N; 183 184 S.reset(Buf, BufferSize); 185 return true; 186 } 187 188 } // namespace 189 190 #endif