StringView.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #pragma once
  2. #include "il2cpp-config.h"
  3. #include <limits.h>
  4. #if IL2CPP_TARGET_WINDOWS
  5. #include <malloc.h>
  6. #else
  7. #include <alloca.h>
  8. #endif
  9. namespace il2cpp
  10. {
  11. namespace utils
  12. {
  13. template<typename CharType>
  14. class StringView
  15. {
  16. private:
  17. const CharType* m_String;
  18. size_t m_Length;
  19. // Intended to only be used by Empty()
  20. inline StringView() :
  21. m_String(NULL),
  22. m_Length(0)
  23. {
  24. }
  25. public:
  26. template<size_t Length>
  27. inline StringView(const CharType(&str)[Length]) :
  28. m_String(str), m_Length(Length - 1)
  29. {
  30. }
  31. inline StringView(const CharType* str, size_t length) :
  32. m_String(str), m_Length(length)
  33. {
  34. IL2CPP_ASSERT(str != NULL);
  35. }
  36. inline StringView(const CharType* str, size_t startIndex, size_t length) :
  37. m_String(str + startIndex), m_Length(length)
  38. {
  39. IL2CPP_ASSERT(str != NULL);
  40. }
  41. inline StringView(const StringView<CharType>& str, size_t startIndex, size_t length) :
  42. m_String(str.Str() + startIndex),
  43. m_Length(length)
  44. {
  45. IL2CPP_ASSERT(startIndex + length <= str.Length());
  46. }
  47. // This is to work around a bug in gcc (24666) where arrays decay to pointers too fast
  48. // This is known to be fixed by at least 7.3.0
  49. #if defined(__GNUC__) && IL2CPP_GCC_VERSION < 70300
  50. inline StringView(const char* str) :
  51. m_String(str), m_Length(strlen(str))
  52. {
  53. }
  54. #endif
  55. inline const CharType* Str() const
  56. {
  57. return m_String;
  58. }
  59. inline size_t Length() const
  60. {
  61. return m_Length;
  62. }
  63. inline CharType operator[](size_t index) const
  64. {
  65. return m_String[index];
  66. }
  67. inline bool IsNullTerminated() const
  68. {
  69. return m_String[m_Length] == 0;
  70. }
  71. inline bool IsEmpty() const
  72. {
  73. return Length() == 0;
  74. }
  75. static inline StringView<CharType> Empty()
  76. {
  77. return StringView<CharType>();
  78. }
  79. inline size_t Find(CharType c, size_t startIndex = 0) const
  80. {
  81. const CharType* end = m_String + m_Length;
  82. for (const CharType* ptr = m_String + startIndex; ptr < end; ptr++)
  83. {
  84. if (*ptr == c)
  85. return ptr - m_String;
  86. }
  87. return NPos();
  88. }
  89. inline size_t RFind(CharType c) const
  90. {
  91. for (const CharType* ptr = m_String + m_Length; ptr-- > m_String;)
  92. {
  93. if (*ptr == c)
  94. return ptr - m_String;
  95. }
  96. return NPos();
  97. }
  98. inline StringView<CharType> SubStr(size_t startIndex, size_t length)
  99. {
  100. return StringView<CharType>(*this, startIndex, length);
  101. }
  102. inline StringView<CharType> SubStr(size_t startIndex)
  103. {
  104. return StringView<CharType>(*this, startIndex, Length() - startIndex);
  105. }
  106. inline static size_t NPos()
  107. {
  108. return static_cast<size_t>(-1);
  109. }
  110. inline bool TryParseAsInt(int& outResult)
  111. {
  112. if (Length() == 0)
  113. return false;
  114. int result = 0;
  115. bool isNegative = false;
  116. const CharType* ptr = m_String;
  117. const CharType* end = m_String + m_Length;
  118. if (ptr[0] == '-')
  119. {
  120. isNegative = true;
  121. ptr++;
  122. }
  123. for (; ptr < end; ptr++)
  124. {
  125. CharType digit = *ptr;
  126. if (digit < '0' || digit > '9')
  127. return false;
  128. int digitNumeric = digit - '0';
  129. if (result > INT_MAX / 10)
  130. return false;
  131. result = result * 10;
  132. if (result > INT_MAX - digitNumeric)
  133. return false;
  134. result += digitNumeric;
  135. }
  136. if (isNegative)
  137. {
  138. outResult = -result;
  139. }
  140. else
  141. {
  142. outResult = result;
  143. }
  144. return true;
  145. }
  146. };
  147. #define StringViewAsNullTerminatedStringOf(CharType, stringView, variableName) \
  148. const CharType* variableName; \
  149. do \
  150. { \
  151. if (!stringView.IsEmpty() && stringView.IsNullTerminated()) \
  152. { \
  153. variableName = stringView.Str(); \
  154. } \
  155. else \
  156. { \
  157. CharType* buffer = static_cast<CharType*>(alloca((stringView.Length() + 1) * sizeof(CharType))); \
  158. memcpy(buffer, stringView.Str(), stringView.Length() * sizeof(CharType)); \
  159. buffer[stringView.Length()] = 0; \
  160. variableName = buffer; \
  161. } \
  162. } \
  163. while (false)
  164. }
  165. }