From 6a0e66b9127b8f9dff8baefbacc7982bfbe75111 Mon Sep 17 00:00:00 2001 From: Twilight-Dream-Of-Magic <31034152+Twilight-Dream-Of-Magic@users.noreply.github.com> Date: Thu, 9 Jun 2022 07:56:31 +0800 Subject: [PATCH 1/3] Forward To C++ 2020 and Compatible C++ 2011 [C++ 2020 template concept support] with repository https://github.com/mandreyel/mio/ Compatible with c++ standard 2011, and add c++ standard 2020 code. --- single_include/mio/mio.hpp | 312 +++++++++++++++++++++++++++++++++++-- 1 file changed, 303 insertions(+), 9 deletions(-) diff --git a/single_include/mio/mio.hpp b/single_include/mio/mio.hpp index c568a46..1b5d762 100644 --- a/single_include/mio/mio.hpp +++ b/single_include/mio/mio.hpp @@ -42,6 +42,155 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include + +#if __cplusplus >= 201103L && __cplusplus <= 201703L + +#include + +std::wstring cpp2017_string2wstring(const std::string &_string) +{ + using convert_typeX = std::codecvt_utf8; + std::wstring_convert converterX; + + return converterX.from_bytes(_string); +} + +std::string cpp2017_wstring2string(const std::wstring &_wstring) +{ + using convert_typeX = std::codecvt_utf8; + std::wstring_convert converterX; + + return converterX.to_bytes(_wstring); +} +#endif + +inline std::wstring string2wstring(const std::string& _string) +{ + ::setlocale(LC_ALL, ""); + std::vector wide_character_buffer; + std::size_t source_string_count = 1; + std::size_t found_not_ascii_count = 0; + for(auto begin = _string.begin(), end = _string.end(); begin != end; begin++) + { + if(static_cast(*begin) > 0) + { + ++source_string_count; + } + else if (static_cast(*begin) < 0) + { + ++found_not_ascii_count; + } + } + + std::size_t target_wstring_count = source_string_count + (found_not_ascii_count / 2); + + wide_character_buffer.resize(target_wstring_count); + std::size_t _converted_count = 0; + ::mbstowcs_s(&_converted_count, &wide_character_buffer[0], target_wstring_count, _string.c_str(), ((size_t)-1)); + + std::size_t _target_wstring_size = 0; + for(auto begin = wide_character_buffer.begin(), end = wide_character_buffer.end(); begin != end && *begin != L'\0'; begin++) + { + ++_target_wstring_size; + } + std::wstring _wstring{ wide_character_buffer.data(), _target_wstring_size }; + + if(_converted_count == 0) + { + throw std::runtime_error("The function string2wstring is not work !"); + } + else + { + if(found_not_ascii_count > 0) + { + //Need Contains character('\0') then check size + if(((_target_wstring_size + 1) - source_string_count) != (found_not_ascii_count / 2)) + { + throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); + } + else + { + return _wstring; + } + } + else + { + //Need Contains character('\0') then check size + if((_target_wstring_size + 1) != source_string_count) + { + throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); + } + else + { + return _wstring; + } + } + } +} + +inline std::string wstring2string(const std::wstring& _wstring) +{ + ::setlocale(LC_ALL, ""); + std::vector character_buffer; + std::size_t source_wstring_count = 1; + std::size_t found_not_ascii_count = 0; + for(auto begin = _wstring.begin(), end = _wstring.end(); begin != end; begin++) + { + if(static_cast(*begin) < 256) + { + ++source_wstring_count; + } + else if (static_cast(*begin) >= 256) + { + ++found_not_ascii_count; + } + } + std::size_t target_string_count = source_wstring_count + found_not_ascii_count * 2; + + character_buffer.resize(target_string_count); + ::size_t _converted_count = 0; + ::wcstombs_s(&_converted_count, &character_buffer[0], target_string_count, _wstring.c_str(), ((size_t)-1)); + + std::size_t _target_string_size = 0; + for(auto begin = character_buffer.begin(), end = character_buffer.end(); begin != end && *begin != '\0'; begin++) + { + ++_target_string_size; + } + std::string _string{ character_buffer.data(), _target_string_size }; + + if(_converted_count == 0) + { + throw std::runtime_error("The function wstring2string is not work !"); + } + else + { + if(found_not_ascii_count > 0) + { + if(((_target_string_size + 1) - source_wstring_count) != (found_not_ascii_count * 2)) + { + throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); + } + else + { + return _string; + } + } + else + { + if((_target_string_size + 1) != source_wstring_count) + { + throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); + } + else + { + return _string; + } + } + } +} + #ifndef MIO_PAGE_HEADER #define MIO_PAGE_HEADER @@ -53,6 +202,14 @@ namespace mio { + #ifdef min + #undef min + #endif //! min + + #ifdef max + #undef max + #endif //! max + /** * This is used by `basic_mmap` to determine whether to create a read-only or * a read-write memory mapping. @@ -623,6 +780,8 @@ mmap_sink make_mmap_sink(const MappingToken& token, std::error_code& error) namespace mio { namespace detail { +#if __cplusplus >= 201103L && __cplusplus < 202002L + template< typename S, typename C = typename std::decay::type, @@ -761,6 +920,86 @@ template< return !path || (*path == 0); } +#else + +#include + +template requires std::same_as +#ifdef _WIN32 + || std::same_as +#endif +struct type_helper +{ + static constexpr bool is_character_type() + { + if constexpr(std::is_pointer_v) + { + return std::same_as>>>; + } + else if constexpr(std::is_array_v) + { + return std::same_as>>>; + } + else + { + return std::same_as>>; + } + } +}; + +template +constexpr bool is_char_type = type_helper::is_character_type(); + +#ifdef _WIN32 +template +constexpr bool is_wchar_type = type_helper::is_character_type(); + +template +constexpr bool is_char_or_wchar_type = is_wchar_type || is_char_type; +#else +template +constexpr bool is_char_or_wchar_type = is_char_type; +#endif + +template +concept have_string_function_type = requires(AnyType object) +{ + object.data(); + object.c_str(); + std::convertible_to; +}; + +template +concept is_string_type = have_string_function_type && std::is_base_of_v>; + +#ifdef _WIN32 +template +concept is_wstring_type = have_string_function_type && std::is_base_of_v>; + +template requires is_wstring_type +const wchar_t* c_str(const StringType& path) +{ + return path.data(); +} +#endif + +template requires is_string_type +const char* c_str(const StringType& path) +{ + return path.data(); +} + +template requires is_string_type +#ifdef _WIN32 + || is_wstring_type +#endif +bool empty(StringType path) +{ + return path.empty(); +} + +#endif // __cplusplus >= 201103L && __cplusplus < 202002L + } // namespace detail } // namespace mio @@ -794,15 +1033,39 @@ inline DWORD int64_low(int64_t n) noexcept return n & 0xffffffff; } -std::wstring s_2_ws(const std::string& s) -{ - if (s.empty()) - return{}; - const auto s_length = static_cast(s.length()); - auto buf = std::vector(s_length); - const auto wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s_length, buf.data(), s_length); - return std::wstring(buf.data(), wide_char_count); -} +//std::wstring s_2_ws(const std::string& s) +//{ +// if (s.empty()) +// return{}; +// +// const auto s_length = static_cast(s.length()); +// auto buffer = std::vector(s_length); +// const auto wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s_length, buffer.data(), s_length); +// if (wide_char_count == 0) +// { +// const auto error = GetLastError(); +// DebugBreak(); +// } +// return std::wstring(buffer.data(), wide_char_count); +//} + +//std::string ws_2_s(const std::wstring& ws) +//{ +// if (ws.empty()) +// return{}; +// +// const auto ws_length = static_cast(ws.length()); +// auto buffer = std::vector(ws_length); +// const auto char_count = WideCharToMultiByte(CP_UTF8, 0, ws.c_str(), ws_length, buffer.data(), ws_length); +// if (char_count == 0) +// { +// const auto error = GetLastError(); +// DebugBreak(); +// } +// return std::string(buffer.data(), char_count); +//} + +#if __cplusplus >= 201103L && __cplusplus < 202002L template< typename String, @@ -835,6 +1098,37 @@ typename std::enable_if< 0); } +#else + +template +file_handle_type open_file_helper(const StringType& path, const access_mode mode) +{ + if constexpr (is_string_type) + { + std::wstring ws_path { string2wstring(path) }; + return open_file_helper(ws_path, mode); + } + if constexpr (is_wstring_type) + { + std::wstring ws_path { std::move(path) }; + return open_file_helper(ws_path, mode); + } +} + +template<> +inline file_handle_type open_file_helper(const std::wstring& path, const access_mode mode) +{ + return ::CreateFileW(c_str(path), + mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); +} + +#endif // __cplusplus >= 201103L && __cplusplus < 202002L + } // win #endif // _WIN32 From 6d020039c72403f97f9499398f4ce8a486c64945 Mon Sep 17 00:00:00 2001 From: Twilight-Dream-Of-Magic <31034152+Twilight-Dream-Of-Magic@users.noreply.github.com> Date: Thu, 9 Jun 2022 08:04:53 +0800 Subject: [PATCH 2/3] Update mio.hpp --- single_include/mio/mio.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/single_include/mio/mio.hpp b/single_include/mio/mio.hpp index 1b5d762..85c3c42 100644 --- a/single_include/mio/mio.hpp +++ b/single_include/mio/mio.hpp @@ -49,7 +49,7 @@ #include -std::wstring cpp2017_string2wstring(const std::string &_string) +inline std::wstring cpp2017_string2wstring(const std::string &_string) { using convert_typeX = std::codecvt_utf8; std::wstring_convert converterX; @@ -57,7 +57,7 @@ std::wstring cpp2017_string2wstring(const std::string &_string) return converterX.from_bytes(_string); } -std::string cpp2017_wstring2string(const std::wstring &_wstring) +inline std::string cpp2017_wstring2string(const std::wstring &_wstring) { using convert_typeX = std::codecvt_utf8; std::wstring_convert converterX; From f05574baf6fe51e15f4ffa3f73dde49c31bf365a Mon Sep 17 00:00:00 2001 From: Twilight-Dream-Of-Magic <31034152+Twilight-Dream-Of-Magic@users.noreply.github.com> Date: Sat, 13 Aug 2022 05:28:15 +0800 Subject: [PATCH 3/3] Updated UTF-8 conversion functions The GCC compiler is now supported --- single_include/mio/mio.hpp | 93 ++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/single_include/mio/mio.hpp b/single_include/mio/mio.hpp index 85c3c42..e7f6c30 100644 --- a/single_include/mio/mio.hpp +++ b/single_include/mio/mio.hpp @@ -42,13 +42,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include - #if __cplusplus >= 201103L && __cplusplus <= 201703L - -#include - inline std::wstring cpp2017_string2wstring(const std::string &_string) { using convert_typeX = std::codecvt_utf8; @@ -87,8 +81,13 @@ inline std::wstring string2wstring(const std::string& _string) std::size_t target_wstring_count = source_string_count + (found_not_ascii_count / 2); wide_character_buffer.resize(target_wstring_count); + + #if defined(_MSC_VER) std::size_t _converted_count = 0; ::mbstowcs_s(&_converted_count, &wide_character_buffer[0], target_wstring_count, _string.c_str(), ((size_t)-1)); + #else + ::mbstowcs(&wide_character_buffer[0], _string.c_str(), target_wstring_count); + #endif std::size_t _target_wstring_size = 0; for(auto begin = wide_character_buffer.begin(), end = wide_character_buffer.end(); begin != end && *begin != L'\0'; begin++) @@ -97,37 +96,38 @@ inline std::wstring string2wstring(const std::string& _string) } std::wstring _wstring{ wide_character_buffer.data(), _target_wstring_size }; + #if defined(_MSC_VER) if(_converted_count == 0) { throw std::runtime_error("The function string2wstring is not work !"); } + #endif + + if(found_not_ascii_count > 0) + { + //Need Contains character('\0') then check size + if(((_target_wstring_size + 1) - source_string_count) != (found_not_ascii_count / 2)) + { + throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); + } + else + { + return _wstring; + } + } else { - if(found_not_ascii_count > 0) + //Need Contains character('\0') then check size + if((_target_wstring_size + 1) != source_string_count) { - //Need Contains character('\0') then check size - if(((_target_wstring_size + 1) - source_string_count) != (found_not_ascii_count / 2)) - { - throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); - } - else - { - return _wstring; - } + throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); } else { - //Need Contains character('\0') then check size - if((_target_wstring_size + 1) != source_string_count) - { - throw std::runtime_error("The function string2wstring, An error occurs during conversion !"); - } - else - { - return _wstring; - } + return _wstring; } } + } inline std::string wstring2string(const std::wstring& _wstring) @@ -147,11 +147,16 @@ inline std::string wstring2string(const std::wstring& _wstring) ++found_not_ascii_count; } } - std::size_t target_string_count = source_wstring_count + found_not_ascii_count * 2; + std::size_t target_string_count = source_wstring_count + found_not_ascii_count * 2; character_buffer.resize(target_string_count); - ::size_t _converted_count = 0; + + #if defined(_MSC_VER) + std::size_t _converted_count = 0; ::wcstombs_s(&_converted_count, &character_buffer[0], target_string_count, _wstring.c_str(), ((size_t)-1)); + #else + ::wcstombs(&character_buffer[0], _wstring.c_str(), target_string_count); + #endif std::size_t _target_string_size = 0; for(auto begin = character_buffer.begin(), end = character_buffer.end(); begin != end && *begin != '\0'; begin++) @@ -160,33 +165,33 @@ inline std::string wstring2string(const std::wstring& _wstring) } std::string _string{ character_buffer.data(), _target_string_size }; + #if defined(_MSC_VER) if(_converted_count == 0) { throw std::runtime_error("The function wstring2string is not work !"); } + #endif + + if(found_not_ascii_count > 0) + { + if(((_target_string_size + 1) - source_wstring_count) != (found_not_ascii_count * 2)) + { + throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); + } + else + { + return _string; + } + } else { - if(found_not_ascii_count > 0) + if((_target_string_size + 1) != source_wstring_count) { - if(((_target_string_size + 1) - source_wstring_count) != (found_not_ascii_count * 2)) - { - throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); - } - else - { - return _string; - } + throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); } else { - if((_target_string_size + 1) != source_wstring_count) - { - throw std::runtime_error("The function wstring2string, An error occurs during conversion !"); - } - else - { - return _string; - } + return _string; } } }