#pragma once #include #include template struct UNICODE_STRING { USHORT Length; USHORT MaximumLength; EMULATOR_CAST(typename Traits::PVOID, char16_t*) Buffer; }; inline std::u16string u8_to_u16(const std::string_view view) { return std::u16string(view.begin(), view.end()); } inline std::string u16_to_u8(const std::u16string_view u16_view) { std::string utf8_str; utf8_str.reserve(u16_view.size() * 2); for (const char16_t ch : u16_view) { if (ch <= 0x7F) { utf8_str.push_back(static_cast(ch)); } else if (ch <= 0x7FF) { utf8_str.push_back(static_cast(0xC0 | (ch >> 6))); utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); } else { utf8_str.push_back(static_cast(0xE0 | (ch >> 12))); utf8_str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); } } return utf8_str; } inline std::string w_to_u8(const std::wstring_view w_view) { std::string utf8_str; utf8_str.reserve(w_view.size() * 2); for (const wchar_t w_ch : w_view) { const auto ch = static_cast(w_ch); if (ch <= 0x7F) { utf8_str.push_back(static_cast(ch)); } else if (ch <= 0x7FF) { utf8_str.push_back(static_cast(0xC0 | (ch >> 6))); utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); } else { utf8_str.push_back(static_cast(0xE0 | (ch >> 12))); utf8_str.push_back(static_cast(0x80 | ((ch >> 6) & 0x3F))); utf8_str.push_back(static_cast(0x80 | (ch & 0x3F))); } } return utf8_str; } #ifndef OS_WINDOWS inline int open_unicode(FILE** handle, const std::filesystem::path& fileName, const std::u16string& mode) { *handle = fopen(fileName.string().c_str(), u16_to_u8(mode).c_str()); return errno; } #else inline std::wstring u16_to_w(const std::u16string& u16str) { return std::wstring(reinterpret_cast(u16str.data()), u16str.size()); } inline auto open_unicode(FILE** handle, const std::filesystem::path& fileName, const std::u16string& mode) { return _wfopen_s(handle, fileName.wstring().c_str(), u16_to_w(mode).c_str()); } #endif