17330f729Sjoerg //===--- Utility.h ----------------------------------------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // Provide some utility classes for use in the demangler(s).
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
13*82d56013Sjoerg #ifndef LLVM_DEMANGLE_UTILITY_H
14*82d56013Sjoerg #define LLVM_DEMANGLE_UTILITY_H
157330f729Sjoerg
167330f729Sjoerg #include "StringView.h"
177330f729Sjoerg #include <cstdint>
187330f729Sjoerg #include <cstdlib>
197330f729Sjoerg #include <cstring>
207330f729Sjoerg #include <iterator>
217330f729Sjoerg #include <limits>
227330f729Sjoerg
237330f729Sjoerg DEMANGLE_NAMESPACE_BEGIN
247330f729Sjoerg
257330f729Sjoerg // Stream that AST nodes write their string representation into after the AST
267330f729Sjoerg // has been parsed.
277330f729Sjoerg class OutputStream {
28*82d56013Sjoerg char *Buffer = nullptr;
29*82d56013Sjoerg size_t CurrentPosition = 0;
30*82d56013Sjoerg size_t BufferCapacity = 0;
317330f729Sjoerg
327330f729Sjoerg // Ensure there is at least n more positions in buffer.
grow(size_t N)337330f729Sjoerg void grow(size_t N) {
347330f729Sjoerg if (N + CurrentPosition >= BufferCapacity) {
357330f729Sjoerg BufferCapacity *= 2;
367330f729Sjoerg if (BufferCapacity < N + CurrentPosition)
377330f729Sjoerg BufferCapacity = N + CurrentPosition;
387330f729Sjoerg Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
397330f729Sjoerg if (Buffer == nullptr)
407330f729Sjoerg std::terminate();
417330f729Sjoerg }
427330f729Sjoerg }
437330f729Sjoerg
447330f729Sjoerg void writeUnsigned(uint64_t N, bool isNeg = false) {
457330f729Sjoerg // Handle special case...
467330f729Sjoerg if (N == 0) {
477330f729Sjoerg *this << '0';
487330f729Sjoerg return;
497330f729Sjoerg }
507330f729Sjoerg
517330f729Sjoerg char Temp[21];
527330f729Sjoerg char *TempPtr = std::end(Temp);
537330f729Sjoerg
547330f729Sjoerg while (N) {
55*82d56013Sjoerg *--TempPtr = char('0' + N % 10);
567330f729Sjoerg N /= 10;
577330f729Sjoerg }
587330f729Sjoerg
597330f729Sjoerg // Add negative sign...
607330f729Sjoerg if (isNeg)
617330f729Sjoerg *--TempPtr = '-';
627330f729Sjoerg this->operator<<(StringView(TempPtr, std::end(Temp)));
637330f729Sjoerg }
647330f729Sjoerg
657330f729Sjoerg public:
OutputStream(char * StartBuf,size_t Size)667330f729Sjoerg OutputStream(char *StartBuf, size_t Size)
677330f729Sjoerg : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
687330f729Sjoerg OutputStream() = default;
reset(char * Buffer_,size_t BufferCapacity_)697330f729Sjoerg void reset(char *Buffer_, size_t BufferCapacity_) {
707330f729Sjoerg CurrentPosition = 0;
717330f729Sjoerg Buffer = Buffer_;
727330f729Sjoerg BufferCapacity = BufferCapacity_;
737330f729Sjoerg }
747330f729Sjoerg
757330f729Sjoerg /// If a ParameterPackExpansion (or similar type) is encountered, the offset
767330f729Sjoerg /// into the pack that we're currently printing.
777330f729Sjoerg unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
787330f729Sjoerg unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
797330f729Sjoerg
807330f729Sjoerg OutputStream &operator+=(StringView R) {
817330f729Sjoerg size_t Size = R.size();
827330f729Sjoerg if (Size == 0)
837330f729Sjoerg return *this;
847330f729Sjoerg grow(Size);
857330f729Sjoerg std::memmove(Buffer + CurrentPosition, R.begin(), Size);
867330f729Sjoerg CurrentPosition += Size;
877330f729Sjoerg return *this;
887330f729Sjoerg }
897330f729Sjoerg
907330f729Sjoerg OutputStream &operator+=(char C) {
917330f729Sjoerg grow(1);
927330f729Sjoerg Buffer[CurrentPosition++] = C;
937330f729Sjoerg return *this;
947330f729Sjoerg }
957330f729Sjoerg
967330f729Sjoerg OutputStream &operator<<(StringView R) { return (*this += R); }
977330f729Sjoerg
987330f729Sjoerg OutputStream &operator<<(char C) { return (*this += C); }
997330f729Sjoerg
1007330f729Sjoerg OutputStream &operator<<(long long N) {
1017330f729Sjoerg if (N < 0)
1027330f729Sjoerg writeUnsigned(static_cast<unsigned long long>(-N), true);
1037330f729Sjoerg else
1047330f729Sjoerg writeUnsigned(static_cast<unsigned long long>(N));
1057330f729Sjoerg return *this;
1067330f729Sjoerg }
1077330f729Sjoerg
1087330f729Sjoerg OutputStream &operator<<(unsigned long long N) {
1097330f729Sjoerg writeUnsigned(N, false);
1107330f729Sjoerg return *this;
1117330f729Sjoerg }
1127330f729Sjoerg
1137330f729Sjoerg OutputStream &operator<<(long N) {
1147330f729Sjoerg return this->operator<<(static_cast<long long>(N));
1157330f729Sjoerg }
1167330f729Sjoerg
1177330f729Sjoerg OutputStream &operator<<(unsigned long N) {
1187330f729Sjoerg return this->operator<<(static_cast<unsigned long long>(N));
1197330f729Sjoerg }
1207330f729Sjoerg
1217330f729Sjoerg OutputStream &operator<<(int N) {
1227330f729Sjoerg return this->operator<<(static_cast<long long>(N));
1237330f729Sjoerg }
1247330f729Sjoerg
1257330f729Sjoerg OutputStream &operator<<(unsigned int N) {
1267330f729Sjoerg return this->operator<<(static_cast<unsigned long long>(N));
1277330f729Sjoerg }
1287330f729Sjoerg
getCurrentPosition()1297330f729Sjoerg size_t getCurrentPosition() const { return CurrentPosition; }
setCurrentPosition(size_t NewPos)1307330f729Sjoerg void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
1317330f729Sjoerg
back()1327330f729Sjoerg char back() const {
1337330f729Sjoerg return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
1347330f729Sjoerg }
1357330f729Sjoerg
empty()1367330f729Sjoerg bool empty() const { return CurrentPosition == 0; }
1377330f729Sjoerg
getBuffer()1387330f729Sjoerg char *getBuffer() { return Buffer; }
getBufferEnd()1397330f729Sjoerg char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
getBufferCapacity()140*82d56013Sjoerg size_t getBufferCapacity() const { return BufferCapacity; }
1417330f729Sjoerg };
1427330f729Sjoerg
1437330f729Sjoerg template <class T> class SwapAndRestore {
1447330f729Sjoerg T &Restore;
1457330f729Sjoerg T OriginalValue;
1467330f729Sjoerg bool ShouldRestore = true;
1477330f729Sjoerg
1487330f729Sjoerg public:
SwapAndRestore(T & Restore_)1497330f729Sjoerg SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
1507330f729Sjoerg
SwapAndRestore(T & Restore_,T NewVal)1517330f729Sjoerg SwapAndRestore(T &Restore_, T NewVal)
1527330f729Sjoerg : Restore(Restore_), OriginalValue(Restore) {
1537330f729Sjoerg Restore = std::move(NewVal);
1547330f729Sjoerg }
~SwapAndRestore()1557330f729Sjoerg ~SwapAndRestore() {
1567330f729Sjoerg if (ShouldRestore)
1577330f729Sjoerg Restore = std::move(OriginalValue);
1587330f729Sjoerg }
1597330f729Sjoerg
shouldRestore(bool ShouldRestore_)1607330f729Sjoerg void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
1617330f729Sjoerg
restoreNow(bool Force)1627330f729Sjoerg void restoreNow(bool Force) {
1637330f729Sjoerg if (!Force && !ShouldRestore)
1647330f729Sjoerg return;
1657330f729Sjoerg
1667330f729Sjoerg Restore = std::move(OriginalValue);
1677330f729Sjoerg ShouldRestore = false;
1687330f729Sjoerg }
1697330f729Sjoerg
1707330f729Sjoerg SwapAndRestore(const SwapAndRestore &) = delete;
1717330f729Sjoerg SwapAndRestore &operator=(const SwapAndRestore &) = delete;
1727330f729Sjoerg };
1737330f729Sjoerg
initializeOutputStream(char * Buf,size_t * N,OutputStream & S,size_t InitSize)1747330f729Sjoerg inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
1757330f729Sjoerg size_t InitSize) {
1767330f729Sjoerg size_t BufferSize;
1777330f729Sjoerg if (Buf == nullptr) {
1787330f729Sjoerg Buf = static_cast<char *>(std::malloc(InitSize));
1797330f729Sjoerg if (Buf == nullptr)
1807330f729Sjoerg return false;
1817330f729Sjoerg BufferSize = InitSize;
1827330f729Sjoerg } else
1837330f729Sjoerg BufferSize = *N;
1847330f729Sjoerg
1857330f729Sjoerg S.reset(Buf, BufferSize);
1867330f729Sjoerg return true;
1877330f729Sjoerg }
1887330f729Sjoerg
1897330f729Sjoerg DEMANGLE_NAMESPACE_END
1907330f729Sjoerg
1917330f729Sjoerg #endif
192