#include "il2cpp-config.h" #include "../char-conversions.h" #include "il2cpp-object-internals.h" #include "utils/Functional.h" #include "utils/Memory.h" #include "utils/StringUtils.h" #include "utils/utf8-cpp/source/utf8/unchecked.h" #include namespace il2cpp { namespace utils { std::string StringUtils::Printf(const char* format, ...) { va_list argsToCheckSize; int n; std::string ret; va_start(argsToCheckSize, format); #if IL2CPP_COMPILER_MSVC // MS vsnprintf always returns -1 if string doesn't fit, rather than // the needed size. Used their 'special' function instead to get required size n = _vscprintf_p(format, argsToCheckSize); #else // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf char buf[1]; n = vsnprintf(buf, 0, format, argsToCheckSize); #endif if (n == -1) return NULL; ret.resize(n + 1, 0); va_end(argsToCheckSize); va_list argsToFormat; va_start(argsToFormat, format); n = vsnprintf(&ret[0], ret.size(), format, argsToFormat); va_end(argsToFormat); IL2CPP_ASSERT(n < (int)ret.size()); if (n == -1) return NULL; // The v*printf methods might put a trailing NUL character, which should not not be in a // std::string, so strip it out. if (!ret.empty() && ret[ret.size() - 1] == '\0') ret = ret.substr(0, ret.size() - 1); return ret; } std::string StringUtils::NPrintf(const char* format, size_t max_n, ...) { va_list argsToCheckSize; size_t n; std::string ret; va_start(argsToCheckSize, max_n); #if IL2CPP_COMPILER_MSVC // MS vsnprintf always returns -1 if string doesn't fit, rather than // the needed size. Used their 'special' function instead to get required size n = _vscprintf_p(format, argsToCheckSize); #else // use a temporary buffer as some docs indicate we cannot pass NULL to vsnprintf char buf[1]; n = vsnprintf(buf, 0, format, argsToCheckSize); #endif if (n == -1) return NULL; n = (max_n < ++n) ? max_n : n; ret.resize(n, 0); va_end(argsToCheckSize); va_list argsToFormat; va_start(argsToFormat, max_n); n = vsnprintf(&ret[0], n, format, argsToFormat); va_end(argsToFormat); IL2CPP_ASSERT(n < ret.size()); if (n == -1) return NULL; // The v*printf methods might put a trailing NUL character, which should not not be in a // std::string, so strip it out. if (!ret.empty() && ret[ret.size() - 1] == '\0') ret = ret.substr(0, ret.size() - 1); return ret; } std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String) { return Utf16ToUtf8(utf16String, -1); } std::string StringUtils::Utf16ToUtf8(const Il2CppChar* utf16String, int maximumSize) { const Il2CppChar* ptr = utf16String; size_t length = 0; while (*ptr) { ptr++; length++; if (maximumSize != -1 && length == maximumSize) break; } std::string utf8String; utf8String.reserve(length); utf8::unchecked::utf16to8(utf16String, ptr, std::back_inserter(utf8String)); return utf8String; } std::string StringUtils::Utf16ToUtf8(const UTF16String& utf16String) { return Utf16ToUtf8(utf16String.c_str(), static_cast(utf16String.length())); } UTF16String StringUtils::Utf8ToUtf16(const char* utf8String) { return Utf8ToUtf16(utf8String, strlen(utf8String)); } UTF16String StringUtils::Utf8ToUtf16(const char* utf8String, size_t length) { UTF16String utf16String; if (utf8::is_valid(utf8String, utf8String + length)) { utf16String.reserve(length); utf8::unchecked::utf8to16(utf8String, utf8String + length, std::back_inserter(utf16String)); } return utf16String; } UTF16String StringUtils::Utf8ToUtf16(const std::string& utf8String) { return Utf8ToUtf16(utf8String.c_str(), utf8String.length()); } char* StringUtils::StringDuplicate(const char *strSource) { char* result = NULL; if (!strSource) return NULL; size_t length = strlen(strSource) + 1; if ((result = (char*)IL2CPP_MALLOC(length))) #if IL2CPP_COMPILER_MSVC strcpy_s(result, length, strSource); #elif IL2CPP_TARGET_LINUX strncpy(result, strSource, length); #else strlcpy(result, strSource, length); #endif return result; } Il2CppChar* StringUtils::StringDuplicate(const Il2CppChar* strSource, size_t length) { size_t byteLengthWithNullTerminator = sizeof(Il2CppChar) * (length + 1); Il2CppChar* utf16name = (Il2CppChar*)IL2CPP_MALLOC(byteLengthWithNullTerminator); memcpy(utf16name, strSource, byteLengthWithNullTerminator); return utf16name; } void StringUtils::StringDelete(const char* str) { IL2CPP_FREE((void*)str); } bool StringUtils::EndsWith(const std::string& string, const std::string& suffix) { const size_t stringLength = string.length(); const size_t suffixLength = suffix.length(); if (suffixLength > stringLength) return false; return string.rfind(suffix.c_str(), stringLength - suffixLength, suffixLength) != std::string::npos; } Il2CppChar* StringUtils::GetChars(Il2CppString* str) { return str->chars; } int32_t StringUtils::GetLength(Il2CppString* str) { return str->length; } } /* utils */ } /* il2cpp */