feat: add smart FILE pointer.
- use std::unique_ptr and custom deleter to implement smart FILE pointer for convenient auto free.
This commit is contained in:
parent
0ac6b477f9
commit
6da990876e
|
@ -3,7 +3,7 @@ namespace YYCC::IOHelper {
|
||||||
|
|
||||||
\page io_helper IO Helper
|
\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
|
\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.
|
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
|
\section io_helper__utf8_fopen UTF8 fopen
|
||||||
|
|
||||||
In Windows, standard \c std::fopen can not handle UTF8 file name in common environment.
|
In Windows, standard \c std::fopen can not handle UTF8 file name in common environment.
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace YYCC::ConfigManager {
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
// get file handle
|
// 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 (fs.get() == nullptr) {
|
||||||
// if we fail to get, it means that we do not have corresponding cfg file.
|
// if we fail to get, it means that we do not have corresponding cfg file.
|
||||||
// all settings should be reset to default value.
|
// all settings should be reset to default value.
|
||||||
|
@ -112,7 +112,7 @@ namespace YYCC::ConfigManager {
|
||||||
|
|
||||||
bool CoreManager::Save() {
|
bool CoreManager::Save() {
|
||||||
// get file handle
|
// 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 we fail to get, return false.
|
||||||
if (fs == nullptr) 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
|
#pragma endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,9 +103,6 @@ namespace YYCC::ConfigManager {
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using FileHandleGuard_t = std::unique_ptr<FILE, std::function<void(FILE*)>>;
|
|
||||||
FileHandleGuard_t GetFileHandle(const yycc_char8_t* mode) const;
|
|
||||||
|
|
||||||
yycc_u8string m_CfgFilePath;
|
yycc_u8string m_CfgFilePath;
|
||||||
uint64_t m_VersionIdentifier;
|
uint64_t m_VersionIdentifier;
|
||||||
std::map<yycc_u8string, AbstractSetting*> m_Settings;
|
std::map<yycc_u8string, AbstractSetting*> m_Settings;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||||
#include "WinImportPrefix.hpp"
|
#include "WinImportPrefix.hpp"
|
||||||
|
@ -13,8 +14,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace YYCC::IOHelper {
|
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
|
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||||
|
|
||||||
// convert mode and file path to wchar
|
// convert mode and file path to wchar
|
||||||
|
|
|
@ -27,6 +27,19 @@ namespace YYCC::IOHelper {
|
||||||
#else
|
#else
|
||||||
#error "Not supported pointer size."
|
#error "Not supported pointer size."
|
||||||
#endif
|
#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<std::FILE, StdFileDeleter>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The UTF8 version of \c std::fopen.
|
* @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.
|
* 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.
|
* @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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,8 +457,8 @@ namespace YYCCTestbench {
|
||||||
TestConfigManager test;
|
TestConfigManager test;
|
||||||
|
|
||||||
// test constraint works
|
// test constraint works
|
||||||
Assert(!test.m_ClampedFloatSetting.Set(2.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::ConfigManager::Constraint"));
|
Assert(test.m_ClampedFloatSetting.Get() == 0.0f, YYCC_U8("YYCC::Constraints::Constraint"));
|
||||||
|
|
||||||
// test modify settings
|
// test modify settings
|
||||||
#define TEST_MACRO(member_name, set_val) { \
|
#define TEST_MACRO(member_name, set_val) { \
|
||||||
|
|
Loading…
Reference in New Issue
Block a user