StringUtils.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // The MIT License (MIT)
  2. //
  3. // Copyright(c) Unity Technologies, Microsoft Corporation
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files(the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions :
  11. //
  12. // The above copyright notice and this permission notice shall be included in all
  13. // copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. // SOFTWARE.
  22. #pragma once
  23. #include "il2cpp-string-types.h"
  24. #include <string>
  25. #include <vector>
  26. #include <limits>
  27. #include <stdint.h>
  28. #include "il2cpp-config.h"
  29. #include "StringView.h"
  30. #include "StringViewUtils.h"
  31. #include "Baselib.h"
  32. namespace il2cpp
  33. {
  34. namespace utils
  35. {
  36. class LIBIL2CPP_CODEGEN_API StringUtils
  37. {
  38. public:
  39. static std::string Printf(const char* format, ...);
  40. static std::string NPrintf(const char* format, size_t max_n, ...);
  41. static std::string Utf16ToUtf8(const Il2CppChar* utf16String);
  42. static std::string Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize);
  43. static std::string Utf16ToUtf8(const UTF16String& utf16String);
  44. static UTF16String Utf8ToUtf16(const char* utf8String);
  45. static UTF16String Utf8ToUtf16(const char* utf8String, size_t length);
  46. static UTF16String Utf8ToUtf16(const std::string& utf8String);
  47. static char* StringDuplicate(const char *strSource);
  48. static Il2CppChar* StringDuplicate(const Il2CppChar* strSource, size_t length);
  49. static bool EndsWith(const std::string& string, const std::string& suffix);
  50. static Il2CppChar* GetChars(Il2CppString* str);
  51. static int32_t GetLength(Il2CppString* str);
  52. static void StringDelete(const char* str);
  53. #if IL2CPP_TARGET_WINDOWS
  54. static inline std::string NativeStringToUtf8(const Il2CppNativeString& nativeStr)
  55. {
  56. IL2CPP_ASSERT(nativeStr.length() < static_cast<size_t>(std::numeric_limits<int>::max()));
  57. return Utf16ToUtf8(nativeStr.c_str(), static_cast<int>(nativeStr.length()));
  58. }
  59. static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr)
  60. {
  61. return Utf16ToUtf8(nativeStr);
  62. }
  63. static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr, uint32_t length)
  64. {
  65. IL2CPP_ASSERT(length < static_cast<uint32_t>(std::numeric_limits<int>::max()));
  66. return Utf16ToUtf8(nativeStr, static_cast<int>(length));
  67. }
  68. static inline Il2CppNativeString Utf8ToNativeString(const std::string& str)
  69. {
  70. IL2CPP_ASSERT(str.length() < static_cast<size_t>(std::numeric_limits<int>::max()));
  71. return Utf8ToUtf16(str.c_str(), str.length());
  72. }
  73. static inline Il2CppNativeString Utf8ToNativeString(const char* str)
  74. {
  75. return Utf8ToUtf16(str);
  76. }
  77. #else
  78. static inline std::string NativeStringToUtf8(Il2CppNativeString& nativeStr)
  79. {
  80. return nativeStr;
  81. }
  82. static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr)
  83. {
  84. return nativeStr;
  85. }
  86. static inline std::string NativeStringToUtf8(const Il2CppNativeChar* nativeStr, uint32_t length)
  87. {
  88. return std::string(nativeStr, length);
  89. }
  90. static inline Il2CppNativeString Utf8ToNativeString(const std::string& str)
  91. {
  92. return str;
  93. }
  94. static inline Il2CppNativeString Utf8ToNativeString(const char* str)
  95. {
  96. return str;
  97. }
  98. #endif
  99. template<typename CharType, size_t N>
  100. static inline size_t LiteralLength(const CharType(&str)[N])
  101. {
  102. return N - 1;
  103. }
  104. template<typename CharType>
  105. static size_t StrLen(const CharType* str)
  106. {
  107. size_t length = 0;
  108. while (*str)
  109. {
  110. str++;
  111. length++;
  112. }
  113. return length;
  114. }
  115. template <typename CharType>
  116. static inline bool Equals(const StringView<CharType>& left, const StringView<CharType>& right)
  117. {
  118. if (left.Length() != right.Length())
  119. return false;
  120. return memcmp(left.Str(), right.Str(), left.Length() * sizeof(CharType)) == 0;
  121. }
  122. template <typename CharType, size_t rightLength>
  123. static inline bool Equals(const StringView<CharType>& left, const CharType (&right)[rightLength])
  124. {
  125. if (left.Length() != rightLength - 1)
  126. return false;
  127. return memcmp(left.Str(), right, (rightLength - 1) * sizeof(CharType)) == 0;
  128. }
  129. template <typename CharType>
  130. static inline bool StartsWith(const StringView<CharType>& left, const StringView<CharType>& right)
  131. {
  132. if (left.Length() < right.Length())
  133. return false;
  134. return memcmp(left.Str(), right.Str(), right.Length() * sizeof(CharType)) == 0;
  135. }
  136. template <typename CharType, size_t rightLength>
  137. static inline bool StartsWith(const StringView<CharType>& left, const CharType(&right)[rightLength])
  138. {
  139. if (left.Length() < rightLength - 1)
  140. return false;
  141. return memcmp(left.Str(), right, (rightLength - 1) * sizeof(CharType)) == 0;
  142. }
  143. // Taken from github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs
  144. template<typename CharType>
  145. static inline size_t Hash(const CharType *str, size_t length)
  146. {
  147. IL2CPP_ASSERT(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
  148. size_t hash1 = 5381;
  149. size_t hash2 = hash1;
  150. size_t i = 0;
  151. CharType c;
  152. const CharType* s = str;
  153. while (true)
  154. {
  155. if (i++ >= length)
  156. break;
  157. c = s[0];
  158. hash1 = ((hash1 << 5) + hash1) ^ c;
  159. if (i++ >= length)
  160. break;
  161. c = s[1];
  162. hash2 = ((hash2 << 5) + hash2) ^ c;
  163. s += 2;
  164. }
  165. return hash1 + (hash2 * 1566083941);
  166. }
  167. template<typename CharType>
  168. static inline size_t Hash(const CharType *str)
  169. {
  170. size_t hash1 = 5381;
  171. size_t hash2 = hash1;
  172. CharType c;
  173. const CharType* s = str;
  174. while ((c = s[0]) != 0)
  175. {
  176. hash1 = ((hash1 << 5) + hash1) ^ c;
  177. c = s[1];
  178. if (c == 0)
  179. break;
  180. hash2 = ((hash2 << 5) + hash2) ^ c;
  181. s += 2;
  182. }
  183. return hash1 + (hash2 * 1566083941);
  184. }
  185. template<typename StringType>
  186. struct StringHasher
  187. {
  188. typedef typename StringType::value_type CharType;
  189. size_t operator()(const StringType& value) const
  190. {
  191. return Hash(value.c_str(), value.length());
  192. }
  193. };
  194. template<typename CharType>
  195. struct StringHasher<const CharType*>
  196. {
  197. size_t operator()(const CharType* value) const
  198. {
  199. return Hash(value);
  200. }
  201. };
  202. #if defined(_MSC_VER)
  203. static inline const baselib_char16_t* NativeStringToBaselib(const Il2CppNativeChar* str)
  204. {
  205. static_assert(sizeof(Il2CppNativeChar) == sizeof(baselib_char16_t), "type sizes should match");
  206. return reinterpret_cast<const baselib_char16_t*>(str);
  207. }
  208. #else
  209. static inline const char* NativeStringToBaselib(const Il2CppNativeChar* str)
  210. {
  211. static_assert(sizeof(Il2CppNativeChar) == sizeof(char), "type sizes should match");
  212. return str;
  213. }
  214. #endif
  215. };
  216. } /* utils */
  217. } /* il2cpp */
  218. // Assumes str is not NULL
  219. #if defined(_MSC_VER)
  220. #define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
  221. il2cpp::utils::StringView<Il2CppNativeChar> variableName((str)->chars, (str)->length);
  222. #define DECLARE_IL2CPP_CHAR_PTR_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
  223. il2cpp::utils::StringView<Il2CppNativeChar> variableName(str, il2cpp::utils::StringUtils::StrLen (str));
  224. #define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
  225. il2cpp::utils::StringView<Il2CppChar> variableName(str, wcslen(str));
  226. #define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
  227. il2cpp::utils::StringView<Il2CppChar> variableName = STRING_TO_STRINGVIEW(str);
  228. #else
  229. #define DECLARE_IL2CPP_STRING_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
  230. Il2CppNativeString variableName##_native_string_storage = il2cpp::utils::StringUtils::Utf16ToUtf8((str)->chars, (str)->length); \
  231. il2cpp::utils::StringView<Il2CppNativeChar> variableName(variableName##_native_string_storage.c_str(), variableName##_native_string_storage.length());
  232. #define DECLARE_IL2CPP_CHAR_PTR_AS_STRING_VIEW_OF_NATIVE_CHARS(variableName, str) \
  233. Il2CppNativeString variableName##_native_string_storage = il2cpp::utils::StringUtils::Utf16ToUtf8(str, il2cpp::utils::StringUtils::StrLen (str)); \
  234. il2cpp::utils::StringView<Il2CppNativeChar> variableName(variableName##_native_string_storage.c_str(), variableName##_native_string_storage.length());
  235. #define DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS(variableName, str) \
  236. UTF16String variableName##_utf16String = il2cpp::utils::StringUtils::Utf8ToUtf16(str); \
  237. il2cpp::utils::StringView<Il2CppChar> variableName = STRING_TO_STRINGVIEW(variableName##_utf16String);
  238. #define DECLARE_NATIVE_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS DECLARE_NATIVE_C_STRING_AS_STRING_VIEW_OF_IL2CPP_CHARS
  239. #endif