xref: /netbsd-src/external/apache2/llvm/dist/llvm/include/llvm/Demangle/Utility.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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