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