Utility.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
  7. // Do not edit! See README.txt.
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Provide some utility classes for use in the demangler.
  15. // There are two copies of this file in the source tree. The one in libcxxabi
  16. // is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
  17. // the copy. See README.txt for more details.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #ifndef DEMANGLE_UTILITY_H
  21. #define DEMANGLE_UTILITY_H
  22. #include "StringView.h"
  23. #include <array>
  24. #include <cstdint>
  25. #include <cstdlib>
  26. #include <cstring>
  27. #include <exception>
  28. #include <limits>
  29. DEMANGLE_NAMESPACE_BEGIN
  30. // Stream that AST nodes write their string representation into after the AST
  31. // has been parsed.
  32. class OutputBuffer {
  33. char *Buffer = nullptr;
  34. size_t CurrentPosition = 0;
  35. size_t BufferCapacity = 0;
  36. // Ensure there is at least n more positions in buffer.
  37. void grow(size_t N) {
  38. if (N + CurrentPosition >= BufferCapacity) {
  39. BufferCapacity *= 2;
  40. if (BufferCapacity < N + CurrentPosition)
  41. BufferCapacity = N + CurrentPosition;
  42. Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
  43. if (Buffer == nullptr)
  44. std::terminate();
  45. }
  46. }
  47. void writeUnsigned(uint64_t N, bool isNeg = false) {
  48. // Handle special case...
  49. if (N == 0) {
  50. *this << '0';
  51. return;
  52. }
  53. std::array<char, 21> Temp;
  54. char *TempPtr = Temp.data() + Temp.size();
  55. while (N) {
  56. *--TempPtr = char('0' + N % 10);
  57. N /= 10;
  58. }
  59. // Add negative sign...
  60. if (isNeg)
  61. *--TempPtr = '-';
  62. this->operator<<(StringView(TempPtr, Temp.data() + Temp.size()));
  63. }
  64. public:
  65. OutputBuffer(char *StartBuf, size_t Size)
  66. : Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
  67. OutputBuffer() = default;
  68. void reset(char *Buffer_, size_t BufferCapacity_) {
  69. CurrentPosition = 0;
  70. Buffer = Buffer_;
  71. BufferCapacity = BufferCapacity_;
  72. }
  73. /// If a ParameterPackExpansion (or similar type) is encountered, the offset
  74. /// into the pack that we're currently printing.
  75. unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
  76. unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
  77. OutputBuffer &operator+=(StringView R) {
  78. size_t Size = R.size();
  79. if (Size == 0)
  80. return *this;
  81. grow(Size);
  82. std::memmove(Buffer + CurrentPosition, R.begin(), Size);
  83. CurrentPosition += Size;
  84. return *this;
  85. }
  86. OutputBuffer &operator+=(char C) {
  87. grow(1);
  88. Buffer[CurrentPosition++] = C;
  89. return *this;
  90. }
  91. OutputBuffer &operator<<(StringView R) { return (*this += R); }
  92. OutputBuffer prepend(StringView R) {
  93. size_t Size = R.size();
  94. grow(Size);
  95. std::memmove(Buffer + Size, Buffer, CurrentPosition);
  96. std::memcpy(Buffer, R.begin(), Size);
  97. CurrentPosition += Size;
  98. return *this;
  99. }
  100. OutputBuffer &operator<<(char C) { return (*this += C); }
  101. OutputBuffer &operator<<(long long N) {
  102. if (N < 0)
  103. writeUnsigned(static_cast<unsigned long long>(-N), true);
  104. else
  105. writeUnsigned(static_cast<unsigned long long>(N));
  106. return *this;
  107. }
  108. OutputBuffer &operator<<(unsigned long long N) {
  109. writeUnsigned(N, false);
  110. return *this;
  111. }
  112. OutputBuffer &operator<<(long N) {
  113. return this->operator<<(static_cast<long long>(N));
  114. }
  115. OutputBuffer &operator<<(unsigned long N) {
  116. return this->operator<<(static_cast<unsigned long long>(N));
  117. }
  118. OutputBuffer &operator<<(int N) {
  119. return this->operator<<(static_cast<long long>(N));
  120. }
  121. OutputBuffer &operator<<(unsigned int N) {
  122. return this->operator<<(static_cast<unsigned long long>(N));
  123. }
  124. void insert(size_t Pos, const char *S, size_t N) {
  125. assert(Pos <= CurrentPosition);
  126. if (N == 0)
  127. return;
  128. grow(N);
  129. std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
  130. std::memcpy(Buffer + Pos, S, N);
  131. CurrentPosition += N;
  132. }
  133. size_t getCurrentPosition() const { return CurrentPosition; }
  134. void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
  135. char back() const {
  136. return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
  137. }
  138. bool empty() const { return CurrentPosition == 0; }
  139. char *getBuffer() { return Buffer; }
  140. char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
  141. size_t getBufferCapacity() const { return BufferCapacity; }
  142. };
  143. template <class T> class SwapAndRestore {
  144. T &Restore;
  145. T OriginalValue;
  146. bool ShouldRestore = true;
  147. public:
  148. SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
  149. SwapAndRestore(T &Restore_, T NewVal)
  150. : Restore(Restore_), OriginalValue(Restore) {
  151. Restore = std::move(NewVal);
  152. }
  153. ~SwapAndRestore() {
  154. if (ShouldRestore)
  155. Restore = std::move(OriginalValue);
  156. }
  157. void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
  158. void restoreNow(bool Force) {
  159. if (!Force && !ShouldRestore)
  160. return;
  161. Restore = std::move(OriginalValue);
  162. ShouldRestore = false;
  163. }
  164. SwapAndRestore(const SwapAndRestore &) = delete;
  165. SwapAndRestore &operator=(const SwapAndRestore &) = delete;
  166. };
  167. inline bool initializeOutputBuffer(char *Buf, size_t *N, OutputBuffer &OB,
  168. size_t InitSize) {
  169. size_t BufferSize;
  170. if (Buf == nullptr) {
  171. Buf = static_cast<char *>(std::malloc(InitSize));
  172. if (Buf == nullptr)
  173. return false;
  174. BufferSize = InitSize;
  175. } else
  176. BufferSize = *N;
  177. OB.reset(Buf, BufferSize);
  178. return true;
  179. }
  180. DEMANGLE_NAMESPACE_END
  181. #endif
  182. #ifdef __GNUC__
  183. #pragma GCC diagnostic pop
  184. #endif