libcxxabi

libcxxabi mirror with random patches
git clone https://git.neptards.moe/neptards/libcxxabi.git
Log | Files | Refs

Utility.h (4962B)


      1 //===--- Utility.h ----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //
      9 // This file is copied from llvm/lib/Demangle/Utility.h.
     10 //===----------------------------------------------------------------------===//
     11 
     12 #ifndef LIBCXX_DEMANGLE_UTILITY_H
     13 #define LIBCXX_DEMANGLE_UTILITY_H
     14 
     15 #include "StringView.h"
     16 
     17 #include <cstdint>
     18 #include <cstdlib>
     19 #include <cstring>
     20 #include <iterator>
     21 #include <limits>
     22 
     23 namespace {
     24 // Stream that AST nodes write their string representation into after the AST
     25 // has been parsed.
     26 class OutputStream {
     27   char *Buffer;
     28   size_t CurrentPosition;
     29   size_t BufferCapacity;
     30 
     31   // Ensure there is at least n more positions in buffer.
     32   void grow(size_t N) {
     33     if (N + CurrentPosition >= BufferCapacity) {
     34       BufferCapacity *= 2;
     35       if (BufferCapacity < N + CurrentPosition)
     36         BufferCapacity = N + CurrentPosition;
     37       Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
     38       if (Buffer == nullptr)
     39         std::terminate();
     40     }
     41   }
     42 
     43   void writeUnsigned(uint64_t N, bool isNeg = false) {
     44     // Handle special case...
     45     if (N == 0) {
     46       *this << '0';
     47       return;
     48     }
     49 
     50     char Temp[21];
     51     char *TempPtr = std::end(Temp);
     52 
     53     while (N) {
     54       *--TempPtr = '0' + char(N % 10);
     55       N /= 10;
     56     }
     57 
     58     // Add negative sign...
     59     if (isNeg)
     60       *--TempPtr = '-';
     61     this->operator<<(StringView(TempPtr, std::end(Temp)));
     62   }
     63 
     64 public:
     65   OutputStream(char *StartBuf, size_t Size)
     66       : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
     67   OutputStream() = default;
     68   void reset(char *Buffer_, size_t BufferCapacity_) {
     69     CurrentPosition = 0;
     70     Buffer = Buffer_;
     71     BufferCapacity = BufferCapacity_;
     72   }
     73 
     74   /// If a ParameterPackExpansion (or similar type) is encountered, the offset
     75   /// into the pack that we're currently printing.
     76   unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
     77   unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
     78 
     79   OutputStream &operator+=(StringView R) {
     80     size_t Size = R.size();
     81     if (Size == 0)
     82       return *this;
     83     grow(Size);
     84     std::memmove(Buffer + CurrentPosition, R.begin(), Size);
     85     CurrentPosition += Size;
     86     return *this;
     87   }
     88 
     89   OutputStream &operator+=(char C) {
     90     grow(1);
     91     Buffer[CurrentPosition++] = C;
     92     return *this;
     93   }
     94 
     95   OutputStream &operator<<(StringView R) { return (*this += R); }
     96 
     97   OutputStream &operator<<(char C) { return (*this += C); }
     98 
     99   OutputStream &operator<<(long long N) {
    100     if (N < 0)
    101       writeUnsigned(static_cast<unsigned long long>(-N), true);
    102     else
    103       writeUnsigned(static_cast<unsigned long long>(N));
    104     return *this;
    105   }
    106 
    107   OutputStream &operator<<(unsigned long long N) {
    108     writeUnsigned(N, false);
    109     return *this;
    110   }
    111 
    112   OutputStream &operator<<(long N) {
    113     return this->operator<<(static_cast<long long>(N));
    114   }
    115 
    116   OutputStream &operator<<(unsigned long N) {
    117     return this->operator<<(static_cast<unsigned long long>(N));
    118   }
    119 
    120   OutputStream &operator<<(int N) {
    121     return this->operator<<(static_cast<long long>(N));
    122   }
    123 
    124   OutputStream &operator<<(unsigned int N) {
    125     return this->operator<<(static_cast<unsigned long long>(N));
    126   }
    127 
    128   size_t getCurrentPosition() const { return CurrentPosition; }
    129   void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
    130 
    131   char back() const {
    132     return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
    133   }
    134 
    135   bool empty() const { return CurrentPosition == 0; }
    136 
    137   char *getBuffer() { return Buffer; }
    138   char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
    139   size_t getBufferCapacity() { return BufferCapacity; }
    140 };
    141 
    142 template <class T> class SwapAndRestore {
    143   T &Restore;
    144   T OriginalValue;
    145   bool ShouldRestore = true;
    146 
    147 public:
    148   SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
    149 
    150   SwapAndRestore(T &Restore_, T NewVal)
    151       : Restore(Restore_), OriginalValue(Restore) {
    152     Restore = std::move(NewVal);
    153   }
    154   ~SwapAndRestore() {
    155     if (ShouldRestore)
    156       Restore = std::move(OriginalValue);
    157   }
    158 
    159   void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
    160 
    161   void restoreNow(bool Force) {
    162     if (!Force && !ShouldRestore)
    163       return;
    164 
    165     Restore = std::move(OriginalValue);
    166     ShouldRestore = false;
    167   }
    168 
    169   SwapAndRestore(const SwapAndRestore &) = delete;
    170   SwapAndRestore &operator=(const SwapAndRestore &) = delete;
    171 };
    172 
    173 inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
    174                                    size_t InitSize) {
    175   size_t BufferSize;
    176   if (Buf == nullptr) {
    177     Buf = static_cast<char *>(std::malloc(InitSize));
    178     if (Buf == nullptr)
    179       return false;
    180     BufferSize = InitSize;
    181   } else
    182     BufferSize = *N;
    183 
    184   S.reset(Buf, BufferSize);
    185   return true;
    186 }
    187 
    188 } // namespace
    189 
    190 #endif