]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Demangle/Utility.h
MFC r345703:
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Demangle / Utility.h
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   void grow(size_t N) {
32     if (N + CurrentPosition >= BufferCapacity) {
33       BufferCapacity *= 2;
34       if (BufferCapacity < N + CurrentPosition)
35         BufferCapacity = N + CurrentPosition;
36       Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
37       if (Buffer == nullptr)
38         std::terminate();
39     }
40   }
41
42   void writeUnsigned(uint64_t N, bool isNeg = false) {
43     // Handle special case...
44     if (N == 0) {
45       *this << '0';
46       return;
47     }
48
49     char Temp[21];
50     char *TempPtr = std::end(Temp);
51
52     while (N) {
53       *--TempPtr = '0' + char(N % 10);
54       N /= 10;
55     }
56
57     // Add negative sign...
58     if (isNeg)
59       *--TempPtr = '-';
60     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   OutputStream() = default;
67   void reset(char *Buffer_, size_t BufferCapacity_) {
68     CurrentPosition = 0;
69     Buffer = Buffer_;
70     BufferCapacity = BufferCapacity_;
71   }
72
73   /// Create an OutputStream from a buffer and a size.  If either of these are
74   /// null a buffer is allocated.
75   static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) {
76     OutputStream Result;
77
78     if (!StartBuf || !Size) {
79       StartBuf = static_cast<char *>(std::malloc(AllocSize));
80       if (StartBuf == nullptr)
81         std::terminate();
82       Size = &AllocSize;
83     }
84
85     Result.reset(StartBuf, *Size);
86     return Result;
87   }
88
89   /// If a ParameterPackExpansion (or similar type) is encountered, the offset
90   /// into the pack that we're currently printing.
91   unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
92   unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
93
94   OutputStream &operator+=(StringView R) {
95     size_t Size = R.size();
96     if (Size == 0)
97       return *this;
98     grow(Size);
99     std::memmove(Buffer + CurrentPosition, R.begin(), Size);
100     CurrentPosition += Size;
101     return *this;
102   }
103
104   OutputStream &operator+=(char C) {
105     grow(1);
106     Buffer[CurrentPosition++] = C;
107     return *this;
108   }
109
110   OutputStream &operator<<(StringView R) { return (*this += R); }
111
112   OutputStream &operator<<(char C) { return (*this += C); }
113
114   OutputStream &operator<<(long long N) {
115     if (N < 0)
116       writeUnsigned(static_cast<unsigned long long>(-N), true);
117     else
118       writeUnsigned(static_cast<unsigned long long>(N));
119     return *this;
120   }
121
122   OutputStream &operator<<(unsigned long long N) {
123     writeUnsigned(N, false);
124     return *this;
125   }
126
127   OutputStream &operator<<(long N) {
128     return this->operator<<(static_cast<long long>(N));
129   }
130
131   OutputStream &operator<<(unsigned long N) {
132     return this->operator<<(static_cast<unsigned long long>(N));
133   }
134
135   OutputStream &operator<<(int N) {
136     return this->operator<<(static_cast<long long>(N));
137   }
138
139   OutputStream &operator<<(unsigned int N) {
140     return this->operator<<(static_cast<unsigned long long>(N));
141   }
142
143   size_t getCurrentPosition() const { return CurrentPosition; }
144   void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
145
146   char back() const {
147     return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
148   }
149
150   bool empty() const { return CurrentPosition == 0; }
151
152   char *getBuffer() { return Buffer; }
153   char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
154   size_t getBufferCapacity() { return BufferCapacity; }
155 };
156
157 template <class T> class SwapAndRestore {
158   T &Restore;
159   T OriginalValue;
160   bool ShouldRestore = true;
161
162 public:
163   SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
164
165   SwapAndRestore(T &Restore_, T NewVal)
166       : Restore(Restore_), OriginalValue(Restore) {
167     Restore = std::move(NewVal);
168   }
169   ~SwapAndRestore() {
170     if (ShouldRestore)
171       Restore = std::move(OriginalValue);
172   }
173
174   void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
175
176   void restoreNow(bool Force) {
177     if (!Force && !ShouldRestore)
178       return;
179
180     Restore = std::move(OriginalValue);
181     ShouldRestore = false;
182   }
183
184   SwapAndRestore(const SwapAndRestore &) = delete;
185   SwapAndRestore &operator=(const SwapAndRestore &) = delete;
186 };
187
188 #endif