StringUtils.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "il2cpp-config.h"
  2. #include "../char-conversions.h"
  3. #include "il2cpp-object-internals.h"
  4. #include "utils/Functional.h"
  5. #include "utils/Memory.h"
  6. #include "utils/StringUtils.h"
  7. #include "utils/utf8-cpp/source/utf8/unchecked.h"
  8. #include <stdarg.h>
  9. namespace il2cpp
  10. {
  11. namespace utils
  12. {
  13. std::string StringUtils::Printf(const char* format, ...)
  14. {
  15. va_list argsToCheckSize;
  16. int n;
  17. std::string ret;
  18. va_start(argsToCheckSize, format);
  19. #if IL2CPP_COMPILER_MSVC
  20. // MS vsnprintf always returns -1 if string doesn't fit, rather than
  21. // the needed size. Used their 'special' function instead to get required size
  22. n = _vscprintf_p(format, argsToCheckSize);
  23. #else
  24. // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf
  25. char buf[1];
  26. n = vsnprintf(buf, 0, format, argsToCheckSize);
  27. #endif
  28. if (n == -1)
  29. return NULL;
  30. ret.resize(n + 1, 0);
  31. va_end(argsToCheckSize);
  32. va_list argsToFormat;
  33. va_start(argsToFormat, format);
  34. n = vsnprintf(&ret[0], ret.size(), format, argsToFormat);
  35. va_end(argsToFormat);
  36. IL2CPP_ASSERT(n < (int)ret.size());
  37. if (n == -1)
  38. return NULL;
  39. // The v*printf methods might put a trailing NUL character, which should not not be in a
  40. // std::string, so strip it out.
  41. if (!ret.empty() && ret[ret.size() - 1] == '\0')
  42. ret = ret.substr(0, ret.size() - 1);
  43. return ret;
  44. }
  45. std::string StringUtils::NPrintf(const char* format, size_t max_n, ...)
  46. {
  47. va_list argsToCheckSize;
  48. size_t n;
  49. std::string ret;
  50. va_start(argsToCheckSize, max_n);
  51. #if IL2CPP_COMPILER_MSVC
  52. // MS vsnprintf always returns -1 if string doesn't fit, rather than
  53. // the needed size. Used their 'special' function instead to get required size
  54. n = _vscprintf_p(format, argsToCheckSize);
  55. #else
  56. // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf
  57. char buf[1];
  58. n = vsnprintf(buf, 0, format, argsToCheckSize);
  59. #endif
  60. if (n == -1)
  61. return NULL;
  62. n = (max_n < ++n) ? max_n : n;
  63. ret.resize(n, 0);
  64. va_end(argsToCheckSize);
  65. va_list argsToFormat;
  66. va_start(argsToFormat, max_n);
  67. n = vsnprintf(&ret[0], n, format, argsToFormat);
  68. va_end(argsToFormat);
  69. IL2CPP_ASSERT(n < ret.size());
  70. if (n == -1)
  71. return NULL;
  72. // The v*printf methods might put a trailing NUL character, which should not not be in a
  73. // std::string, so strip it out.
  74. if (!ret.empty() && ret[ret.size() - 1] == '\0')
  75. ret = ret.substr(0, ret.size() - 1);
  76. return ret;
  77. }
  78. std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String)
  79. {
  80. return Utf16ToUtf8(utf16String, -1);
  81. }
  82. std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize)
  83. {
  84. const Il2CppChar* ptr = utf16String;
  85. size_t length = 0;
  86. while (*ptr)
  87. {
  88. ptr++;
  89. length++;
  90. if (maximumSize != -1 && length == maximumSize)
  91. break;
  92. }
  93. std::string utf8String;
  94. utf8String.reserve(length);
  95. utf8::unchecked::utf16to8(utf16String, ptr, std::back_inserter(utf8String));
  96. return utf8String;
  97. }
  98. std::string StringUtils::Utf16ToUtf8(const UTF16String& utf16String)
  99. {
  100. return Utf16ToUtf8(utf16String.c_str(), static_cast<int>(utf16String.length()));
  101. }
  102. UTF16String StringUtils::Utf8ToUtf16(const char* utf8String)
  103. {
  104. return Utf8ToUtf16(utf8String, strlen(utf8String));
  105. }
  106. UTF16String StringUtils::Utf8ToUtf16(const char* utf8String, size_t length)
  107. {
  108. UTF16String utf16String;
  109. if (utf8::is_valid(utf8String, utf8String + length))
  110. {
  111. utf16String.reserve(length);
  112. utf8::unchecked::utf8to16(utf8String, utf8String + length, std::back_inserter(utf16String));
  113. }
  114. return utf16String;
  115. }
  116. UTF16String StringUtils::Utf8ToUtf16(const std::string& utf8String)
  117. {
  118. return Utf8ToUtf16(utf8String.c_str(), utf8String.length());
  119. }
  120. char* StringUtils::StringDuplicate(const char *strSource)
  121. {
  122. char* result = NULL;
  123. if (!strSource)
  124. return NULL;
  125. size_t length = strlen(strSource) + 1;
  126. if ((result = (char*)IL2CPP_MALLOC(length)))
  127. #if IL2CPP_COMPILER_MSVC
  128. strcpy_s(result, length, strSource);
  129. #elif IL2CPP_TARGET_LINUX
  130. strncpy(result, strSource, length);
  131. #else
  132. strlcpy(result, strSource, length);
  133. #endif
  134. return result;
  135. }
  136. Il2CppChar* StringUtils::StringDuplicate(const Il2CppChar* strSource, size_t length)
  137. {
  138. size_t byteLengthWithNullTerminator = sizeof(Il2CppChar) * (length + 1);
  139. Il2CppChar* utf16name = (Il2CppChar*)IL2CPP_MALLOC(byteLengthWithNullTerminator);
  140. memcpy(utf16name, strSource, byteLengthWithNullTerminator);
  141. return utf16name;
  142. }
  143. void StringUtils::StringDelete(const char* str)
  144. {
  145. IL2CPP_FREE((void*)str);
  146. }
  147. bool StringUtils::EndsWith(const std::string& string, const std::string& suffix)
  148. {
  149. const size_t stringLength = string.length();
  150. const size_t suffixLength = suffix.length();
  151. if (suffixLength > stringLength)
  152. return false;
  153. return string.rfind(suffix.c_str(), stringLength - suffixLength, suffixLength) != std::string::npos;
  154. }
  155. Il2CppChar* StringUtils::GetChars(Il2CppString* str)
  156. {
  157. return str->chars;
  158. }
  159. int32_t StringUtils::GetLength(Il2CppString* str)
  160. {
  161. return str->length;
  162. }
  163. } /* utils */
  164. } /* il2cpp */