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