feat: update IO helper.
- add utf8 path to std::filesystem::path convertion function. - add left-padding zero format string for printing pointer. - update exception handler, but not finished because console helper need update.
This commit is contained in:
		| @ -1,11 +1,11 @@ | |||||||
| #include "ExceptionHelper.hpp" | #include "ExceptionHelper.hpp" | ||||||
| #if YYCC_OS == YYCC_OS_WINDOWS | #if YYCC_OS == YYCC_OS_WINDOWS | ||||||
|  |  | ||||||
|  | #include "WinFctHelper.hpp" | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <cstdarg> | #include <cstdarg> | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <cinttypes> | #include <cinttypes> | ||||||
| #include "WinFctHelper.hpp" |  | ||||||
|  |  | ||||||
| #include "WinImportPrefix.hpp" | #include "WinImportPrefix.hpp" | ||||||
| #include <Windows.h> | #include <Windows.h> | ||||||
| @ -96,7 +96,7 @@ namespace YYCC::ExceptionHelper { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static void UExceptionFormat(std::FILE* fs, const char* fmt, ...) { | 	static void UExceptionBacktraceFormatLine(std::FILE* fs, const char* fmt, ...) { | ||||||
| 		// write to file | 		// write to file | ||||||
| 		va_list arg1; | 		va_list arg1; | ||||||
| 		va_start(arg1, fmt); | 		va_start(arg1, fmt); | ||||||
| @ -109,7 +109,7 @@ namespace YYCC::ExceptionHelper { | |||||||
| 		va_end(arg2); | 		va_end(arg2); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static void UExceptionPrint(std::FILE* fs, const char* strl) { | 	static void UExceptionBacktraceWriteLine(std::FILE* fs, const char* strl) { | ||||||
| 		// write to file | 		// write to file | ||||||
| 		std::fputs(strl, fs); | 		std::fputs(strl, fs); | ||||||
| 		// write to stdout | 		// write to stdout | ||||||
| @ -127,7 +127,7 @@ namespace YYCC::ExceptionHelper { | |||||||
| 		// init symbol | 		// init symbol | ||||||
| 		if (!SymInitialize(process, 0, TRUE)) { | 		if (!SymInitialize(process, 0, TRUE)) { | ||||||
| 			// fail to load. return | 			// fail to load. return | ||||||
| 			UExceptionPrint(fs, "Lost symbol file!\n"); | 			UExceptionBacktraceWriteLine(fs, "Lost symbol file!\n"); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -182,7 +182,7 @@ namespace YYCC::ExceptionHelper { | |||||||
| 			// depth breaker | 			// depth breaker | ||||||
| 			--maxdepth; | 			--maxdepth; | ||||||
| 			if (maxdepth < 0) { | 			if (maxdepth < 0) { | ||||||
| 				UExceptionPrint(fs, "...\n");		// indicate there are some frames not listed | 				UExceptionBacktraceWriteLine(fs, "...\n");		// indicate there are some frames not listed | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @ -205,7 +205,7 @@ namespace YYCC::ExceptionHelper { | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// write to file | 			// write to file | ||||||
| 			UExceptionFormat(fs, "0x%016llx(rel: 0x%016llx)[%s]\t%s#%llu\n", | 			UExceptionBacktraceFormatLine(fs, "0x%016llx(rel: 0x%016llx)[%s]\t%s#%llu\n", | ||||||
| 				frame.AddrPC.Offset, frame.AddrPC.Offset - module_base, module_name, | 				frame.AddrPC.Offset, frame.AddrPC.Offset - module_base, module_name, | ||||||
| 				source_file, source_file_line | 				source_file, source_file_line | ||||||
| 			); | 			); | ||||||
| @ -218,6 +218,10 @@ namespace YYCC::ExceptionHelper { | |||||||
| 		SymCleanup(process); | 		SymCleanup(process); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static void UExceptionErrorLog(const std::wstring& filename, LPEXCEPTION_POINTERS info) { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	static void UExceptionCoreDump(LPCWSTR filename, LPEXCEPTION_POINTERS info) { | 	static void UExceptionCoreDump(LPCWSTR filename, LPEXCEPTION_POINTERS info) { | ||||||
| 		// open file and write | 		// open file and write | ||||||
| 		HANDLE hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 		HANDLE hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||||||
| @ -236,11 +240,13 @@ namespace YYCC::ExceptionHelper { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static void UExceptionFetchRecordPath(std::wstring& log_path, std::wstring& coredump_path) { | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	static LONG WINAPI UExceptionImpl(LPEXCEPTION_POINTERS info) { | 	static LONG WINAPI UExceptionImpl(LPEXCEPTION_POINTERS info) { | ||||||
| 		// detect loop calling | 		// detect loop calling | ||||||
| 		if (g_IsProcessing) { | 		if (g_IsProcessing) goto end_proc; | ||||||
| 			goto end_proc; |  | ||||||
| 		} |  | ||||||
| 		// start process | 		// start process | ||||||
| 		g_IsProcessing = true; | 		g_IsProcessing = true; | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,25 +1,22 @@ | |||||||
| #include "IOHelper.hpp" | #include "IOHelper.hpp" | ||||||
| #if YYCC_OS == YYCC_OS_WINDOWS |  | ||||||
|  |  | ||||||
| #include "EncodingHelper.hpp" | #include "EncodingHelper.hpp" | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <stdexcept> | ||||||
|  |  | ||||||
|  | #if YYCC_OS == YYCC_OS_WINDOWS | ||||||
| #include "WinImportPrefix.hpp" | #include "WinImportPrefix.hpp" | ||||||
| #include <Windows.h> | #include <Windows.h> | ||||||
| #include <io.h> |  | ||||||
| #include <fcntl.h> |  | ||||||
| #include "WinImportSuffix.hpp" | #include "WinImportSuffix.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| namespace YYCC::IOHelper { | namespace YYCC::IOHelper { | ||||||
|  |  | ||||||
| 	bool futf8(FILE* fs) { | 	FILE* UTF8FOpen(const char* u8_filepath, const char* u8_mode) { | ||||||
| 		// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode?view=msvc-170 | #if YYCC_OS == YYCC_OS_WINDOWS | ||||||
| 		return _setmode(_fileno(fs), _O_U8TEXT) != -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	FILE* fopen(const char* u8_filepath, const char* u8_mode) { |  | ||||||
| 		// convert mode and file path to wchar | 		// convert mode and file path to wchar | ||||||
| 		std::wstring wmode, wpath; | 		std::wstring wmode, wpath; | ||||||
| 		if (!YYCC::EncodingHelper::UTF8ToWchar(u8_mode, wmode)) | 		if (!YYCC::EncodingHelper::UTF8ToWchar(u8_mode, wmode)) | ||||||
| @ -29,8 +26,28 @@ namespace YYCC::IOHelper { | |||||||
|  |  | ||||||
| 		// call microsoft specified fopen which support wchar as argument. | 		// call microsoft specified fopen which support wchar as argument. | ||||||
| 		return _wfopen(wpath.c_str(), wmode.c_str()); | 		return _wfopen(wpath.c_str(), wmode.c_str()); | ||||||
|  |  | ||||||
|  | #else | ||||||
|  | 		return std::fopen(u8_filepath, u8_mode); | ||||||
|  | #endif | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	std::filesystem::path UTF8Path(const char* 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."); | ||||||
|  |  | ||||||
|  | 		// call microsoft specified fopen which support wchar as argument. | ||||||
|  | 		return std::filesystem::path(wpath); | ||||||
|  |  | ||||||
|  | #else | ||||||
|  | 		return std::filesystem::path(u8_path); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif |  | ||||||
|  | |||||||
| @ -1,23 +1,48 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "YYCCInternal.hpp" | #include "YYCCInternal.hpp" | ||||||
| #if YYCC_OS == YYCC_OS_WINDOWS |  | ||||||
|  |  | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
|  | #include <filesystem> | ||||||
|  |  | ||||||
| namespace YYCC::IOHelper { | namespace YYCC::IOHelper { | ||||||
| 	 | 	 | ||||||
|  | #if UINTPTR_MAX == UINT32_MAX | ||||||
|  | #define PRI_XPTR_LEFT_PADDING "08" | ||||||
|  | #elif UINTPTR_MAX == UINT64_MAX | ||||||
| 	/** | 	/** | ||||||
| 	 * @brief Set given FILE* as UTF8 mode. | 	 * @brief The left-padding zero format string of HEX-printed pointer type. | ||||||
| 	 * @param fs[in] The FILE* need to be set as UTF8 mode. | 	 * @details | ||||||
| 	 * @return True if success, otherwise false. | 	 * When printing a pointer with HEX style, we always hope it can be left-padded with some zero for easy reading. | ||||||
| 	 * @warning Once this function success, you can not use any narrow char function on this FILE*, | 	 * In different architecture, the size of this padding is differnet too so we create this macro. | ||||||
| 	 * such as std::fputs, std::fprintf and etc. You only can use wide char function on it, | 	 * \n | ||||||
| 	 * or use the functions provided in this namespace by providing UTF8 string as their argument. | 	 * In 32-bit environment, it will be "08" meaning left pad zero until 8 number position. | ||||||
|  | 	 * In 64-bit environment, it will be "016" meaning left pad zero until 16 number position. | ||||||
| 	*/ | 	*/ | ||||||
| 	bool futf8(FILE* fs); | #define PRI_XPTR_LEFT_PADDING "016" | ||||||
|  | #else | ||||||
|  | #error "Not supported pointer size." | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	FILE* fopen(const char* u8_filepath, const char* u8_mode); | 	/** | ||||||
|  | 	 * @brief The UTF8 version of std::fopen. | ||||||
|  | 	 * @param u8_filepath[in] The UTF8 encoded path to the file to be opened. | ||||||
|  | 	 * @param u8_mode[in] UTF8 encoded mode string of the file to be opened. | ||||||
|  | 	 * @remarks | ||||||
|  | 	 * This function is suit for Windows because std::fopen do not support UTF8 on Windows. | ||||||
|  | 	 * On other platforms, this function will delegate request directly to std::fopen. | ||||||
|  | 	 * @return FILE* of the file to be opened, or nullptr if failed. | ||||||
|  | 	*/ | ||||||
|  | 	FILE* UTF8FOpen(const char* u8_filepath, const char* u8_mode); | ||||||
|  | 	 | ||||||
|  | 	/** | ||||||
|  | 	 * @brief Build std::filesystem::path from UTF8 string. | ||||||
|  | 	 * @param u8_path[in] UTF8 path string for building this std::filesystem::path. | ||||||
|  | 	 * @return std::filesystem::path instance. | ||||||
|  | 	 * @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?). | ||||||
|  | 	 * @remarks | ||||||
|  | 	 * This function is suit for Windows. | ||||||
|  | 	 * On other platforms, it will simply call the constructor of std::filesystem::path. | ||||||
|  | 	*/ | ||||||
|  | 	std::filesystem::path UTF8Path(const char* u8_path); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif |  | ||||||
|  | |||||||
| @ -216,7 +216,7 @@ namespace YYCCTestbench { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static void WinFctTestbench() { | 	static void WinFctTestbench() { | ||||||
| 		Console::WriteLine("Current Module HANDLE: 0x%016" PRIXPTR, YYCC::WinFctHelper::GetCurrentModule()); | 		Console::WriteLine("Current Module HANDLE: 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR, YYCC::WinFctHelper::GetCurrentModule()); | ||||||
| 		Console::WriteLine("Temp Directory: %s", YYCC::WinFctHelper::GetTempDirectory().c_str()); | 		Console::WriteLine("Temp Directory: %s", YYCC::WinFctHelper::GetTempDirectory().c_str()); | ||||||
| 		Console::WriteLine("Current Module Name: %s", YYCC::WinFctHelper::GetModuleName(YYCC::WinFctHelper::GetCurrentModule()).c_str()); | 		Console::WriteLine("Current Module Name: %s", YYCC::WinFctHelper::GetModuleName(YYCC::WinFctHelper::GetCurrentModule()).c_str()); | ||||||
| 	} | 	} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user