Utility.h 5.0 KB

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