feat: add various functions
- Add Win32 CopyFile, MoveFile, DeleteFile functions in WinFctHelper. - rename FsPathPatch to StdPatch because this namespace will hold all standard library patches in future. - add polyfill for std:basic_string::starts_with, std::basic_string::ends_with std::basic_string_view::starts_with, std::basic_string_view::ends_with in StdPatch. - add polyfill for unordered and ordered associative standard library container's contains function in StdPatch. - documentation and testbench will be fixed in later commits.
This commit is contained in:
		| @ -43,7 +43,7 @@ | ||||
|  | ||||
|     \li \subpage io_helper | ||||
|  | ||||
|     \li \subpage fs_path_patch | ||||
|     \li \subpage std_patch | ||||
|  | ||||
|     <B>Advanced Features</B> | ||||
|  | ||||
|  | ||||
| @ -1,7 +1,9 @@ | ||||
| namespace YYCC::FsPathPatch { | ||||
| namespace YYCC::StdPatch { | ||||
| /** | ||||
| 
 | ||||
| \page fs_path_patch std::filesystem::path Patch | ||||
| \page std_patch Standard Library Patch | ||||
| 
 | ||||
| \section std_patch__fs_path std::filesystem::path Patch | ||||
| 
 | ||||
| As you know, the underlying char type of \c std::filesystem::path is \c wchar_t on Windows, | ||||
| and in other platforms, it is simple \c char. | ||||
| @ -23,17 +25,17 @@ This patch is served for Windows but also works on other plaftoms. | ||||
| If you are in Windows, this patch will perform extra operations to achieve goals, | ||||
| and in other platforms, they just redirect request to corresponding vanilla C++ functions. | ||||
| 
 | ||||
| \section fs_path_patch__from_utf8_path Create Path from UTF8 String | ||||
| \subsection std_patch__fs_path__from_utf8_path Create Path from UTF8 String | ||||
| 
 | ||||
| #FromUTF8Path provides this feature. | ||||
| #ToStdPath provides this feature. | ||||
| It accepts an string pointer to UTF8 string and try to create \c std::filesystem::path from it. | ||||
| Function will throw exception if encoding convertion or constructor self failed. | ||||
| There are some example: | ||||
| 
 | ||||
| \code | ||||
| auto foobar_path = YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("/foo/bar")); | ||||
| auto slashed_path = foobar_path / YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("test")); | ||||
| auto replaced_ext = foobar_path.replace_extension(YYCC::FsPathPatch::FromUTF8Path(YYCC_U8(".txt"))); | ||||
| auto foobar_path = YYCC::StdPatch::ToStdPath(YYCC_U8("/foo/bar")); | ||||
| auto slashed_path = foobar_path / YYCC::StdPatch::ToStdPath(YYCC_U8("test")); | ||||
| auto replaced_ext = foobar_path.replace_extension(YYCC::StdPatch::ToStdPath(YYCC_U8(".txt"))); | ||||
| \endcode | ||||
| 
 | ||||
| For first line in example, it is obvious that you can create a \c std::filesystem::path from this function. | ||||
| @ -58,17 +60,17 @@ However it is depracted since C++ 20, | ||||
| because \c std::filesystem::path directly supports UTF8 by \c char8_t since C++ 20. | ||||
| Because C++ standard is volatile, we create this function to have an uniform programming experience. | ||||
| 
 | ||||
| \section fs_path_patch__to_utf8_path Extract UTF8 Path String from Path | ||||
| \subsection std_patch__fs_path__to_utf8_path Extract UTF8 Path String from Path | ||||
| 
 | ||||
| #ToUTF8Path provides this feature. | ||||
| It basically is the reversed operation of #FromUTF8Path. | ||||
| It basically is the reversed operation of #ToStdPath. | ||||
| It is usually used when you have done all path work in \c std::filesystem::path | ||||
| and want to get the result. | ||||
| There is an example: | ||||
| 
 | ||||
| \code | ||||
| auto foobar_path = YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("/foo/bar")); | ||||
| auto result = YYCC::FsPathPatch::ToUTF8Path(foobar_path / YYCC::FsPathPatch::FromUTF8Path(YYCC_U8("test"))); | ||||
| auto foobar_path = YYCC::StdPatch::ToStdPath(YYCC_U8("/foo/bar")); | ||||
| auto result = YYCC::StdPatch::ToUTF8Path(foobar_path / YYCC::StdPatch::ToStdPath(YYCC_U8("test"))); | ||||
| \endcode | ||||
| 
 | ||||
| */ | ||||
| @ -11,7 +11,7 @@ PRIVATE | ||||
|     DialogHelper.cpp | ||||
|     EncodingHelper.cpp | ||||
|     ExceptionHelper.cpp | ||||
|     FsPathPatch.cpp | ||||
|     StdPatch.cpp | ||||
|     IOHelper.cpp | ||||
|     StringHelper.cpp | ||||
|     WinFctHelper.cpp | ||||
| @ -32,7 +32,7 @@ FILES | ||||
|     DialogHelper.hpp | ||||
|     EncodingHelper.hpp | ||||
|     ExceptionHelper.hpp | ||||
|     FsPathPatch.hpp | ||||
|     StdPatch.hpp | ||||
|     IOHelper.hpp | ||||
|     ParserHelper.hpp | ||||
|     StringHelper.hpp | ||||
| @ -71,8 +71,12 @@ PRIVATE | ||||
|     $<$<CXX_COMPILER_ID:MSVC>:UNICODE> | ||||
|     $<$<CXX_COMPILER_ID:MSVC>:_UNICODE> | ||||
| ) | ||||
| # Order build as UTF-8 in MSVC | ||||
| target_compile_options(YYCCommonplace | ||||
| # Enable new __cplusplus macro in MSVC. | ||||
| # Because we use it in header, so we need populate it. | ||||
| PUBLIC | ||||
|     $<$<CXX_COMPILER_ID:MSVC>:/Zc:__cplusplus> | ||||
| # Order build as UTF-8 in MSVC | ||||
| PRIVATE | ||||
|     $<$<CXX_COMPILER_ID:MSVC>:/utf-8> | ||||
| ) | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
| #include "StringHelper.hpp" | ||||
| #include "IOHelper.hpp" | ||||
| #include "EncodingHelper.hpp" | ||||
| #include "FsPathPatch.hpp" | ||||
| #include "StdPatch.hpp" | ||||
| #include <filesystem> | ||||
| #include <cstdarg> | ||||
| #include <cstdio> | ||||
| @ -459,8 +459,8 @@ namespace YYCC::ExceptionHelper { | ||||
| 			if (!YYCC::WinFctHelper::GetModuleFileName(NULL, u8_process_path)) | ||||
| 				return false; | ||||
| 			// extract file name from full path by std::filesystem::path | ||||
| 			std::filesystem::path process_path(FsPathPatch::FromUTF8Path(u8_process_path.c_str())); | ||||
| 			u8_process_name = FsPathPatch::ToUTF8Path(process_path.filename()); | ||||
| 			std::filesystem::path process_path(StdPatch::ToStdPath(u8_process_path.c_str())); | ||||
| 			u8_process_name = StdPatch::ToUTF8Path(process_path.filename()); | ||||
| 		} | ||||
| 		// then get process id | ||||
| 		DWORD process_id = GetCurrentProcessId(); | ||||
| @ -478,19 +478,19 @@ namespace YYCC::ExceptionHelper { | ||||
| 		if (!WinFctHelper::GetLocalAppData(u8_localappdata_path)) | ||||
| 			return false; | ||||
| 		// convert to std::filesystem::path | ||||
| 		std::filesystem::path crash_report_path(FsPathPatch::FromUTF8Path(u8_localappdata_path.c_str())); | ||||
| 		std::filesystem::path crash_report_path(StdPatch::ToStdPath(u8_localappdata_path.c_str())); | ||||
| 		// slash into crash report folder | ||||
| 		crash_report_path /= FsPathPatch::FromUTF8Path(YYCC_U8("CrashDumps")); | ||||
| 		crash_report_path /= StdPatch::ToStdPath(YYCC_U8("CrashDumps")); | ||||
| 		// use create function to make sure it is existing | ||||
| 		std::filesystem::create_directories(crash_report_path); | ||||
|  | ||||
| 		// build log path and coredump path | ||||
| 		// build std::filesystem::path first | ||||
| 		std::filesystem::path log_filepath = crash_report_path / FsPathPatch::FromUTF8Path(u8_log_filename.c_str()); | ||||
| 		std::filesystem::path coredump_filepath = crash_report_path / FsPathPatch::FromUTF8Path(u8_coredump_filename.c_str()); | ||||
| 		std::filesystem::path log_filepath = crash_report_path / StdPatch::ToStdPath(u8_log_filename.c_str()); | ||||
| 		std::filesystem::path coredump_filepath = crash_report_path / StdPatch::ToStdPath(u8_coredump_filename.c_str()); | ||||
| 		// output to result | ||||
| 		log_path = FsPathPatch::ToUTF8Path(log_filepath); | ||||
| 		coredump_path = FsPathPatch::ToUTF8Path(coredump_filepath); | ||||
| 		log_path = StdPatch::ToUTF8Path(log_filepath); | ||||
| 		coredump_path = StdPatch::ToUTF8Path(coredump_filepath); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| @ -1,29 +0,0 @@ | ||||
| #pragma once | ||||
| #include "YYCCInternal.hpp" | ||||
|  | ||||
| #include <filesystem> | ||||
|  | ||||
| /** | ||||
|  * @brief \c std::filesystem::path related patches for UTF8 compatibility | ||||
|  * @details | ||||
|  * See also \ref fs_path_patch. | ||||
| */ | ||||
| namespace YYCC::FsPathPatch { | ||||
| 	 | ||||
| 	/** | ||||
| 	 * @brief Constructs \c std::filesystem::path from UTF8 path. | ||||
| 	 * @param[in] u8_path UTF8 path string for building. | ||||
| 	 * @return \c std::filesystem::path instance. | ||||
| 	 * @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?). | ||||
| 	*/ | ||||
| 	std::filesystem::path FromUTF8Path(const yycc_char8_t* u8_path); | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Returns the UTF8 representation of given \c std::filesystem::path. | ||||
| 	 * @param[in] path The \c std::filesystem::path instance converting to UTF8 path. | ||||
| 	 * @return The UTF8 representation of given \c std::filesystem::path. | ||||
| 	 * @exception std::invalid_argument Fail to convert to UTF8 string. | ||||
| 	*/ | ||||
| 	yycc_u8string ToUTF8Path(const std::filesystem::path& path); | ||||
|  | ||||
| } | ||||
| @ -1,24 +1,24 @@ | ||||
| #include "FsPathPatch.hpp" | ||||
| #include "StdPatch.hpp" | ||||
| 
 | ||||
| #include "EncodingHelper.hpp" | ||||
| #include <string> | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| namespace YYCC::FsPathPatch { | ||||
| namespace YYCC::StdPatch { | ||||
| 
 | ||||
| 	std::filesystem::path FromUTF8Path(const yycc_char8_t* u8_path) { | ||||
| 	std::filesystem::path ToStdPath(const yycc_u8string_view& u8_path) { | ||||
| #if YYCC_OS == YYCC_OS_WINDOWS | ||||
| 
 | ||||
| 		// convert path to wchar
 | ||||
| 		std::wstring wpath; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(u8_path, wpath)) | ||||
| 			throw std::invalid_argument("Fail to convert given UTF8 string."); | ||||
| 
 | ||||
| 		// return path with wchar_t ctor
 | ||||
| 		return std::filesystem::path(wpath); | ||||
| 		 | ||||
| #else | ||||
| 		return std::filesystem::path(EncodingHelper::ToOrdinary(u8_path)); | ||||
| 		std::string cache = YYCC::EncodingHelper::ToOrdinary(u8_path); | ||||
| 		return std::filesystem::path(cache.c_str()); | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
							
								
								
									
										216
									
								
								src/StdPatch.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/StdPatch.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,216 @@ | ||||
| #pragma once | ||||
| #include "YYCCInternal.hpp" | ||||
|  | ||||
| #include <filesystem> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
|  | ||||
| /** | ||||
|  * @brief \c Standard library related patches for UTF8 compatibility and the limitation of C++ standard version. | ||||
|  * @details | ||||
|  * See also \ref std_patch. | ||||
| */ | ||||
| namespace YYCC::StdPatch { | ||||
| 	 | ||||
| 	/** | ||||
| 	 * @brief Constructs \c std::filesystem::path from UTF8 path. | ||||
| 	 * @param[in] u8_path UTF8 path string for building. | ||||
| 	 * @return \c std::filesystem::path instance. | ||||
| 	 * @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?). | ||||
| 	*/ | ||||
| 	std::filesystem::path ToStdPath(const yycc_u8string_view& u8_path); | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Returns the UTF8 representation of given \c std::filesystem::path. | ||||
| 	 * @param[in] path The \c std::filesystem::path instance converting to UTF8 path. | ||||
| 	 * @return The UTF8 representation of given \c std::filesystem::path. | ||||
| 	 * @exception std::invalid_argument Fail to convert to UTF8 string. | ||||
| 	*/ | ||||
| 	yycc_u8string ToUTF8Path(const std::filesystem::path& path); | ||||
|  | ||||
| #pragma region StartsWith EndsWith | ||||
|  | ||||
| 	// Reference: | ||||
| 	// https://en.cppreference.com/w/cpp/string/basic_string_view/starts_with | ||||
| 	// https://en.cppreference.com/w/cpp/string/basic_string_view/ends_with | ||||
| 	// https://en.cppreference.com/w/cpp/string/basic_string/starts_with | ||||
| 	// https://en.cppreference.com/w/cpp/string/basic_string/ends_with | ||||
| 	 | ||||
| #pragma region String View | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view begins with the given prefix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string_view<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept { | ||||
| 		return std::basic_string_view<CharT, Traits>(that.data(), std::min(that.size(), sv.size())) == sv; | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view begins with the given prefix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] ch A single character. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept { | ||||
| 		return !that.empty() && Traits::eq(that.front(), ch); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view begins with the given prefix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] s A null-terminated character string. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept { | ||||
| 		return StartsWith(that, std::basic_string_view(s)); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view ends with the given suffix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string_view<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept { | ||||
| 		return that.size() >= sv.size() && that.compare(that.size() - sv.size(), std::basic_string_view<CharT, Traits>::npos, sv); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view ends with the given suffix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] ch A single character. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string_view<CharT, Traits>& that, CharT ch) noexcept { | ||||
| 		return !that.empty() && Traits::eq(that.back(), ch); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string view ends with the given suffix | ||||
| 	 * @param[in] that The string view to find. | ||||
| 	 * @param[in] s A null-terminated character string. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string_view<CharT, Traits>& that, const CharT* s) noexcept { | ||||
| 		return EndsWith(that, std::basic_string_view(s)); | ||||
| 	} | ||||
| 	 | ||||
| #pragma endregion | ||||
|  | ||||
| #pragma region String | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Checks if the string begins with the given prefix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept { | ||||
| 		return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string begins with the given prefix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] ch A single character. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept { | ||||
| 		return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string begins with the given prefix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] s A null-terminated character string. | ||||
| 	 * @return True if the string view begins with the provided prefix, false otherwise. | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool StartsWith(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept { | ||||
| 		return StartsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * @brief Checks if the string ends with the given suffix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] sv A string view which may be a result of implicit conversion from \c std::basic_string. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string<CharT, Traits>& that, std::basic_string_view<CharT, Traits> sv) noexcept { | ||||
| 		return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), sv); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string ends with the given suffix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] ch A single character. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string<CharT, Traits>& that, CharT ch) noexcept { | ||||
| 		return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), ch); | ||||
| 	} | ||||
| 	/** | ||||
| 	 * @brief Checks if the string ends with the given suffix | ||||
| 	 * @param[in] that The string to find. | ||||
| 	 * @param[in] s A null-terminated character string. | ||||
| 	 * @return True if the string view ends with the provided suffix, false otherwise.  | ||||
| 	*/ | ||||
| 	template<class CharT, class Traits = std::char_traits<CharT>> | ||||
| 	bool EndsWith(const std::basic_string<CharT, Traits>& that, const CharT* s) noexcept { | ||||
| 		return EndsWith(std::basic_string_view<CharT, Traits>(that.data(), that.size()), s); | ||||
| 	} | ||||
| 	 | ||||
| #pragma endregion | ||||
|  | ||||
| #pragma endregion | ||||
|  | ||||
| #pragma region Contain | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Checks if there is an element with key equivalent to key in the container. | ||||
| 	 * @details  | ||||
| 	 * The polyfill to \c Contains function of unordered and ordered associative container. | ||||
| 	 * Because this function only present after C++ 20. | ||||
| 	 * This function will use our custom polyfill if the version of C++ standard you are using lower than C++ 20. | ||||
| 	 * Otherwise it will fallback to vanilla standard library function. | ||||
| 	 * @tparam _TContainer  | ||||
| 	 * The type of container. This container must have \c find() and \c end() member functions. | ||||
| 	 * @tparam _TKey  | ||||
| 	 * The type of key of container. | ||||
| 	 * If the container is a set, this type is the type of item in set. | ||||
| 	 * If the container is a map, this type is the key type of map. | ||||
| 	 * @param[in] container The reference to container to find. | ||||
| 	 * @param[in] key Key value of the element to search for  | ||||
| 	 * @return True if there is such an element, otherwise false. | ||||
| 	 * @remarks | ||||
| 	 * This template function do not have constraint check. | ||||
| 	 * If container type has \c find() and \c end() member functions, this template function will be created without any error. | ||||
| 	 * However, this function should be used for standard library associative container according to its original purpose. | ||||
| 	 * It means that the type of container usually and should be one of following types: | ||||
| 	 * \li \c std::set | ||||
| 	 * \li \c std::multiset | ||||
| 	 * \li \c std::map | ||||
| 	 * \li \c std::multimap | ||||
| 	 * \li \c std::unordered_set | ||||
| 	 * \li \c std::unordered_multiset | ||||
| 	 * \li \c std::unordered_map | ||||
| 	 * \li \c std::unordered_multimap | ||||
| 	*/ | ||||
| 	template<class _TContainer, class _TKey> | ||||
| 	bool Contains(const _TContainer& container, const _TKey& key) { | ||||
| #if __cplusplus < 202002L | ||||
| 		return container.find(key) != container.end(); | ||||
| #else | ||||
| 		return container.contains(key); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| #pragma endregion | ||||
|  | ||||
| } | ||||
| @ -9,7 +9,7 @@ namespace YYCC::WinFctHelper { | ||||
| 	HMODULE GetCurrentModule() { | ||||
| 		// Reference: https://stackoverflow.com/questions/557081/how-do-i-get-the-hmodule-for-the-currently-executing-code | ||||
| 		HMODULE hModule = NULL; | ||||
| 		GetModuleHandleExW( | ||||
| 		::GetModuleHandleExW( | ||||
| 			GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,	// get address and do not inc ref counter. | ||||
| 			(LPCWSTR)GetCurrentModule, | ||||
| 			&hModule); | ||||
| @ -24,7 +24,7 @@ namespace YYCC::WinFctHelper { | ||||
|  | ||||
| 		// fetch temp folder | ||||
| 		while (true) { | ||||
| 			if ((expected_size = GetTempPathW(static_cast<DWORD>(wpath.size()), wpath.data())) == 0) { | ||||
| 			if ((expected_size = ::GetTempPathW(static_cast<DWORD>(wpath.size()), wpath.data())) == 0) { | ||||
| 				// failed, set to empty | ||||
| 				return false; | ||||
| 			} | ||||
| @ -50,13 +50,13 @@ namespace YYCC::WinFctHelper { | ||||
| 		DWORD copied_size; | ||||
|  | ||||
| 		while (true) { | ||||
| 			if ((copied_size = GetModuleFileNameW(hModule, wpath.data(), static_cast<DWORD>(wpath.size()))) == 0) { | ||||
| 			if ((copied_size = ::GetModuleFileNameW(hModule, wpath.data(), static_cast<DWORD>(wpath.size()))) == 0) { | ||||
| 				// failed, return | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			// check insufficient buffer | ||||
| 			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { | ||||
| 			if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) { | ||||
| 				// buffer is not enough, enlarge it and try again. | ||||
| 				wpath.resize(wpath.size() + MAX_PATH); | ||||
| 			} else { | ||||
| @ -87,7 +87,27 @@ namespace YYCC::WinFctHelper { | ||||
|  | ||||
| 	bool IsValidCodePage(UINT code_page) { | ||||
| 		CPINFOEXW cpinfo; | ||||
| 		return GetCPInfoExW(code_page, 0, &cpinfo); | ||||
| 		return ::GetCPInfoExW(code_page, 0, &cpinfo); | ||||
| 	} | ||||
|  | ||||
| 	BOOL CopyFile(const yycc_u8string_view& lpExistingFileName, const yycc_u8string_view& lpNewFileName, BOOL bFailIfExists) { | ||||
| 		std::wstring wExistingFileName, wNewFileName; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(lpExistingFileName, wExistingFileName)) return FALSE; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(lpNewFileName, wNewFileName)) return FALSE; | ||||
| 		return ::CopyFileW(wExistingFileName.c_str(), wNewFileName.c_str(), bFailIfExists); | ||||
| 	} | ||||
|  | ||||
| 	BOOL MoveFile(const yycc_u8string_view& lpExistingFileName, const yycc_u8string_view& lpNewFileName) { | ||||
| 		std::wstring wExistingFileName, wNewFileName; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(lpExistingFileName, wExistingFileName)) return FALSE; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(lpNewFileName, wNewFileName)) return FALSE; | ||||
| 		return ::MoveFileW(wExistingFileName.c_str(), wNewFileName.c_str()); | ||||
| 	} | ||||
|  | ||||
| 	BOOL DeleteFile(const yycc_u8string_view& lpFileName) { | ||||
| 		std::wstring wFileName; | ||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(lpFileName, wFileName)) return FALSE; | ||||
| 		return ::DeleteFileW(wFileName.c_str()); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -64,6 +64,43 @@ namespace YYCC::WinFctHelper { | ||||
| 	*/ | ||||
| 	bool IsValidCodePage(UINT code_page); | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Copies an existing file to a new file. | ||||
| 	 * @param lpExistingFileName The name of an existing file. | ||||
| 	 * @param lpNewFileName The name of the new file. | ||||
| 	 * @param bFailIfExists  | ||||
| 	 * If this parameter is TRUE and the new file specified by \c lpNewFileName already exists, the function fails. | ||||
| 	 * If this parameter is FALSE and the new file already exists, the function overwrites the existing file and succeeds. | ||||
| 	 * @return  | ||||
| 	 * If the function succeeds, the return value is nonzero. | ||||
| 	 * If the function fails, the return value is zero. To get extended error information, call \c GetLastError. | ||||
| 	 * @remarks Same as Windows \c CopyFile: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-copyfilew | ||||
| 	*/ | ||||
| 	BOOL CopyFile(const yycc_u8string_view& lpExistingFileName, const yycc_u8string_view& lpNewFileName, BOOL bFailIfExists); | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Moves an existing file or a directory, including its children. | ||||
| 	 * @param lpExistingFileName The current name of the file or directory on the local computer. | ||||
| 	 * @param lpNewFileName  | ||||
| 	 * The new name for the file or directory. The new name must not already exist. | ||||
| 	 * A new file may be on a different file system or drive. A new directory must be on the same drive. | ||||
| 	 * @return  | ||||
| 	 * If the function succeeds, the return value is nonzero. | ||||
| 	 * If the function fails, the return value is zero. To get extended error information, call \c GetLastError. | ||||
| 	 * @remarks Same as Windows \c MoveFile: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefilew | ||||
| 	*/ | ||||
| 	BOOL MoveFile(const yycc_u8string_view& lpExistingFileName, const yycc_u8string_view& lpNewFileName); | ||||
|  | ||||
| 	/** | ||||
| 	 * @brief Deletes an existing file. | ||||
| 	 * @param lpFileName The name of the file to be deleted. | ||||
| 	 * @return  | ||||
| 	 * If the function succeeds, the return value is nonzero. | ||||
| 	 * If the function fails, the return value is zero. To get extended error information, call \c GetLastError. | ||||
| 	 * @remarks Same as Windows \c DeleteFile: https://learn.microsoft.com/e-us/windows/win32/api/winbase/nf-winbase-deletefile | ||||
| 	*/ | ||||
| 	BOOL DeleteFile(const yycc_u8string_view& lpFileName); | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -16,5 +16,8 @@ | ||||
| #undef LoadImage | ||||
| #undef GetTempPath | ||||
| #undef GetModuleFileName | ||||
| #undef CopyFile | ||||
| #undef MoveFile | ||||
| #undef DeleteFile | ||||
|  | ||||
| #endif | ||||
| @ -10,7 +10,7 @@ | ||||
| #include "ParserHelper.hpp" | ||||
| #include "IOHelper.hpp" | ||||
| #include "WinFctHelper.hpp" | ||||
| #include "FsPathPatch.hpp" | ||||
| #include "StdPatch.hpp" | ||||
| #include "ExceptionHelper.hpp" | ||||
|  | ||||
| #include "ConfigManager.hpp" | ||||
|  | ||||
| @ -394,13 +394,13 @@ namespace YYCCTestbench { | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	static void FsPathPatch() { | ||||
| 	static void StdPatch() { | ||||
|  | ||||
| 		std::filesystem::path test_path; | ||||
| 		for (const auto& strl : c_UTF8TestStrTable) { | ||||
| 			test_path /= YYCC::FsPathPatch::FromUTF8Path(strl.c_str()); | ||||
| 			test_path /= YYCC::StdPatch::ToStdPath(strl.c_str()); | ||||
| 	} | ||||
| 		YYCC::yycc_u8string test_slashed_path(YYCC::FsPathPatch::ToUTF8Path(test_path)); | ||||
| 		YYCC::yycc_u8string test_slashed_path(YYCC::StdPatch::ToUTF8Path(test_path)); | ||||
|  | ||||
| #if YYCC_OS == YYCC_OS_WINDOWS | ||||
| 		std::wstring wdecilmer(1u, std::filesystem::path::preferred_separator); | ||||
| @ -410,7 +410,7 @@ namespace YYCCTestbench { | ||||
| #endif | ||||
| 		YYCC::yycc_u8string test_joined_path(YYCC::StringHelper::Join(c_UTF8TestStrTable, decilmer.c_str())); | ||||
|  | ||||
| 		Assert(test_slashed_path == test_joined_path, YYCC_U8("YYCC::FsPathPatch")); | ||||
| 		Assert(test_slashed_path == test_joined_path, YYCC_U8("YYCC::StdPatch")); | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -630,7 +630,7 @@ int main(int argc, char* argv[]) { | ||||
| 	YYCCTestbench::StringTestbench(); | ||||
| 	YYCCTestbench::ParserTestbench(); | ||||
| 	YYCCTestbench::WinFctTestbench(); | ||||
| 	YYCCTestbench::FsPathPatch(); | ||||
| 	YYCCTestbench::StdPatch(); | ||||
| 	// advanced | ||||
| 	YYCCTestbench::ConfigManagerTestbench(); | ||||
| 	YYCCTestbench::ArgParserTestbench(argc, argv); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user