From 6da990876e9783e0db447c43ce10742cd3a9047c Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 2 Aug 2024 09:50:15 +0800 Subject: [PATCH] feat: add smart FILE pointer. - use std::unique_ptr and custom deleter to implement smart FILE pointer for convenient auto free. --- doc/src/io_helper.dox | 7 ++++++- src/ConfigManager.cpp | 13 ++----------- src/ConfigManager.hpp | 3 --- src/IOHelper.cpp | 5 +++-- src/IOHelper.hpp | 15 ++++++++++++++- testbench/main.cpp | 4 ++-- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/doc/src/io_helper.dox b/doc/src/io_helper.dox index 02d72b5..806e2e8 100644 --- a/doc/src/io_helper.dox +++ b/doc/src/io_helper.dox @@ -3,7 +3,7 @@ namespace YYCC::IOHelper { \page io_helper IO Helper -YYCC::IOHelper currently only has one function and one macro. +Actually, YYCC::IOHelper includes functions which can not be placed in other place. \section io_helper__ptr_pri_padding Pointer Print Padding @@ -25,6 +25,11 @@ std::printf(stdout, "Raw Pointer 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR, raw_ptr); Note \c PRIXPTR is defined by standard library for formatting pointer as hexadecimal style. +\section io_helper__smart_file Smart FILE Pointer + +#SmartStdFile use \c std::unique_ptr with custom deleter to implement smart \c FILE*. +It is useful in the cases that you want to automatically free opened file when leaving corresponding scope. + \section io_helper__utf8_fopen UTF8 fopen In Windows, standard \c std::fopen can not handle UTF8 file name in common environment. diff --git a/src/ConfigManager.cpp b/src/ConfigManager.cpp index 51f26cb..407285c 100644 --- a/src/ConfigManager.cpp +++ b/src/ConfigManager.cpp @@ -49,7 +49,7 @@ namespace YYCC::ConfigManager { Reset(); // get file handle - auto fs = this->GetFileHandle(YYCC_U8("rb")); + IOHelper::SmartStdFile fs(IOHelper::UTF8FOpen(m_CfgFilePath.c_str(), YYCC_U8("rb"))); if (fs.get() == nullptr) { // if we fail to get, it means that we do not have corresponding cfg file. // all settings should be reset to default value. @@ -112,7 +112,7 @@ namespace YYCC::ConfigManager { bool CoreManager::Save() { // get file handle - auto fs = this->GetFileHandle(YYCC_U8("wb")); + IOHelper::SmartStdFile fs(IOHelper::UTF8FOpen(m_CfgFilePath.c_str(), YYCC_U8("wb"))); // if we fail to get, return false. if (fs == nullptr) return false; @@ -157,15 +157,6 @@ namespace YYCC::ConfigManager { } } - CoreManager::FileHandleGuard_t CoreManager::GetFileHandle(const yycc_char8_t* mode) const { - return CoreManager::FileHandleGuard_t( - IOHelper::UTF8FOpen(this->m_CfgFilePath.c_str(), mode), - [](FILE* fs) -> void { - if (fs != nullptr) std::fclose(fs); - } - ); - } - #pragma endregion } diff --git a/src/ConfigManager.hpp b/src/ConfigManager.hpp index cb5d1c4..b5664a9 100644 --- a/src/ConfigManager.hpp +++ b/src/ConfigManager.hpp @@ -103,9 +103,6 @@ namespace YYCC::ConfigManager { void Reset(); private: - using FileHandleGuard_t = std::unique_ptr>; - FileHandleGuard_t GetFileHandle(const yycc_char8_t* mode) const; - yycc_u8string m_CfgFilePath; uint64_t m_VersionIdentifier; std::map m_Settings; diff --git a/src/IOHelper.cpp b/src/IOHelper.cpp index 5c91672..008645e 100644 --- a/src/IOHelper.cpp +++ b/src/IOHelper.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #if YYCC_OS == YYCC_OS_WINDOWS #include "WinImportPrefix.hpp" @@ -13,8 +14,8 @@ #endif namespace YYCC::IOHelper { - - FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode) { + + std::FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode) { #if YYCC_OS == YYCC_OS_WINDOWS // convert mode and file path to wchar diff --git a/src/IOHelper.hpp b/src/IOHelper.hpp index a6ef75e..34a78fd 100644 --- a/src/IOHelper.hpp +++ b/src/IOHelper.hpp @@ -27,6 +27,19 @@ namespace YYCC::IOHelper { #else #error "Not supported pointer size." #endif + + /// @brief C++ standard deleter for std::FILE* + class StdFileDeleter { + public: + StdFileDeleter() {} + void operator() (std::FILE* ptr) { + if (ptr != nullptr) { + std::fclose(ptr); + } + } + }; + /// @brief Smart unique pointer of \c std::FILE* + using SmartStdFile = std::unique_ptr; /** * @brief The UTF8 version of \c std::fopen. @@ -37,6 +50,6 @@ namespace YYCC::IOHelper { * On other platforms, this function will delegate request directly to std::fopen. * @return \c FILE* of the file to be opened, or nullptr if failed. */ - FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode); + std::FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode); } diff --git a/testbench/main.cpp b/testbench/main.cpp index 878e914..c5439c9 100644 --- a/testbench/main.cpp +++ b/testbench/main.cpp @@ -457,8 +457,8 @@ namespace YYCCTestbench { TestConfigManager test; // test constraint works - Assert(!test.m_ClampedFloatSetting.Set(2.0f), YYCC_U8("YYCC::ConfigManager::Constraint")); - Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::ConfigManager::Constraint")); + Assert(!test.m_ClampedFloatSetting.Set(2.0f), YYCC_U8("YYCC::Constraints::Constraint")); + Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::Constraints::Constraint")); // test modify settings #define TEST_MACRO(member_name, set_val) { \