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.
grow(size_t N)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:
OutputStream(char * StartBuf,size_t Size)65 OutputStream(char *StartBuf, size_t Size)
66 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
67 OutputStream() = default;
reset(char * Buffer_,size_t BufferCapacity_)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
getCurrentPosition()128 size_t getCurrentPosition() const { return CurrentPosition; }
setCurrentPosition(size_t NewPos)129 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
130
back()131 char back() const {
132 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
133 }
134
empty()135 bool empty() const { return CurrentPosition == 0; }
136
getBuffer()137 char *getBuffer() { return Buffer; }
getBufferEnd()138 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
getBufferCapacity()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:
SwapAndRestore(T & Restore_)148 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
149
SwapAndRestore(T & Restore_,T NewVal)150 SwapAndRestore(T &Restore_, T NewVal)
151 : Restore(Restore_), OriginalValue(Restore) {
152 Restore = std::move(NewVal);
153 }
~SwapAndRestore()154 ~SwapAndRestore() {
155 if (ShouldRestore)
156 Restore = std::move(OriginalValue);
157 }
158
shouldRestore(bool ShouldRestore_)159 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
160
restoreNow(bool Force)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
initializeOutputStream(char * Buf,size_t * N,OutputStream & S,size_t InitSize)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
191