StringView.h 4.9 KB

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