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
|
||||
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -103,9 +103,6 @@ namespace YYCC::ConfigManager {
|
|||
void Reset();
|
||||
|
||||
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;
|
||||
uint64_t m_VersionIdentifier;
|
||||
std::map<yycc_u8string, AbstractSetting*> m_Settings;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#if YYCC_OS == YYCC_OS_WINDOWS
|
||||
#include "WinImportPrefix.hpp"
|
||||
|
@ -14,7 +15,7 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -28,6 +28,19 @@ namespace YYCC::IOHelper {
|
|||
#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<std::FILE, StdFileDeleter>;
|
||||
|
||||
/**
|
||||
* @brief The UTF8 version of \c std::fopen.
|
||||
* @param[in] u8_filepath The UTF8 encoded path to the file to be opened.
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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) { \
|
||||
|
|
Loading…
Reference in New Issue
Block a user