#pragma once #include "types.hpp" #include #include #include #include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include #endif #include #include #include #include #include namespace util { #ifdef _WIN32 inline std::string to_string(std::wstring_view wstr) { const auto size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.length(), nullptr, 0, nullptr, nullptr); std::string str(size, 0); WideCharToMultiByte(CP_UTF8, 0, wstr.data(), wstr.length(), str.data(), str.length(), nullptr, nullptr); return str; } inline std::wstring to_wstring(std::string_view str) { const auto size = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), nullptr, 0); std::wstring wstr(size, 0); MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), wstr.data(), wstr.length()); return wstr; } #endif template std::basic_string to_lower(std::basic_string_view view) { std::basic_string out(view.size(), '\0'); std::transform( std::begin(view), std::end(view), std::begin(out), [](typename std::basic_string::value_type c) { return std::use_facet< std::ctype::value_type>>( std::locale()) .tolower(c); }); return out; } template constexpr bool string_eq_nocase(std::basic_string_view rh, std::basic_string_view lh) { const auto rh_lower = to_lower(rh); const auto lh_lower = to_lower(lh); return rh_lower == lh_lower; } template auto split_with(const std::basic_string &str, CharT delimiter) -> std::vector> { std::vector> parts; std::basic_string part; const auto start = str.find_first_not_of(delimiter); const auto end = str.find_last_not_of(delimiter); std::basic_istringstream stream( str.substr(start, end == std::string::npos ? end : end + 1)); while (std::getline(stream, part, delimiter)) parts.push_back(part); return parts; } #include template inline constexpr auto from_char_radix(const char &c, I radix = 10) -> I { I value = 0; if (std::isdigit(c)) { value = c - '0'; } else if (std::isalpha(c)) { if (std::isupper(c)) { value = c + 10 - 'A'; } else { value = c + 10 - 'a'; } } return value < radix ? value : std::numeric_limits::max(); } template inline constexpr auto from_string_view_radix(std::string_view view, I radix = 10) -> I { auto negative = false; if (view.starts_with('-')) { negative = true; view.remove_prefix(1); } else if (view.starts_with('+')) { negative = false; view.remove_prefix(1); } I value = 0; const auto max = std::numeric_limits::max(); for (auto &&c : view) { const auto i = from_char_radix(c, radix); if (i >= radix) { return max; } if (value > max / radix) { return max; } value *= radix; if (i > max - value) { return max; } value += i; } if (negative && std::is_signed_v) { return -value; } else { return value; } } } // namespace util