From 39b2d8c7c9bb254bdd5d1fdffa338553e0236c03 Mon Sep 17 00:00:00 2001 From: CrepHidery Date: Sat, 30 May 2026 13:01:09 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20EnhancedFile=E6=B5=81=E5=BC=8F?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/file_io.cpp | 557 +++++++++++++++++++++++++++++++++++++++++++---- core/file_io.h | 198 ++++++++++++++++- 2 files changed, 708 insertions(+), 47 deletions(-) diff --git a/core/file_io.cpp b/core/file_io.cpp index 3aade15..245b01c 100644 --- a/core/file_io.cpp +++ b/core/file_io.cpp @@ -2,78 +2,80 @@ #include "../common.h" #include #include +#include +#include +#include #ifdef _WIN32 #include #endif +// 原有的 xfopen 函数实现 FILE* xfopen(const char* fn, const char* mode) { #ifdef _WIN32 - // Windows下处理中文路径:UTF-8 -> UTF-16 -> _wfopen FILE* file = nullptr; - // 计算需要的宽字符缓冲区大小 int wpath_len = MultiByteToWideChar(CP_UTF8, 0, fn, -1, nullptr, 0); int wmode_len = MultiByteToWideChar(CP_UTF8, 0, mode, -1, nullptr, 0); if (wpath_len <= 0 || wmode_len <= 0) { - return nullptr; // 转换失败 + return nullptr; } - // 分配宽字符缓冲区 wchar_t* wpath = (wchar_t*)malloc(wpath_len * sizeof(wchar_t)); wchar_t* wmode = (wchar_t*)malloc(wmode_len * sizeof(wchar_t)); if (wpath && wmode) { - // 转换UTF-8到UTF-16 MultiByteToWideChar(CP_UTF8, 0, fn, -1, wpath, wpath_len); MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, wmode_len); - - // 使用宽字符版本打开文件 file = _wfopen(wpath, wmode); } - // 释放内存 free(wpath); free(wmode); return file; #else - // Linux/macOS等系统直接使用fopen,因为这些系统默认使用UTF-8 return fopen(fn, mode); #endif } +// 原有的 my_fopen 函数实现 +extern char savepath[]; + FILE *my_fopen(const char *fn, const char *mode) { - if (savepath[0]) { - size_t fn_len = strlen(fn); + extern char savepath[]; + if (savepath[0]) { + size_t fn_len = strlen(fn); size_t path_len = strlen(savepath); - char* fix_fn = NEWN char[path_len + fn_len + 2]; // +2 for '/' and '\0' + char* fix_fn = new char[path_len + fn_len + 2]; if (!fix_fn) return nullptr; - char* ch; - if ((ch = const_cast(strrchr(fn, '/')))) snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, ch + 1); - else if ((ch = const_cast(strrchr(fn, '\\')))) snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, ch + 1); - else snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, fn); - FILE* fe = fopen(fix_fn, mode); - delete[] fix_fn; - return fe; - } - else return fopen(fn, mode); -} - -// SavePath 拼接版 + char* ch; + if ((ch = const_cast(strrchr(fn, '/')))) + snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, ch + 1); + else if ((ch = const_cast(strrchr(fn, '\\')))) + snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, ch + 1); + else + snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, fn); + FILE* fe = fopen(fix_fn, mode); + delete[] fix_fn; + return fe; + } + else return fopen(fn, mode); +} + +// 原有的 my_xfopen 函数实现 FILE* my_xfopen(const char* fn, const char* mode) { + extern char savepath[]; FILE* file = nullptr; char* fix_fn = nullptr; if (savepath[0]) { - // 分配内存 size_t fn_len = strlen(fn); size_t path_len = strlen(savepath); fix_fn = (char*)malloc(path_len + fn_len + 2); if (!fix_fn) return nullptr; - // 查找文件名部分 const char* filename_part; const char* ch; @@ -84,20 +86,18 @@ FILE* my_xfopen(const char* fn, const char* mode) { else filename_part = fn; - // 拼接路径(使用snprintf更安全) snprintf(fix_fn, path_len + fn_len + 2, "%s/%s", savepath, filename_part); } - // 确定要打开的文件路径 const char* path_to_open = fix_fn ? fix_fn : fn; #ifdef _WIN32 - // Windows下使用宽字符版本处理中文路径 int wpath_len = MultiByteToWideChar(CP_UTF8, 0, path_to_open, -1, nullptr, 0); int wmode_len = MultiByteToWideChar(CP_UTF8, 0, mode, -1, nullptr, 0); - - if (wpath_len <= 0 || wmode_len <= 0) { - return nullptr; // 转换失败 + + if (wpath_len <= 0 || wmode_len <= 0) { + if (fix_fn) free(fix_fn); + return nullptr; } wchar_t* wpath = (wchar_t*)malloc(wpath_len * sizeof(wchar_t)); @@ -111,39 +111,504 @@ FILE* my_xfopen(const char* fn, const char* mode) { free(wpath); free(wmode); } else { - // 内存分配失败时的处理 if (wpath) free(wpath); if (wmode) free(wmode); } #else - // Linux/Mac等系统直接使用fopen file = fopen(path_to_open, mode); #endif - // 释放临时路径内存 - if (fix_fn) { - free(fix_fn); - } - + if (fix_fn) free(fix_fn); return file; } +// 原有的函数实现 FILE* oxfopen(const char* fn, const char* mode) { - FILE* file = xfopen(fn, mode); - if(file == nullptr) file = fopen(fn, mode); // fallback - return file; + FILE* file = xfopen(fn, mode); + if(file == nullptr) file = fopen(fn, mode); + return file; } + FILE* my_oxfopen(const char* fn, const char* mode) { - FILE* file = my_xfopen(fn, mode); - if(file == nullptr) file = my_fopen(fn, mode); // fallback - return file; + FILE* file = my_xfopen(fn, mode); + if(file == nullptr) file = my_fopen(fn, mode); + return file; } -// RAII 式 UniqueFile oxfopen_unique(const char* fn, const char* mode) { return UniqueFile(oxfopen(fn, mode)); } UniqueFile my_oxfopen_unique(const char* fn, const char* mode) { return UniqueFile(my_oxfopen(fn, mode)); +} + +// EnhancedFile 实现 +EnhancedFile::EnhancedFile(FILE* f) noexcept : file(f) {} + +EnhancedFile::EnhancedFile(UniqueFile&& f) noexcept : file(std::move(f)) {} + +EnhancedFile::operator bool() const noexcept { + return file != nullptr; +} + +bool EnhancedFile::operator!() const noexcept { + return file == nullptr; +} + +EnhancedFile::operator FILE*() const noexcept { + return file.get(); +} + +FILE* EnhancedFile::operator->() const noexcept { + return file.get(); +} + +FILE& EnhancedFile::operator*() const noexcept { + return *file.get(); +} + +FILE* EnhancedFile::get() const noexcept { + return file.get(); +} + +UniqueFile EnhancedFile::release() noexcept { + return std::move(file); +} + +void EnhancedFile::reset(FILE* f) noexcept { + file.reset(f); +} + +void EnhancedFile::close() noexcept { + file.reset(); +} + +bool EnhancedFile::flush() noexcept { + if (file) return fflush(file.get()) == 0; + return false; +} + +long EnhancedFile::tell() const noexcept { + if (file) return ftell(file.get()); + return -1L; +} + +bool EnhancedFile::seek(long offset, int origin) noexcept { + if (file) return fseek(file.get(), offset, origin) == 0; + return false; +} + +bool EnhancedFile::eof() const noexcept { + if (file) return feof(file.get()) != 0; + return true; +} + +bool EnhancedFile::error() const noexcept { + if (file) return ferror(file.get()) != 0; + return true; +} + +void EnhancedFile::clearerr() noexcept { + if (file) ::clearerr(file.get()); +} + +size_t EnhancedFile::write(const void* buffer, size_t size, size_t count) noexcept { + if (file) return fwrite(buffer, size, count, file.get()); + return 0; +} + +size_t EnhancedFile::read(void* buffer, size_t size, size_t count) noexcept { + if (file) return fread(buffer, size, count, file.get()); + return 0; +} + +int EnhancedFile::putc(int ch) noexcept { + if (file) return fputc(ch, file.get()); + return EOF; +} + +int EnhancedFile::getc() noexcept { + if (file) return fgetc(file.get()); + return EOF; +} + +bool EnhancedFile::puts(const char* str) noexcept { + if (file) return fputs(str, file.get()) >= 0; + return false; +} + +char* EnhancedFile::gets(char* buffer, int maxSize) noexcept { + if (file) return fgets(buffer, maxSize, file.get()); + return nullptr; +} + +int EnhancedFile::printf(const char* format, ...) noexcept { + if (!file) return -1; + va_list args; + va_start(args, format); + int result = vfprintf(file.get(), format, args); + va_end(args); + return result; +} + +int EnhancedFile::scanf(const char* format, ...) noexcept { + if (!file) return EOF; + va_list args; + va_start(args, format); + int result = vfscanf(file.get(), format, args); + va_end(args); + return result; +} + +// 工厂函数实现 +EnhancedFile oxfopen_enhanced(const char* fn, const char* mode) { + return EnhancedFile(oxfopen(fn, mode)); +} + +EnhancedFile my_oxfopen_enhanced(const char* fn, const char* mode) { + return EnhancedFile(my_oxfopen(fn, mode)); +} + +// 操纵符实现 +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::hex_tag) { + ef.set_hex(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::dec_tag) { + ef.set_dec(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::oct_tag) { + ef.set_oct(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::showbase_tag) { + ef.set_showbase(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noshowbase_tag) { + ef.set_showbase(false); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::uppercase_tag) { + ef.set_uppercase(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::nouppercase_tag) { + ef.set_uppercase(false); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::boolalpha_tag) { + ef.set_boolalpha(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noboolalpha_tag) { + ef.set_boolalpha(false); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::skipws_tag) { + ef.set_skipws(true); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noskipws_tag) { + ef.set_skipws(false); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::endl_tag) { + if (ef) { + fputc('\n', ef.get()); + ef.flush(); + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::flush_tag) { + if (ef) ef.flush(); + return ef; +} + +// 标准库兼容的 endl +EnhancedFile& operator<<(EnhancedFile& ef, std::ostream& (*manip)(std::ostream&)) { + if (ef && manip == static_cast(std::endl)) { + fputc('\n', ef.get()); + ef.flush(); + } + return ef; +} + +// 流式输出运算符实现 +EnhancedFile& operator<<(EnhancedFile& ef, const char* str) { + if (ef && str) fputs(str, ef.get()); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, const std::string& str) { + if (ef) fputs(str.c_str(), ef.get()); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, int val) { + if (ef) { + if (ef.is_hex() || ef.is_oct()) { + unsigned int uval = static_cast(val); + if (ef.is_hex()) { + if (ef.showbase()) fprintf(ef.get(), "0x"); + fprintf(ef.get(), ef.uppercase() ? "%X" : "%x", uval); + } else { + if (ef.showbase()) fprintf(ef.get(), "0"); + fprintf(ef.get(), "%o", uval); + } + } else { + fprintf(ef.get(), "%d", val); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, unsigned int val) { + if (ef) { + if (ef.is_hex()) { + if (ef.showbase()) fprintf(ef.get(), "0x"); + fprintf(ef.get(), ef.uppercase() ? "%X" : "%x", val); + } else if (ef.is_oct()) { + if (ef.showbase()) fprintf(ef.get(), "0"); + fprintf(ef.get(), "%o", val); + } else { + fprintf(ef.get(), "%u", val); + } + + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, long val) { + if (ef) { + if (ef.is_hex() || ef.is_oct()) { + unsigned long uval = static_cast(val); + if (ef.is_hex()) { + if (ef.showbase()) fprintf(ef.get(), "0x"); + fprintf(ef.get(), ef.uppercase() ? "%lX" : "%lx", uval); + } else { + if (ef.showbase()) fprintf(ef.get(), "0"); + fprintf(ef.get(), "%lo", uval); + } + } else { + fprintf(ef.get(), "%ld", val); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, unsigned long val) { + if (ef) { + FILE* f = ef.get(); + if (ef.is_hex()) { + if (ef.showbase()) fprintf(f, "0x"); + fprintf(f, ef.uppercase() ? "%lX" : "%lx", val); + } else if (ef.is_oct()) { + if (ef.showbase()) fprintf(f, "0"); + fprintf(f, "%lo", val); + } else { + fprintf(f, "%lu", val); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, long long val) { + if (ef) { + FILE* f = ef.get(); + if (ef.is_hex() || ef.is_oct()) { + + unsigned long long uval = static_cast(val); + if (ef.is_hex()) { + if (ef.showbase()) fprintf(f, "0x"); + fprintf(f, ef.uppercase() ? "%llX" : "%llx", uval); + } else { + if (ef.showbase()) fprintf(f, "0"); + fprintf(f, "%llo", uval); + } + } else { + fprintf(f, "%lld", val); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, unsigned long long val) { + if (ef) { + FILE* f = ef.get(); + if (ef.is_hex()) { + if (ef.showbase()) fprintf(f, "0x"); + fprintf(f, ef.uppercase() ? "%llX" : "%llx", val); + } else if (ef.is_oct()) { + if (ef.showbase()) fprintf(f, "0"); + fprintf(f, "%llo", val); + } else { + fprintf(f, "%llu", val); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, float val) { + if (ef) fprintf(ef.get(), "%f", val); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, double val) { + if (ef) fprintf(ef.get(), "%f", val); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, long double val) { + if (ef) fprintf(ef.get(), "%Lf", val); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, char c) { + if (ef) fputc(c, ef.get()); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, unsigned char c) { + if (ef) fputc(static_cast(c), ef.get()); + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, bool val) { + if (ef) { + if (ef.boolalpha()) { + fputs(val ? "true" : "false", ef.get()); + } else { + fprintf(ef.get(), "%d", val ? 1 : 0); + } + } + return ef; +} + +EnhancedFile& operator<<(EnhancedFile& ef, const void* ptr) { + if (ef) fprintf(ef.get(), "%p", ptr); + return ef; +} + +// 流式输入运算符实现 +EnhancedFile& operator>>(EnhancedFile& ef, std::string& str) { + if (ef) { + str.clear(); + + // 跳过空白字符 + if (ef.skipws()) { + int ch; + while ((ch = fgetc(ef.get())) != EOF && std::isspace(ch)); + if (ch != EOF) ungetc(ch, ef.get()); + } + + // 读取非空白字符 + char buffer[4096]; + if (fscanf(ef.get(), "%4095s", buffer) == 1) { + str = buffer; + } + } + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, int& val) { + if (ef) fscanf(ef.get(), "%d", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, unsigned int& val) { + if (ef) fscanf(ef.get(), "%u", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, long& val) { + if (ef) fscanf(ef.get(), "%ld", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, unsigned long& val) { + if (ef) fscanf(ef.get(), "%lu", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, long long& val) { + if (ef) fscanf(ef.get(), "%lld", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, unsigned long long& val) { + if (ef) fscanf(ef.get(), "%llu", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, float& val) { + if (ef) fscanf(ef.get(), "%f", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, double& val) { + if (ef) fscanf(ef.get(), "%lf", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, long double& val) { + if (ef) fscanf(ef.get(), "%Lf", &val); + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, char& c) { + if (ef) { + if (ef.skipws()) { + int ch; + while ((ch = fgetc(ef.get())) != EOF && std::isspace(ch)); + if (ch != EOF) { + c = static_cast(ch); + return ef; + } + } else { + int ch = fgetc(ef.get()); + if (ch != EOF) { + c = static_cast(ch); + return ef; + } + } + } + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, unsigned char& c) { + if (ef) { + int ch = fgetc(ef.get()); + if (ch != EOF) { + c = static_cast(ch); + } + } + return ef; +} + +EnhancedFile& operator>>(EnhancedFile& ef, bool& val) { + if (ef) { + std::string str; + ef >> str; + if (str == "true" || str == "1") { + val = true; + } else if (str == "false" || str == "0") { + val = false; + } + } + return ef; } \ No newline at end of file diff --git a/core/file_io.h b/core/file_io.h index 75d5b79..647ae6e 100644 --- a/core/file_io.h +++ b/core/file_io.h @@ -1,15 +1,211 @@ #pragma once #include #include +#include +#include + +#ifndef __cplusplus + #error "This header requires C++. Please compile with a C++ compiler." +#endif struct FileDeleter { void operator()(FILE* f) const noexcept { if (f) fclose(f); } }; + +// 基础类型定义 using UniqueFile = std::unique_ptr; +// 格式化状态标志 +enum class NumberBase { + Dec, + Hex, + Oct +}; + +// 增强的文件类,支持运算符重载 +class EnhancedFile { +private: + UniqueFile file; + + // 格式化状态 + struct FormatState { + NumberBase base = NumberBase::Dec; + bool showbase = false; // 显示进制前缀 (0x, 0) + bool uppercase = false; // 十六进制大写字母 + bool boolalpha = false; // true/false 而不是 1/0 + bool skipws = true; // 跳过空白字符 + int width = 0; // 字段宽度 (0=无限制) + int precision = 6; // 浮点数精度 + char fill = ' '; // 填充字符 + } format; + +public: + // 构造函数 + EnhancedFile() noexcept = default; + explicit EnhancedFile(FILE* f) noexcept; + explicit EnhancedFile(UniqueFile&& f) noexcept; + + // 移动语义 + EnhancedFile(EnhancedFile&& other) noexcept = default; + EnhancedFile& operator=(EnhancedFile&& other) noexcept = default; + + // 禁止拷贝 + EnhancedFile(const EnhancedFile&) = delete; + EnhancedFile& operator=(const EnhancedFile&) = delete; + + // 析构函数 + ~EnhancedFile() = default; + + // 运算符重载 + explicit operator bool() const noexcept; + bool operator!() const noexcept; + operator FILE*() const noexcept; + FILE* operator->() const noexcept; + FILE& operator*() const noexcept; + + // 成员函数 + FILE* get() const noexcept; + UniqueFile release() noexcept; + void reset(FILE* f = nullptr) noexcept; + void close() noexcept; + bool flush() noexcept; + long tell() const noexcept; + bool seek(long offset, int origin) noexcept; + bool eof() const noexcept; + bool error() const noexcept; + void clearerr() noexcept; + + // 读写操作 + size_t write(const void* buffer, size_t size, size_t count) noexcept; + size_t read(void* buffer, size_t size, size_t count) noexcept; + int putc(int ch) noexcept; + int getc() noexcept; + bool puts(const char* str) noexcept; + char* gets(char* buffer, int maxSize) noexcept; + int printf(const char* format, ...) noexcept; + int scanf(const char* format, ...) noexcept; + + // 格式化状态设置 + void set_base(NumberBase base) noexcept { format.base = base; } + void set_hex(bool enable) noexcept { format.base = enable ? NumberBase::Hex : NumberBase::Dec; } + void set_oct(bool enable) noexcept { format.base = enable ? NumberBase::Oct : NumberBase::Dec; } + void set_dec(bool enable) noexcept { if (enable) format.base = NumberBase::Dec; } + void set_showbase(bool enable) noexcept { format.showbase = enable; } + void set_uppercase(bool enable) noexcept { format.uppercase = enable; } + void set_boolalpha(bool enable) noexcept { format.boolalpha = enable; } + void set_skipws(bool enable) noexcept { format.skipws = enable; } + void set_width(int w) noexcept { format.width = w; } + void set_precision(int p) noexcept { format.precision = p; } + void set_fill(char c) noexcept { format.fill = c; } + + // 格式化状态获取 + NumberBase base() const noexcept { return format.base; } + bool is_hex() const noexcept { return format.base == NumberBase::Hex; } + bool is_oct() const noexcept { return format.base == NumberBase::Oct; } + bool is_dec() const noexcept { return format.base == NumberBase::Dec; } + bool showbase() const noexcept { return format.showbase; } + bool uppercase() const noexcept { return format.uppercase; } + bool boolalpha() const noexcept { return format.boolalpha; } + bool skipws() const noexcept { return format.skipws; } + int width() const noexcept { return format.width; } + int precision() const noexcept { return format.precision; } + char fill() const noexcept { return format.fill; } +}; + +// 工厂函数 +EnhancedFile oxfopen_enhanced(const char* fn, const char* mode); +EnhancedFile my_oxfopen_enhanced(const char* fn, const char* mode); + +// 原有的函数声明 FILE* oxfopen(const char* fn, const char* mode); FILE* my_oxfopen(const char* fn, const char* mode); UniqueFile oxfopen_unique(const char* fn, const char* mode); -UniqueFile my_oxfopen_unique(const char* fn, const char* mode); \ No newline at end of file +UniqueFile my_oxfopen_unique(const char* fn, const char* mode); + +// 自定义操纵符 +namespace file_manip { + // 进制操纵符 + struct hex_tag {}; inline constexpr hex_tag hex; + struct dec_tag {}; inline constexpr dec_tag dec; + struct oct_tag {}; inline constexpr oct_tag oct; + + // 格式操纵符 + struct showbase_tag {}; inline constexpr showbase_tag showbase; + struct noshowbase_tag {}; inline constexpr noshowbase_tag noshowbase; + struct uppercase_tag {}; inline constexpr uppercase_tag uppercase; + struct nouppercase_tag {}; inline constexpr nouppercase_tag nouppercase; + struct boolalpha_tag {}; inline constexpr boolalpha_tag boolalpha; + struct noboolalpha_tag {}; inline constexpr noboolalpha_tag noboolalpha; + struct skipws_tag {}; inline constexpr skipws_tag skipws; + struct noskipws_tag {}; inline constexpr noskipws_tag noskipws; + + // 流操纵符 + struct endl_tag {}; inline constexpr endl_tag endl; + struct flush_tag {}; inline constexpr flush_tag flush; +} + +// 进制操纵符重载 +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::hex_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::dec_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::oct_tag); + +// 格式操纵符重载 +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::showbase_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noshowbase_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::uppercase_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::nouppercase_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::boolalpha_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noboolalpha_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::skipws_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::noskipws_tag); + +// 流操纵符重载 +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::endl_tag); +EnhancedFile& operator<<(EnhancedFile& ef, file_manip::flush_tag); + +// 标准库兼容的操纵符重载(可选) +EnhancedFile& operator<<(EnhancedFile& ef, std::ostream& (*manip)(std::ostream&)); + +// 流式输出运算符 (<<) +EnhancedFile& operator<<(EnhancedFile& ef, const char* str); +EnhancedFile& operator<<(EnhancedFile& ef, const std::string& str); +EnhancedFile& operator<<(EnhancedFile& ef, int val); +EnhancedFile& operator<<(EnhancedFile& ef, unsigned int val); +EnhancedFile& operator<<(EnhancedFile& ef, long val); +EnhancedFile& operator<<(EnhancedFile& ef, unsigned long val); +EnhancedFile& operator<<(EnhancedFile& ef, long long val); +EnhancedFile& operator<<(EnhancedFile& ef, unsigned long long val); +EnhancedFile& operator<<(EnhancedFile& ef, float val); +EnhancedFile& operator<<(EnhancedFile& ef, double val); +EnhancedFile& operator<<(EnhancedFile& ef, long double val); +EnhancedFile& operator<<(EnhancedFile& ef, char c); +EnhancedFile& operator<<(EnhancedFile& ef, unsigned char c); +EnhancedFile& operator<<(EnhancedFile& ef, bool val); +EnhancedFile& operator<<(EnhancedFile& ef, const void* ptr); + +// 流式输入运算符 (>>) +EnhancedFile& operator>>(EnhancedFile& ef, std::string& str); +EnhancedFile& operator>>(EnhancedFile& ef, int& val); +EnhancedFile& operator>>(EnhancedFile& ef, unsigned int& val); +EnhancedFile& operator>>(EnhancedFile& ef, long& val); +EnhancedFile& operator>>(EnhancedFile& ef, unsigned long& val); +EnhancedFile& operator>>(EnhancedFile& ef, long long& val); +EnhancedFile& operator>>(EnhancedFile& ef, unsigned long long& val); +EnhancedFile& operator>>(EnhancedFile& ef, float& val); +EnhancedFile& operator>>(EnhancedFile& ef, double& val); +EnhancedFile& operator>>(EnhancedFile& ef, long double& val); +EnhancedFile& operator>>(EnhancedFile& ef, char& c); +EnhancedFile& operator>>(EnhancedFile& ef, unsigned char& c); +EnhancedFile& operator>>(EnhancedFile& ef, bool& val); + +// 从 UniqueFile 创建 EnhancedFile +inline EnhancedFile to_enhanced(UniqueFile&& uf) { + return EnhancedFile(std::move(uf)); +} + +// 从 EnhancedFile 获取 UniqueFile +inline UniqueFile to_unique(EnhancedFile&& ef) { + return ef.release(); +} \ No newline at end of file From f0262c100010490874affd67f3ea19de840f3a20 Mon Sep 17 00:00:00 2001 From: CrepHidery Date: Sat, 30 May 2026 13:02:57 +0800 Subject: [PATCH 2/4] fix: savepath --- core/file_io.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/file_io.cpp b/core/file_io.cpp index 245b01c..e34f7fa 100644 --- a/core/file_io.cpp +++ b/core/file_io.cpp @@ -40,11 +40,7 @@ FILE* xfopen(const char* fn, const char* mode) { #endif } -// 原有的 my_fopen 函数实现 -extern char savepath[]; - FILE *my_fopen(const char *fn, const char *mode) { - extern char savepath[]; if (savepath[0]) { size_t fn_len = strlen(fn); size_t path_len = strlen(savepath); @@ -66,7 +62,6 @@ FILE *my_fopen(const char *fn, const char *mode) { // 原有的 my_xfopen 函数实现 FILE* my_xfopen(const char* fn, const char* mode) { - extern char savepath[]; FILE* file = nullptr; char* fix_fn = nullptr; From 45d64fa0d95b6404c7fff81c17fea0fe4f203c88 Mon Sep 17 00:00:00 2001 From: CrepHidery Date: Sat, 30 May 2026 13:18:14 +0800 Subject: [PATCH 3/4] fix: operator>> --- core/file_io.cpp | 54 +++++++++++++++++++++++++++++++------- core/pac_extract.cpp | 15 ++++++----- main_console.cpp | 30 +++++++++------------ pages/page_advanced_op.cpp | 2 +- pages/page_connect.cpp | 8 +++--- pages/page_log.cpp | 4 +-- pages/page_manual.cpp | 2 +- pages/page_partition.cpp | 4 +-- 8 files changed, 76 insertions(+), 43 deletions(-) diff --git a/core/file_io.cpp b/core/file_io.cpp index e34f7fa..bad43ca 100644 --- a/core/file_io.cpp +++ b/core/file_io.cpp @@ -521,47 +521,83 @@ EnhancedFile& operator>>(EnhancedFile& ef, std::string& str) { } EnhancedFile& operator>>(EnhancedFile& ef, int& val) { - if (ef) fscanf(ef.get(), "%d", &val); + if (ef) { + if (fscanf(ef.get(), "%d", &val) != 1) { + val = 0; // 读取失败时设置默认值 + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, unsigned int& val) { - if (ef) fscanf(ef.get(), "%u", &val); + if (ef) { + if (fscanf(ef.get(), "%u", &val) != 1) { + val = 0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, long& val) { - if (ef) fscanf(ef.get(), "%ld", &val); + if (ef) { + if (fscanf(ef.get(), "%ld", &val) != 1) { + val = 0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, unsigned long& val) { - if (ef) fscanf(ef.get(), "%lu", &val); + if (ef) { + if (fscanf(ef.get(), "%lu", &val) != 1) { + val = 0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, long long& val) { - if (ef) fscanf(ef.get(), "%lld", &val); + if (ef) { + if (fscanf(ef.get(), "%lld", &val) != 1) { + val = 0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, unsigned long long& val) { - if (ef) fscanf(ef.get(), "%llu", &val); + if (ef) { + if (fscanf(ef.get(), "%llu", &val) != 1) { + val = 0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, float& val) { - if (ef) fscanf(ef.get(), "%f", &val); + if (ef) { + if (fscanf(ef.get(), "%f", &val) != 1) { + val = 0.0f; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, double& val) { - if (ef) fscanf(ef.get(), "%lf", &val); + if (ef) { + if (fscanf(ef.get(), "%lf", &val) != 1) { + val = 0.0; + } + } return ef; } EnhancedFile& operator>>(EnhancedFile& ef, long double& val) { - if (ef) fscanf(ef.get(), "%Lf", &val); + if (ef) { + if (fscanf(ef.get(), "%Lf", &val) != 1) { + val = 0.0L; + } + } return ef; } diff --git a/core/pac_extract.cpp b/core/pac_extract.cpp index 156dbc9..76b26d1 100644 --- a/core/pac_extract.cpp +++ b/core/pac_extract.cpp @@ -763,10 +763,10 @@ bool pac_extract(const char* fn, const char* floder) DEG_LOG(E, "No partition info found in xml"); return false; } - UniqueFile fi = oxfopen_unique("partitions_temp.xml","w"); + EnhancedFile fi = oxfopen_enhanced("partitions_temp.xml","w"); if(fi) { - fwrite(partxml.c_str(), 1, partxml.size(), fi.get()); - fi.reset(); + fi << partxml; + fi.close(); } else { DEG_LOG(E, "Failed to create temporary partitions XML file."); @@ -1016,12 +1016,13 @@ bool pac_flash(spdio_t* io, const char* floder) auto into_func = [=]() mutable { - UniqueFile fi = oxfopen_unique(fdl1_path.c_str(), "r"); + EnhancedFile fi = oxfopen_enhanced(fdl1_path.c_str(), "r"); if (!fi) { DEG_LOG(W, "File does not exist.\n"); if (isHelperInit) gui_idle_call_wait_drag([](){ showErrorDialog(GTK_WINDOW(helper.getWidget("main_window")), _("Error"), _("File does not exist.")); }, GTK_WINDOW(helper.getWidget("main_window"))); + fi.close(); return; } send_file(io, fdl1_path.c_str(), fdl1_base_addr, 0, 528, 0, 0); @@ -1200,11 +1201,11 @@ bool pac_flash(spdio_t* io, const char* floder) std::istreambuf_iterator()); std::string partxml = ExtractPartitionsWithTags(content); - UniqueFile f1 = oxfopen_unique("repartition_xml_temp.xml", "w"); + EnhancedFile f1 = oxfopen_enhanced("repartition_xml_temp.xml", "w"); if (!f1) ERR_EXIT("Failed to create temporary repartition XML file.\n"); if(f1) { - fwrite(partxml.c_str(), 1, partxml.size(), f1.get()); - f1.reset(); + f1 << partxml; + f1.close(); } uint8_t* buf = io->temp_buf; int n = scan_xml_partitions(io, "repartition_xml_temp.xml", buf, 0xffff); diff --git a/main_console.cpp b/main_console.cpp index 0238ae8..a9b9dc9 100644 --- a/main_console.cpp +++ b/main_console.cpp @@ -1815,15 +1815,14 @@ int main_console(int argc, char** argv) { continue; } const char* fn; - UniqueFile fi; if (argcount <= 2) { DEG_LOG(W, "read_parts partition_table_file"); argc = 1; continue; } fn = str2[2]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + EnhancedFile fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist."); argc -= 2; argv += 2; @@ -1836,15 +1835,14 @@ int main_console(int argc, char** argv) { } else if(!strcmp(str2[1], "pac")){ const char* fn; - UniqueFile fi; if (argcount <= 2) { DEG_LOG(W, "pac FILE"); argc = 1; continue; } fn = str2[2]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + EnhancedFile fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist."); argc -= 2; argv += 2; @@ -2003,15 +2001,14 @@ int main_console(int argc, char** argv) { continue; } const char* fn; - UniqueFile fi; if (argcount <= 2) { DEG_LOG(W, "repartition FILE"); argc = 1; continue; } fn = str2[2]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + EnhancedFile fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist."); argc -= 2; argv += 2; @@ -2166,7 +2163,7 @@ int main_console(int argc, char** argv) { continue; } const char* fn; - UniqueFile fi; + EnhancedFile fi; const char* name = str2[2]; if (argcount <= 3) { DEG_LOG(W, "w/write_part part_name/part_id FILE\n"); @@ -2174,8 +2171,8 @@ int main_console(int argc, char** argv) { continue; } fn = str2[3]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist.\n"); argc -= 3; argv += 3; @@ -2240,7 +2237,6 @@ int main_console(int argc, char** argv) { continue; } const char* fn; - UniqueFile fi; const char* name = str2[2]; if (argcount <= 3) { DEG_LOG(W, "w_force part_name/part_id FILE"); @@ -2261,8 +2257,8 @@ int main_console(int argc, char** argv) { continue; } fn = str2[3]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + EnhancedFile fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist."); argc -= 3; argv += 3; @@ -2299,8 +2295,8 @@ int main_console(int argc, char** argv) { continue; } fn = str2[3]; - fi = oxfopen_unique(fn, "r"); - if (fi == nullptr) { + EnhancedFile fi = oxfopen_enhanced(fn, "r"); + if (!fi) { DEG_LOG(E, "File does not exist."); argc -= 3; argv += 3; diff --git a/pages/page_advanced_op.cpp b/pages/page_advanced_op.cpp index cd7f563..2b3e0b6 100644 --- a/pages/page_advanced_op.cpp +++ b/pages/page_advanced_op.cpp @@ -75,7 +75,7 @@ static void on_button_clicked_start_repart(GtkWidgetHelper helper) { ensure_device_attached_or_exit(helper); GtkWidget *parent = helper.getWidget("main_window"); std::string filePath = helper.getEntryText(helper.getWidget("xml_path")); - UniqueFile fi = oxfopen_unique(filePath.c_str(), "r"); + EnhancedFile fi = oxfopen_enhanced(filePath.c_str(), "r"); if (!fi) { DEG_LOG(E, "File does not exist."); return; diff --git a/pages/page_connect.cpp b/pages/page_connect.cpp index a5e4032..1cd49e1 100644 --- a/pages/page_connect.cpp +++ b/pages/page_connect.cpp @@ -139,7 +139,7 @@ void on_button_clicked_fdl_exec(GtkWidgetHelper helper) { bottom_bar_set_status(dtxt + " -> FDL Executing"); //Send fdl2 if (g_app_state.device.device_mode == SPRD3) { - UniqueFile fi = oxfopen_unique(fdl_path, "r"); + EnhancedFile fi = oxfopen_enhanced(fdl_path, "r"); if (!fi) { DEG_LOG(W, "File does not exist."); return; @@ -152,7 +152,7 @@ void on_button_clicked_fdl_exec(GtkWidgetHelper helper) { if (result) { DEG_LOG(I, "Skipping FDL send in SPRD4 mode."); } else { - UniqueFile fi = oxfopen_unique(fdl_path, "r"); + EnhancedFile fi = oxfopen_enhanced(fdl_path, "r"); if (!fi) { DEG_LOG(W, "File does not exist."); return; @@ -338,7 +338,7 @@ void on_button_clicked_fdl_exec(GtkWidgetHelper helper) { if(!(helper.getSwitchState(helper.getWidget("exec_addr"))) && g_app_state.device.device_mode == SPRD3) { // 1) 保留原有 fdl_info.json 写入逻辑,兼容旧行为 - UniqueFile json_file = oxfopen_unique("fdl_info.json", "w"); + EnhancedFile json_file = oxfopen_enhanced("fdl_info.json", "w"); if (json_file) { json j = { @@ -347,7 +347,7 @@ void on_button_clicked_fdl_exec(GtkWidgetHelper helper) { {"fdl2_path", fdl2_path_json}, {"fdl2_addr", fdl2_addr_json} }; - fprintf(json_file.get(), "%s\n", j.dump().c_str()); + json_file << j.dump(); } // 2) 同步写入 AppConfig,交由 ConfigService 管理“最近使用的 FDL” diff --git a/pages/page_log.cpp b/pages/page_log.cpp index c6b3f15..a9565b8 100644 --- a/pages/page_log.cpp +++ b/pages/page_log.cpp @@ -12,12 +12,12 @@ static void on_button_clicked_exp_log(GtkWidgetHelper helper) { } std::string txt_orig = helper.getTextAreaText(txtOutput); const char* txt = txt_orig.c_str(); - UniqueFile fo = oxfopen_unique(savePath.c_str(), "w"); + EnhancedFile fo = oxfopen_enhanced(savePath.c_str(), "w"); if (!fo) { showErrorDialog(GTK_WINDOW(parent), _(_(_(("Error")))), _("Failed to save log file!")); return; } - fprintf(fo.get(), "%s", txt); + fo << txt; showInfoDialog(GTK_WINDOW(parent), _(_(_(("Completed")))), _("Log export completed!")); } diff --git a/pages/page_manual.cpp b/pages/page_manual.cpp index f05e1d4..dc443d2 100644 --- a/pages/page_manual.cpp +++ b/pages/page_manual.cpp @@ -46,7 +46,7 @@ static void on_button_clicked_m_write(GtkWidgetHelper helper) { showErrorDialog(GTK_WINDOW(parent), _(_(_(("Error")))), _("No partition name specified!")); return; } - UniqueFile fi = oxfopen_unique(filename.c_str(), "r"); + EnhancedFile fi = oxfopen_enhanced(filename.c_str(), "r"); if (!fi) { DEG_LOG(E, "File does not exist.\n"); return; diff --git a/pages/page_partition.cpp b/pages/page_partition.cpp index 7536649..e786561 100644 --- a/pages/page_partition.cpp +++ b/pages/page_partition.cpp @@ -607,7 +607,7 @@ void on_button_clicked_list_write(GtkWidgetHelper helper) { showErrorDialog(parent, _(_(("Error"))), _("No partition table loaded, cannot write partition list!")); return; } - UniqueFile fi = oxfopen_unique(filename.c_str(), "r"); + EnhancedFile fi = oxfopen_enhanced(filename.c_str(), "r"); if (!fi) { DEG_LOG(E, "File does not exist.\n"); return; @@ -659,7 +659,7 @@ void on_button_clicked_list_force_write(GtkWidgetHelper helper) { showErrorDialog(parent, _(_(("Error"))), _("No partition table loaded, cannot write partition list!")); return; } - UniqueFile fi = oxfopen_unique(filename.c_str(), "r"); + EnhancedFile fi = oxfopen_enhanced(filename.c_str(), "r"); if (!fi) { DEG_LOG(E, "File does not exist.\n"); return; From cd72554e895dc005fd19c0fec2210ee246ae9816 Mon Sep 17 00:00:00 2001 From: CrepHidery Date: Sat, 30 May 2026 13:28:33 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20operator*=20=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/file_io.cpp | 4 ---- core/file_io.h | 1 - 2 files changed, 5 deletions(-) diff --git a/core/file_io.cpp b/core/file_io.cpp index bad43ca..d640bf0 100644 --- a/core/file_io.cpp +++ b/core/file_io.cpp @@ -159,10 +159,6 @@ FILE* EnhancedFile::operator->() const noexcept { return file.get(); } -FILE& EnhancedFile::operator*() const noexcept { - return *file.get(); -} - FILE* EnhancedFile::get() const noexcept { return file.get(); } diff --git a/core/file_io.h b/core/file_io.h index 647ae6e..d67b75a 100644 --- a/core/file_io.h +++ b/core/file_io.h @@ -63,7 +63,6 @@ class EnhancedFile { bool operator!() const noexcept; operator FILE*() const noexcept; FILE* operator->() const noexcept; - FILE& operator*() const noexcept; // 成员函数 FILE* get() const noexcept;