Utility.h 5.0 KB

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