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