[llvm] [cmake] Add possibility to use ChooseMSVCCRT.cmake when include LLVM library
[llvm-core.git] / include / llvm / Demangle / Utility.h
blobec23859af46afce15f3f367a31eb149ddda23e31
1 //===--- Utility.h ----------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Provide some utility classes for use in the demangler(s).
11 //===----------------------------------------------------------------------===//
13 #ifndef DEMANGLE_UTILITY_H
14 #define DEMANGLE_UTILITY_H
16 #include "StringView.h"
17 #include <cstdint>
18 #include <cstdlib>
19 #include <cstring>
20 #include <iterator>
21 #include <limits>
23 DEMANGLE_NAMESPACE_BEGIN
25 // Stream that AST nodes write their string representation into after the AST
26 // has been parsed.
27 class OutputStream {
28 char *Buffer;
29 size_t CurrentPosition;
30 size_t BufferCapacity;
32 // Ensure there is at least n more positions in buffer.
33 void grow(size_t N) {
34 if (N + CurrentPosition >= BufferCapacity) {
35 BufferCapacity *= 2;
36 if (BufferCapacity < N + CurrentPosition)
37 BufferCapacity = N + CurrentPosition;
38 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
39 if (Buffer == nullptr)
40 std::terminate();
44 void writeUnsigned(uint64_t N, bool isNeg = false) {
45 // Handle special case...
46 if (N == 0) {
47 *this << '0';
48 return;
51 char Temp[21];
52 char *TempPtr = std::end(Temp);
54 while (N) {
55 *--TempPtr = '0' + char(N % 10);
56 N /= 10;
59 // Add negative sign...
60 if (isNeg)
61 *--TempPtr = '-';
62 this->operator<<(StringView(TempPtr, std::end(Temp)));
65 public:
66 OutputStream(char *StartBuf, size_t Size)
67 : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
68 OutputStream() = default;
69 void reset(char *Buffer_, size_t BufferCapacity_) {
70 CurrentPosition = 0;
71 Buffer = Buffer_;
72 BufferCapacity = BufferCapacity_;
75 /// If a ParameterPackExpansion (or similar type) is encountered, the offset
76 /// into the pack that we're currently printing.
77 unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
78 unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
80 OutputStream &operator+=(StringView R) {
81 size_t Size = R.size();
82 if (Size == 0)
83 return *this;
84 grow(Size);
85 std::memmove(Buffer + CurrentPosition, R.begin(), Size);
86 CurrentPosition += Size;
87 return *this;
90 OutputStream &operator+=(char C) {
91 grow(1);
92 Buffer[CurrentPosition++] = C;
93 return *this;
96 OutputStream &operator<<(StringView R) { return (*this += R); }
98 OutputStream &operator<<(char C) { return (*this += C); }
100 OutputStream &operator<<(long long N) {
101 if (N < 0)
102 writeUnsigned(static_cast<unsigned long long>(-N), true);
103 else
104 writeUnsigned(static_cast<unsigned long long>(N));
105 return *this;
108 OutputStream &operator<<(unsigned long long N) {
109 writeUnsigned(N, false);
110 return *this;
113 OutputStream &operator<<(long N) {
114 return this->operator<<(static_cast<long long>(N));
117 OutputStream &operator<<(unsigned long N) {
118 return this->operator<<(static_cast<unsigned long long>(N));
121 OutputStream &operator<<(int N) {
122 return this->operator<<(static_cast<long long>(N));
125 OutputStream &operator<<(unsigned int N) {
126 return this->operator<<(static_cast<unsigned long long>(N));
129 size_t getCurrentPosition() const { return CurrentPosition; }
130 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
132 char back() const {
133 return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
136 bool empty() const { return CurrentPosition == 0; }
138 char *getBuffer() { return Buffer; }
139 char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
140 size_t getBufferCapacity() { return BufferCapacity; }
143 template <class T> class SwapAndRestore {
144 T &Restore;
145 T OriginalValue;
146 bool ShouldRestore = true;
148 public:
149 SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
151 SwapAndRestore(T &Restore_, T NewVal)
152 : Restore(Restore_), OriginalValue(Restore) {
153 Restore = std::move(NewVal);
155 ~SwapAndRestore() {
156 if (ShouldRestore)
157 Restore = std::move(OriginalValue);
160 void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
162 void restoreNow(bool Force) {
163 if (!Force && !ShouldRestore)
164 return;
166 Restore = std::move(OriginalValue);
167 ShouldRestore = false;
170 SwapAndRestore(const SwapAndRestore &) = delete;
171 SwapAndRestore &operator=(const SwapAndRestore &) = delete;
174 inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
175 size_t InitSize) {
176 size_t BufferSize;
177 if (Buf == nullptr) {
178 Buf = static_cast<char *>(std::malloc(InitSize));
179 if (Buf == nullptr)
180 return false;
181 BufferSize = InitSize;
182 } else
183 BufferSize = *N;
185 S.reset(Buf, BufferSize);
186 return true;
189 DEMANGLE_NAMESPACE_END
191 #endif