Foundations

This commit is contained in:
2026-08-29 01:50:50 +08:00
parent bf5fc3bda6
commit 8e95904cc4
100 changed files with 13997 additions and 0 deletions
+220
View File
@@ -0,0 +1,220 @@
#include <c_FileIter.h>
#include <stdio.h>
#include <c_Memory.h>
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
#ifdef _WIN32
#include <windows.h>
typedef struct {
HANDLE hFind;
WIN32_FIND_DATAA findData;
} WinIterCtx;
#else
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
typedef struct {
DIR* dir;
} PosixIterCtx;
#endif
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// 内部辅助函数:获取下一个有效条目(过滤 "." 和 ".."
static void c_FileIter_InternalFetch(c_FileIter_t* iter) {
#ifdef _WIN32
WinIterCtx* ctx = (WinIterCtx*)iter->internal_ctx;
while (FindNextFileA(ctx->hFind, &ctx->findData)) {
if (strcmp(ctx->findData.cFileName, ".") == 0 || strcmp(ctx->findData.cFileName, "..") == 0) {
continue; // 过滤
}
// 填充缓存
strncpy(iter->current.name, ctx->findData.cFileName, sizeof(iter->current.name) - 1);
iter->current.name[sizeof(iter->current.name) - 1] = '\0';
if (ctx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
iter->current.type = C_FILE_TYPE_DIR;
iter->current.size = 0;
} else {
iter->current.type = C_FILE_TYPE_REGULAR;
iter->current.size = ((unsigned long long)ctx->findData.nFileSizeHigh << 32) | ctx->findData.nFileSizeLow;
}
iter->has_next = C_TRUE;
return;
}
#else
PosixIterCtx* ctx = (PosixIterCtx*)iter->internal_ctx;
struct dirent* entry;
while ((entry = readdir(ctx->dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue; // 过滤
}
// 填充名字
strncpy(iter->current.name, entry->d_name, sizeof(iter->current.name) - 1);
iter->current.name[sizeof(iter->current.name) - 1] = '\0';
// 组装完整路径获取大文件大小及类型
char full_path[512];
snprintf(full_path, sizeof(full_path), "%s/%s", iter->base_path, entry->d_name);
struct stat stat_buf;
if (stat(full_path, &stat_buf) == 0) {
iter->current.size = (unsigned long long)stat_buf.st_size;
if (S_ISDIR(stat_buf.st_mode)) {
iter->current.type = C_FILE_TYPE_DIR;
} else if (S_ISREG(stat_buf.st_mode)) {
iter->current.type = C_FILE_TYPE_REGULAR;
} else {
iter->current.type = C_FILE_TYPE_UNKNOWN;
}
} else {
iter->current.type = C_FILE_TYPE_UNKNOWN;
iter->current.size = 0;
}
iter->has_next = C_TRUE;
return;
}
#endif
// 没有更多文件了,触发自动资源清理
iter->has_next = C_FALSE;
if (iter->internal_ctx) {
#ifdef _WIN32
FindClose(((WinIterCtx*)iter->internal_ctx)->hFind);
#else
closedir(((PosixIterCtx*)iter->internal_ctx)->dir);
#endif
C_FREE(iter->internal_ctx);
iter->internal_ctx = NULL;
}
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
c_err_t c_FileIter_Init(c_FileIter_t* iter, const char* dirpath) {
if (!iter || !dirpath) return C_ERR_FAIL;
iter->internal_ctx = NULL;
iter->has_next = C_FALSE;
strncpy(iter->base_path, dirpath, sizeof(iter->base_path) - 1);
iter->base_path[sizeof(iter->base_path) - 1] = '\0';
#ifdef _WIN32
WinIterCtx* ctx = (WinIterCtx*)C_ALLOC(sizeof(WinIterCtx));
if (!ctx) return C_ERR_FAIL;
char search_path[512];
snprintf(search_path, sizeof(search_path), "%s\\*", dirpath);
ctx->hFind = FindFirstFile(search_path, &ctx->findData);
if (ctx->hFind == INVALID_HANDLE_VALUE) {
C_FREE(ctx);
return C_ERR_FAIL;
}
iter->internal_ctx = ctx;
// 检查第一个读取到的是否是 "." 或 "..",如果是,则继续查找有效文件
if (strcmp(ctx->findData.cFileName, ".") == 0 || strcmp(ctx->findData.cFileName, "..") == 0) {
c_FileIter_InternalFetch(iter);
} else {
strncpy(iter->current.name, ctx->findData.cFileName, sizeof(iter->current.name) - 1);
iter->current.name[sizeof(iter->current.name) - 1] = '\0';
if (ctx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
iter->current.type = C_FILE_TYPE_DIR;
iter->current.size = 0;
} else {
iter->current.type = C_FILE_TYPE_REGULAR;
iter->current.size = ((unsigned long long)ctx->findData.nFileSizeHigh << 32) | ctx->findData.nFileSizeLow;
}
iter->has_next = C_TRUE;
}
#else
PosixIterCtx* ctx = (PosixIterCtx*)C_ALLOC(sizeof(PosixIterCtx));
if (!ctx) return C_ERR_FAIL;
ctx->dir = opendir(dirpath);
if (!ctx->dir) {
C_FREE(ctx);
return C_ERR_FAIL;
}
iter->internal_ctx = ctx;
// 触发预读第一项
c_FileIter_InternalFetch(iter);
#endif
return C_ERR_OK;
}
c_bool_t c_FileIter_HasNext(c_FileIter_t* iter) {
return (iter != NULL) ? iter->has_next : C_FALSE;
}
void c_FileIter_Next(c_FileIter_t* iter) {
if (iter && iter->has_next) {
c_FileIter_InternalFetch(iter);
}
}
const c_FileEntry_t* c_FileIter_Get(c_FileIter_t* iter) {
if (iter && iter->has_next) {
return &(iter->current);
}
return NULL;
}
c_err_t c_FileIter_Remove(c_FileIter_t* iter) {
if (!iter || !iter->has_next) return C_ERR_FAIL;
char full_path[512];
#ifdef _WIN32
snprintf(full_path, sizeof(full_path), "%s\\%s", iter->base_path, iter->current.name);
#else
snprintf(full_path, sizeof(full_path), "%s/%s", iter->base_path, iter->current.name);
#endif
int res = -1;
if (iter->current.type == C_FILE_TYPE_DIR) {
#ifdef _WIN32
res = RemoveDirectory(full_path) ? 0 : -1;
#else
res = rmdir(full_path);
#endif
} else {
#ifdef _WIN32
res = DeleteFile(full_path) ? 0 : -1;
#else
res = unlink(full_path);
#endif
}
// 执行完物理删除后,提前释放当前迭代器的内部流句柄,防止调用者后续发生未知异常
iter->has_next = C_FALSE;
if (iter->internal_ctx) {
#ifdef _WIN32
FindClose(((WinIterCtx*)iter->internal_ctx)->hFind);
#else
closedir(((PosixIterCtx*)iter->internal_ctx)->dir);
#endif
C_FREE(iter->internal_ctx);
iter->internal_ctx = NULL;
}
return (res == 0) ? C_ERR_OK : C_ERR_FAIL;
}