1 //===--- Utility.h ----------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
23 DEMANGLE_NAMESPACE_BEGIN
25 // Stream that AST nodes write their string representation into after the AST
29 size_t CurrentPosition
;
30 size_t BufferCapacity
;
32 // Ensure there is at least n more positions in buffer.
34 if (N
+ CurrentPosition
>= BufferCapacity
) {
36 if (BufferCapacity
< N
+ CurrentPosition
)
37 BufferCapacity
= N
+ CurrentPosition
;
38 Buffer
= static_cast<char *>(std::realloc(Buffer
, BufferCapacity
));
39 if (Buffer
== nullptr)
44 void writeUnsigned(uint64_t N
, bool isNeg
= false) {
45 // Handle special case...
52 char *TempPtr
= std::end(Temp
);
55 *--TempPtr
= '0' + char(N
% 10);
59 // Add negative sign...
62 this->operator<<(StringView(TempPtr
, std::end(Temp
)));
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_
) {
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();
85 std::memmove(Buffer
+ CurrentPosition
, R
.begin(), Size
);
86 CurrentPosition
+= Size
;
90 OutputStream
&operator+=(char C
) {
92 Buffer
[CurrentPosition
++] = C
;
96 OutputStream
&operator<<(StringView R
) { return (*this += R
); }
98 OutputStream
&operator<<(char C
) { return (*this += C
); }
100 OutputStream
&operator<<(long long N
) {
102 writeUnsigned(static_cast<unsigned long long>(-N
), true);
104 writeUnsigned(static_cast<unsigned long long>(N
));
108 OutputStream
&operator<<(unsigned long long N
) {
109 writeUnsigned(N
, false);
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
; }
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
{
146 bool ShouldRestore
= true;
149 SwapAndRestore(T
&Restore_
) : SwapAndRestore(Restore_
, Restore_
) {}
151 SwapAndRestore(T
&Restore_
, T NewVal
)
152 : Restore(Restore_
), OriginalValue(Restore
) {
153 Restore
= std::move(NewVal
);
157 Restore
= std::move(OriginalValue
);
160 void shouldRestore(bool ShouldRestore_
) { ShouldRestore
= ShouldRestore_
; }
162 void restoreNow(bool Force
) {
163 if (!Force
&& !ShouldRestore
)
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
,
177 if (Buf
== nullptr) {
178 Buf
= static_cast<char *>(std::malloc(InitSize
));
181 BufferSize
= InitSize
;
185 S
.reset(Buf
, BufferSize
);
189 DEMANGLE_NAMESPACE_END