]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Demangle/Utility.h
MFC r345805: Unify SCSI_STATUS_BUSY retry handling with other cases.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / 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   /// 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   OutputStream &operator+=(StringView R) {
79     size_t Size = R.size();
80     if (Size == 0)
81       return *this;
82     grow(Size);
83     std::memmove(Buffer + CurrentPosition, R.begin(), Size);
84     CurrentPosition += Size;
85     return *this;
86   }
87
88   OutputStream &operator+=(char C) {
89     grow(1);
90     Buffer[CurrentPosition++] = C;
91     return *this;
92   }
93
94   OutputStream &operator<<(StringView R) { return (*this += R); }
95
96   OutputStream &operator<<(char C) { return (*this += C); }
97
98   OutputStream &operator<<(long long N) {
99     if (N < 0)
100       writeUnsigned(static_cast<unsigned long long>(-N), true);
101     else
102       writeUnsigned(static_cast<unsigned long long>(N));
103     return *this;
104   }
105
106   OutputStream &operator<<(unsigned long long N) {
107     writeUnsigned(N, false);
108     return *this;
109   }
110
111   OutputStream &operator<<(long N) {
112     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     return this->operator<<(static_cast<long long>(N));
121   }
122
123   OutputStream &operator<<(unsigned int N) {
124     return this->operator<<(static_cast<unsigned long long>(N));
125   }
126
127   size_t getCurrentPosition() const { return CurrentPosition; }
128   void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
129
130   char back() const {
131     return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
132   }
133
134   bool empty() const { return CurrentPosition == 0; }
135
136   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   SwapAndRestore(T &Restore_, T NewVal)
150       : Restore(Restore_), OriginalValue(Restore) {
151     Restore = std::move(NewVal);
152   }
153   ~SwapAndRestore() {
154     if (ShouldRestore)
155       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   if (Buf == nullptr) {
176     Buf = static_cast<char *>(std::malloc(InitSize));
177     if (Buf == nullptr)
178       return false;
179     BufferSize = InitSize;
180   } else
181     BufferSize = *N;
182
183   S.reset(Buf, BufferSize);
184   return true;
185 }
186
187 #endif