From 80805e08ee3f377bcb5cc3c0eb70b0220508dcf9 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Thu, 19 Aug 2021 20:37:21 -0700 Subject: [PATCH] 3-point file iteration API; unicode support on win32 --- .../static_site_generator.c | 36 +++-- source/md.c | 137 ++++++++++++------ source/md.h | 11 +- 3 files changed, 126 insertions(+), 58 deletions(-) diff --git a/samples/static_site_generator/static_site_generator.c b/samples/static_site_generator/static_site_generator.c index 9de4d2f..321bed3 100644 --- a/samples/static_site_generator/static_site_generator.c +++ b/samples/static_site_generator/static_site_generator.c @@ -69,22 +69,32 @@ int main(int argument_count, char **arguments) MD_Node *root_list = MD_MakeList(arena); { printf("Searching for site pages at \"%.*s\"...\n", MD_S8VArg(page_dir_path)); - MD_FileInfo file_info = {0}; - for(MD_FileIter it = {0}; MD_FileIterIncrement(arena, &it, page_dir_path, &file_info);) + + MD_FileIter it = {0}; + if (MD_FileIterBegin(&it, page_dir_path)) { - if(MD_S8Match(MD_PathSkipLastPeriod(file_info.filename), MD_S8Lit("md"), MD_StringMatchFlag_CaseInsensitive) && - !MD_S8Match(MD_PathSkipLastSlash(MD_PathChopLastPeriod(file_info.filename)), - MD_PathSkipLastSlash(MD_PathChopLastPeriod(site_info_path)), - MD_StringMatchFlag_CaseInsensitive | - MD_StringMatchFlag_SlashInsensitive)) + for(;;) { - printf("Processing site page at \"%.*s\"...\n", MD_S8VArg(file_info.filename)); - MD_String8 folder = MD_PathChopLastSlash(page_dir_path); - MD_String8 path = MD_S8Fmt(arena, "%.*s/%.*s", - MD_S8VArg(folder), MD_S8VArg(file_info.filename)); - MD_Node *node = MD_ParseWholeFile(arena, path).node; - MD_PushNewReference(arena, root_list, node); + MD_FileInfo file_info = MD_FileIterNext(arena, &it); + if (file_info.filename.size == 0) + { + break; + } + if(MD_S8Match(MD_PathSkipLastPeriod(file_info.filename), MD_S8Lit("md"), MD_StringMatchFlag_CaseInsensitive) && + !MD_S8Match(MD_PathSkipLastSlash(MD_PathChopLastPeriod(file_info.filename)), + MD_PathSkipLastSlash(MD_PathChopLastPeriod(site_info_path)), + MD_StringMatchFlag_CaseInsensitive | + MD_StringMatchFlag_SlashInsensitive)) + { + printf("Processing site page at \"%.*s\"...\n", MD_S8VArg(file_info.filename)); + MD_String8 folder = MD_PathChopLastSlash(page_dir_path); + MD_String8 path = MD_S8Fmt(arena, "%.*s/%.*s", + MD_S8VArg(folder), MD_S8VArg(file_info.filename)); + MD_Node *node = MD_ParseWholeFile(arena, path).node; + MD_PushNewReference(arena, root_list, node); + } } + MD_FileIterEnd(&it); } } diff --git a/source/md.c b/source/md.c index eadb9eb..9a998b3 100644 --- a/source/md.c +++ b/source/md.c @@ -13,53 +13,89 @@ //- win32 "file iteration" #if MD_DEFAULT_FILE_ITER && MD_OS_WINDOWS -#if !defined(MD_IMPL_FileIterIncrement) -# define MD_IMPL_FileIterIncrement MD_WIN32_FileIterIncrement +#if !defined(MD_IMPL_FileIterBegin) +# define MD_IMPL_FileIterBegin MD_WIN32_FileIterBegin +#endif +#if !defined(MD_IMPL_FileIterNext) +# define MD_IMPL_FileIterNext MD_WIN32_FileIterNext +#endif +#if !defined(MD_IMPL_FileIterEnd) +# define MD_IMPL_FileIterEnd MD_WIN32_FileIterEnd #endif +typedef struct MD_WIN32_FileIter{ + HANDLE state; + MD_u64 first; + WIN32_FIND_DATAW find_data; +} MD_WIN32_FileIter; + +MD_StaticAssert(sizeof(MD_FileIter) >= sizeof(MD_WIN32_FileIter), file_iter_size_check); + static MD_b32 -MD_WIN32_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, - MD_FileInfo *out_info) +MD_WIN32_FileIterBegin(MD_FileIter *it, MD_String8 path) { - MD_b32 result = 0; + //- init search + MD_ArenaTemp scratch = MD_GetScratch(0, 0); - MD_ArenaTemp scratch = MD_GetScratch(&arena, 1); + MD_u8 c = path.str[path.size - 1]; + MD_b32 need_star = (c == '/' || c == '\\'); + MD_String8 cpath = need_star ? MD_S8Fmt(scratch.arena, "%.*s*", MD_S8VArg(path)) : path; + MD_String16 cpath16 = MD_S16FromS8(scratch.arena, cpath); - WIN32_FIND_DATAA find_data = MD_ZERO_STRUCT; - HANDLE state = *(HANDLE *)(&it->state[0]); - if(state == 0) - { - MD_b32 need_star = 0; - if(path.str[path.size-1] == '/' || - path.str[path.size-1] == '\\') - { - need_star = 1; - } - MD_String8 cpath = need_star ? MD_S8Fmt(scratch.arena, "%.*s*", MD_S8VArg(path)) : path; - state = FindFirstFileA((char*)cpath.str, &find_data); - result = !!state; - } - else - { - result = !!FindNextFileA(state, &find_data); - } - - it->state[0] = *(MD_u64 *)(&state); - if(result) - { - out_info->flags = 0; - if(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - out_info->flags |= MD_FileFlag_Directory; - } - out_info->filename = MD_S8Fmt(arena, "%s", find_data.cFileName); - out_info->file_size = ((((MD_u64)find_data.nFileSizeHigh) << 32) | - ((MD_u64)find_data.nFileSizeLow)); - } + WIN32_FIND_DATAW find_data = MD_ZERO_STRUCT; + HANDLE state = FindFirstFileW((WCHAR*)cpath16.str, &find_data); MD_ReleaseScratch(scratch); - return result; + //- fill results + MD_b32 result = !!state; + if (result){ + MD_WIN32_FileIter *win32_it = (MD_WIN32_FileIter*)it; + win32_it->state = state; + win32_it->first = 1; + MD_MemoryCopy(&win32_it->find_data, &find_data, sizeof(find_data)); + } + return(result); +} + +static MD_FileInfo +MD_WIN32_FileIterNext(MD_Arena *arena, MD_FileIter *it) +{ + //- get low-level file info for this step + MD_b32 good = 0; + + MD_WIN32_FileIter *win32_it = (MD_WIN32_FileIter*)it; + WIN32_FIND_DATAW *find_data = &win32_it->find_data; + if (win32_it->first){ + win32_it->first = 0; + good = 1; + } + else{ + good = FindNextFileW(win32_it->state, find_data); + } + + //- convert to MD_FileInfo + MD_FileInfo result = {0}; + if (good){ + if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){ + result.flags |= MD_FileFlag_Directory; + } + MD_u16 *filename_base = (MD_u16*)find_data->cFileName; + MD_u16 *ptr = filename_base; + for (;*ptr != 0; ptr += 1); + MD_String16 filename16 = {filename_base, (MD_u64)(ptr - filename_base)}; + result.filename = MD_S8FromS16(arena, filename16); + result.file_size = ((((MD_u64)find_data->nFileSizeHigh) << 32) | + ((MD_u64)find_data->nFileSizeLow)); + } + return(result); +} + +static void +MD_WIN32_FileIterEnd(MD_FileIter *it) +{ + MD_WIN32_FileIter *win32_it = (MD_WIN32_FileIter*)it; + CloseHandle(win32_it->state); } #endif @@ -3091,12 +3127,31 @@ MD_LoadEntireFile(MD_Arena *arena, MD_String8 filename) } MD_FUNCTION_IMPL MD_b32 -MD_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, MD_FileInfo *out_info) +MD_FileIterBegin(MD_FileIter *it, MD_String8 path) { -#if !defined(MD_IMPL_FileIterIncrement) +#if !defined(MD_IMPL_FileIterBegin) return(0); #else - return(MD_IMPL_FileIterIncrement(arena, it, path, out_info)); + return(MD_IMPL_FileIterBegin(it, path)); +#endif +} + +MD_FUNCTION_IMPL MD_FileInfo +MD_FileIterNext(MD_Arena *arena, MD_FileIter *it) +{ +#if !defined(MD_IMPL_FileIterNext) + MD_FileInfo result = {0}; + return(result); +#else + return(MD_IMPL_FileIterNext(arena, it)); +#endif +} + +MD_FUNCTION_IMPL void +MD_FileIterEnd(MD_FileIter *it) +{ +#if defined(MD_IMPL_FileIterEnd) + MD_IMPL_FileIterEnd(it); #endif } diff --git a/source/md.h b/source/md.h index 758b040..70c2788 100644 --- a/source/md.h +++ b/source/md.h @@ -9,8 +9,9 @@ ** ** Overridable : ** "file iteration" ** OPTIONAL -** #define MD_IMPL_FileIterIncrement -** (MD_Arena*, MD_FileIter*, MD_String8, MD_FileInfo* out) -> MD_b32 +** #define MD_IMPL_FileIterBegin (MD_FileIter*, MD_String8) -> MD_b32 +** #define MD_IMPL_FileIterNext (MD_Arena*, MD_FileIter*) -> MD_FileInfo +** #define MD_IMPL_FileIterEnd (MD_FileIter*) -> void ** ** "low level memory" ** OPTIONAL (required for default arena) ** #define MD_IMPL_Reserve (MD_u64) -> void* @@ -688,7 +689,7 @@ typedef struct MD_FileIter MD_FileIter; struct MD_FileIter { // This is opaque state to store OS-specific file-system iteration data. - MD_u64 state[2]; + MD_u8 opaque[640]; }; //~ Basic Utilities @@ -977,7 +978,9 @@ MD_FUNCTION MD_i64 MD_CmdLineI64FromString(MD_CmdLine cmdln, MD_String8 name); //~ File System MD_FUNCTION MD_String8 MD_LoadEntireFile(MD_Arena *arena, MD_String8 filename); -MD_FUNCTION MD_b32 MD_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, MD_FileInfo *out_info); +MD_FUNCTION MD_b32 MD_FileIterBegin(MD_FileIter *it, MD_String8 path); +MD_FUNCTION MD_FileInfo MD_FileIterNext(MD_Arena *arena, MD_FileIter *it); +MD_FUNCTION void MD_FileIterEnd(MD_FileIter *it); #endif // MD_H