StringView.h 5.0 KB

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