#pragma once #include "types.h" #include #include #include #include #include #include #include #include #if defined(__has_include) && __has_include() #include #ifndef _MSC_VER #include #endif #else #include #endif namespace StringUtil { /// Constructs a std::string from a format string. std::string StdStringFromFormat(const char* format, ...) printflike(1, 2); std::string StdStringFromFormatV(const char* format, std::va_list ap); /// Checks if a wildcard matches a search string. bool WildcardMatch(const char* subject, const char* mask, bool case_sensitive = true); /// Safe version of strlcpy. std::size_t Strlcpy(char* dst, const char* src, std::size_t size); /// Strlcpy from string_view. std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size); /// Platform-independent strcasecmp static inline int Strcasecmp(const char* s1, const char* s2) { #ifdef _MSC_VER return _stricmp(s1, s2); #else return strcasecmp(s1, s2); #endif } /// Platform-independent strcasecmp static inline int Strncasecmp(const char* s1, const char* s2, std::size_t n) { #ifdef _MSC_VER return _strnicmp(s1, s2, n); #else return strncasecmp(s1, s2, n); #endif } /// Wrapper arond std::from_chars template::value, bool> = true> inline std::optional FromChars(const std::string_view& str, int base = 10) { T value; #if defined(__has_include) && __has_include() const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.length(), value, base); if (result.ec != std::errc()) return std::nullopt; #else std::string temp(str); std::istringstream ss(temp); ss >> std::setbase(base) >> value; if (ss.fail()) return std::nullopt; #endif return value; } template::value, bool> = true> inline std::optional FromChars(const std::string_view& str) { T value; #if defined(__has_include) && __has_include() && defined(_MSC_VER) const std::from_chars_result result = std::from_chars(str.data(), str.data() + str.length(), value); if (result.ec != std::errc()) return std::nullopt; #else /// libstdc++ does not support from_chars with floats yet std::string temp(str); std::istringstream ss(temp); ss >> value; if (ss.fail()) return std::nullopt; #endif return value; } /// Explicit override for booleans template<> inline std::optional FromChars(const std::string_view& str, int base) { if (Strncasecmp("true", str.data(), str.length()) == 0 || Strncasecmp("yes", str.data(), str.length()) == 0 || Strncasecmp("on", str.data(), str.length()) == 0 || Strncasecmp("1", str.data(), str.length()) == 0) { return true; } if (Strncasecmp("false", str.data(), str.length()) == 0 || Strncasecmp("no", str.data(), str.length()) == 0 || Strncasecmp("off", str.data(), str.length()) == 0 || Strncasecmp("0", str.data(), str.length()) == 0) { return false; } return std::nullopt; } /// Encode/decode hexadecimal byte buffers std::optional> DecodeHex(const std::string_view& str); std::string EncodeHex(const u8* data, int length); /// starts_with from C++20 ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* prefix) { return (str.compare(0, std::strlen(prefix), prefix) == 0); } ALWAYS_INLINE static bool EndsWith(const std::string_view& str, const char* suffix) { const std::size_t suffix_length = std::strlen(suffix); return (str.length() >= suffix_length && str.compare(str.length() - suffix_length, suffix_length, suffix) == 0); } /// Strided memcpy/memcmp. ALWAYS_INLINE static void StrideMemCpy(void* dst, std::size_t dst_stride, const void* src, std::size_t src_stride, std::size_t copy_size, std::size_t count) { const u8* src_ptr = static_cast(src); u8* dst_ptr = static_cast(dst); for (std::size_t i = 0; i < count; i++) { std::memcpy(dst_ptr, src_ptr, copy_size); src_ptr += src_stride; dst_ptr += dst_stride; } } ALWAYS_INLINE static int StrideMemCmp(const void* p1, std::size_t p1_stride, const void* p2, std::size_t p2_stride, std::size_t copy_size, std::size_t count) { const u8* p1_ptr = static_cast(p1); const u8* p2_ptr = static_cast(p2); for (std::size_t i = 0; i < count; i++) { int result = std::memcmp(p1_ptr, p2_ptr, copy_size); if (result != 0) return result; p2_ptr += p2_stride; p1_ptr += p1_stride; } return 0; } #ifdef _WIN32 /// Converts the specified UTF-8 string to a wide string. std::wstring UTF8StringToWideString(const std::string_view& str); bool UTF8StringToWideString(std::wstring& dest, const std::string_view& str); /// Converts the specified wide string to a UTF-8 string. std::string WideStringToUTF8String(const std::wstring_view& str); bool WideStringToUTF8String(std::string& dest, const std::wstring_view& str); #endif } // namespace StringUtil