New list dir api
This commit is contained in:
@@ -202,8 +202,9 @@ int Run(Strs s) {
|
|||||||
|
|
||||||
Strs ListDir(char *dir) {
|
Strs ListDir(char *dir) {
|
||||||
Strs result = {};
|
Strs result = {};
|
||||||
S8_List files = OS_ListDir(Perm, S8_MakeFromChar(dir), 0);
|
for (OS_FileIter it = OS_IterateFiles(Perm, S8_MakeFromChar(dir)); OS_IsValid(it); OS_Advance(&it)) {
|
||||||
S8_For(it, files) result.add(it->string);
|
result.add(S8_Copy(Perm, it.absolute_path));
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,9 @@ int main(int argument_count, char **arguments) {
|
|||||||
// Search for build file in the project directory
|
// Search for build file in the project directory
|
||||||
S8_String build_file = {0};
|
S8_String build_file = {0};
|
||||||
{
|
{
|
||||||
S8_List files_current_dir = OS_ListDir(Perm, S8_Lit(".."), 0);
|
for (OS_FileIter it = OS_IterateFiles(Perm, S8_Lit("..")); OS_IsValid(it); OS_Advance(&it)) {
|
||||||
for (S8_Node *it = files_current_dir.first; it; it = it->next) {
|
if (S8_Find(it.filename, S8_Lit("build_file.c"), S8_IgnoreCase)) {
|
||||||
if (S8_Find(it->string, S8_Lit("build_file.c"), S8_IgnoreCase)) {
|
build_file = it.absolute_path;
|
||||||
build_file = it->string;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,9 +38,8 @@ int main(int argument_count, char **arguments) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
S8_String a = S8_ChopLastPeriod(build_file);
|
S8_String name_no_ext = S8_GetNameNoExt(build_file);
|
||||||
S8_String b = S8_SkipToLastSlash(a);
|
S8_String exe_name = S8_Format(Perm, "%.*s.exe", S8_Expand(name_no_ext));
|
||||||
S8_String exe_name = S8_Format(Perm, "%.*s.exe", S8_Expand(b));
|
|
||||||
|
|
||||||
// Compile the build file only if code changed
|
// Compile the build file only if code changed
|
||||||
if (SRC_WasModified(build_file, exe_name)) {
|
if (SRC_WasModified(build_file, exe_name)) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ SRC_CacheEntry *SRC_FindCache(SRC_Cache *cache, uint64_t filepath_hash) {
|
|||||||
SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) {
|
SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) {
|
||||||
char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false);
|
char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false);
|
||||||
if (!resolved_file) {
|
if (!resolved_file) {
|
||||||
IO_Printf("Failed to resolve file: %s\n", file.str);
|
IO_Printf("Failed to resolve file: %.*s\n", S8_Expand(file));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) {
|
|||||||
S8_String file_it = S8_MakeFromChar(iter.filename);
|
S8_String file_it = S8_MakeFromChar(iter.filename);
|
||||||
SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file);
|
SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file);
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
IO_Printf("Missing cache for: %s\n", file_it.str);
|
IO_Printf("Missing cache for: %.*s\n", S8_Expand(file_it));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
|
- I think it's okay to say that strings being null terminated should be mostly treated as NOT terminated but leave some
|
||||||
|
leeway for big buffers and other such things. Just make sure to not relay on it because it's easier unless specified.
|
||||||
|
- Not sure if we should assume that strings should use allocators or arenas, for now it's arenas because I don't have other use cases
|
||||||
@todo
|
@todo
|
||||||
- Rewrite OS_ListDir, no weird flags and conventions, [relative, absolute, is_dir]
|
|
||||||
- add c++ default args using macros
|
|
||||||
- Rework string flags
|
|
||||||
- String should use allocator instead of arena?
|
|
||||||
- Maybe remove completely null termination from S8_String, I think it might complicate and is error prone because one can sometimes assume it's null terminated and it isn't
|
|
||||||
- Maybe create a nice C++ binding for strings,
|
- Maybe create a nice C++ binding for strings,
|
||||||
- also add String Arrays and String Builder, temp allocators hook ins for nicer api
|
- also add String Arrays and String Builder, temp allocators hook ins for nicer api
|
||||||
- Iterating over unicode codepoints using For
|
- Iterating over unicode codepoints using For
|
||||||
|
|||||||
@@ -126,69 +126,72 @@ OS_API double OS_GetTime(void) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo: I think we want a list with both relative + absolute + other things
|
/*
|
||||||
//
|
User needs to copy particular filename to keep it.
|
||||||
// Returns directories with slash at the end '/'
|
|
||||||
// By default returns absolute paths
|
|
||||||
OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) {
|
|
||||||
MA_Checkpoint scratch = MA_GetScratch1(arena);
|
|
||||||
S8_List dirs_to_read = S8_MakeEmptyList();
|
|
||||||
S8_List result = S8_MakeEmptyList();
|
|
||||||
S8_AddNode(scratch.arena, &dirs_to_read, path);
|
|
||||||
|
|
||||||
for (S8_Node *it = dirs_to_read.first; it; it = it->next) {
|
for (OS_FileIter it = OS_IterateFiles(it); OS_IsValid(iter); OS_Advance(it)) {
|
||||||
wchar_t wbuff[1024];
|
}
|
||||||
S8_String modified_path = S8_Format(scratch.arena, "%.*s\\*", (int)it->string.len, it->string.str);
|
|
||||||
IO_Assert(modified_path.len < MA_LENGTHOF(wbuff));
|
|
||||||
int64_t wsize = UTF_CreateWidecharFromChar(wbuff, MA_LENGTHOF(wbuff), modified_path.str, modified_path.len);
|
|
||||||
IO_Assert(wsize);
|
|
||||||
|
|
||||||
WIN32_FIND_DATAW ffd;
|
*/
|
||||||
HANDLE handle = FindFirstFileW(wbuff, &ffd);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
do {
|
typedef struct OS_Win32_FileIter {
|
||||||
|
HANDLE handle;
|
||||||
|
WIN32_FIND_DATAW data;
|
||||||
|
} OS_Win32_FileIter;
|
||||||
|
|
||||||
//
|
OS_API bool OS_IsValid(OS_FileIter it) {
|
||||||
// Skip '.' and '..'
|
return it.is_valid;
|
||||||
//
|
}
|
||||||
if (ffd.cFileName[0] == '.') {
|
|
||||||
if (ffd.cFileName[1] == '.') {
|
|
||||||
if (ffd.cFileName[2] == 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ffd.cFileName[1] == 0)
|
OS_API void OS_Advance(OS_FileIter *it) {
|
||||||
continue;
|
while (FindNextFileW(it->w32->handle, &it->w32->data) != 0) {
|
||||||
}
|
WIN32_FIND_DATAW *data = &it->w32->data;
|
||||||
|
|
||||||
bool dir = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
// Skip '.' and '..'
|
||||||
S8_String filename = UTF_CreateStringFromWidechar(scratch.arena, ffd.cFileName, S8_WideLength(ffd.cFileName));
|
if (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0) continue;
|
||||||
S8_String is_dir = dir ? S8_Lit("/") : S8_Lit("");
|
if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue;
|
||||||
S8_String rel_abs_path = S8_Format(scratch.arena, "%.*s/%.*s%.*s", S8_Expand(it->string), S8_Expand(filename), S8_Expand(is_dir));
|
|
||||||
if (flags & OS_RELATIVE_PATHS) {
|
|
||||||
S8_Add(arena, &result, rel_abs_path);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
S8_String abs_path = OS_GetAbsolutePath(arena, rel_abs_path);
|
|
||||||
S8_Add(arena, &result, abs_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir && flags & OS_RECURSIVE) {
|
it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
S8_AddNode(scratch.arena, &dirs_to_read, rel_abs_path);
|
it->filename = UTF_CreateStringFromWidechar(it->arena, data->cFileName, S8_WideLength(data->cFileName));
|
||||||
}
|
char *is_dir = it->is_directory ? "/" : "";
|
||||||
} while (FindNextFileW(handle, &ffd) != 0);
|
char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/";
|
||||||
|
it->relative_path = S8_Format(it->arena, "%.*s%s%.*s%s", S8_Expand(it->path), separator, S8_Expand(it->filename), is_dir);
|
||||||
|
it->absolute_path = OS_GetAbsolutePath(it->arena, it->relative_path);
|
||||||
|
it->is_valid = true;
|
||||||
|
|
||||||
DWORD error = GetLastError();
|
if (it->is_directory) {
|
||||||
if (error != ERROR_NO_MORE_FILES) {
|
IO_Assert(it->relative_path.str[it->relative_path.len - 1] == '/');
|
||||||
// Not sure what to do here hmmm
|
IO_Assert(it->absolute_path.str[it->absolute_path.len - 1] == '/');
|
||||||
}
|
}
|
||||||
FindClose(handle);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_ReleaseScratch(scratch);
|
it->is_valid = false;
|
||||||
return result;
|
DWORD error = GetLastError();
|
||||||
|
IO_Assert(error == ERROR_NO_MORE_FILES);
|
||||||
|
FindClose(it->w32->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
OS_API OS_FileIter OS_IterateFiles(MA_Arena *scratch_arena, S8_String path) {
|
||||||
|
OS_FileIter it = {0};
|
||||||
|
it.arena = scratch_arena;
|
||||||
|
it.path = path;
|
||||||
|
|
||||||
|
S8_String modified_path = S8_Format(it.arena, "%.*s\\*", S8_Expand(path));
|
||||||
|
wchar_t *wbuff = MA_PushArray(it.arena, wchar_t, modified_path.len + 1);
|
||||||
|
int64_t wsize = UTF_CreateWidecharFromChar(wbuff, modified_path.len + 1, modified_path.str, modified_path.len);
|
||||||
|
IO_Assert(wsize);
|
||||||
|
|
||||||
|
it.w32 = MA_PushStruct(it.arena, OS_Win32_FileIter);
|
||||||
|
it.w32->handle = FindFirstFileW(wbuff, &it.w32->data);
|
||||||
|
if (it.w32->handle == INVALID_HANDLE_VALUE) {
|
||||||
|
it.is_valid = false;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
IO_Assert(it.w32->data.cFileName[0] == '.' && it.w32->data.cFileName[1] == 0);
|
||||||
|
OS_Advance(&it);
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS_API OS_Result OS_MakeDir(S8_String path) {
|
OS_API OS_Result OS_MakeDir(S8_String path) {
|
||||||
@@ -238,6 +241,9 @@ OS_API OS_Result OS_DeleteFile(S8_String path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) {
|
OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) {
|
||||||
|
IO_Todo();
|
||||||
|
return OS_FAILURE;
|
||||||
|
#if 0
|
||||||
if (flags & OS_RECURSIVE) {
|
if (flags & OS_RECURSIVE) {
|
||||||
MA_Checkpoint scratch = MA_GetScratch();
|
MA_Checkpoint scratch = MA_GetScratch();
|
||||||
S8_List list = OS_ListDir(scratch.arena, path, OS_RECURSIVE);
|
S8_List list = OS_ListDir(scratch.arena, path, OS_RECURSIVE);
|
||||||
@@ -267,6 +273,7 @@ OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) {
|
|||||||
result = OS_PATH_NOT_FOUND;
|
result = OS_PATH_NOT_FOUND;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static OS_Result OS__WriteFile(S8_String path, S8_String data, bool append) {
|
static OS_Result OS__WriteFile(S8_String path, S8_String data, bool append) {
|
||||||
@@ -475,41 +482,39 @@ OS_API double OS_GetTime(void) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) {
|
OS_API bool OS_IsValid(OS_FileIter it) {
|
||||||
IO_Assert((flags & OS_RECURSIVE) == 0);
|
return it.is_valid;
|
||||||
MA_Checkpoint scratch = MA_GetScratch1(arena);
|
}
|
||||||
path = S8_Copy(scratch.arena, path);
|
|
||||||
|
|
||||||
S8_List result = {0};
|
OS_API void OS_Advance(OS_FileIter *it) {
|
||||||
struct dirent *dir = 0;
|
struct dirent *file = 0;
|
||||||
DIR *d = opendir((char *)path.str);
|
while ((file = readdir((DIR *)it->dir)) != NULL) {
|
||||||
if (d) {
|
if (file->d_name[0] == '.' && file->d_name[1] == '.' && file->d_name[2] == 0) continue;
|
||||||
while ((dir = readdir(d)) != NULL) {
|
if (file->d_name[0] == '.' && file->d_name[1] == 0) continue;
|
||||||
if (dir->d_name[0] == '.') {
|
|
||||||
if (dir->d_name[1] == '.') {
|
|
||||||
if (dir->d_name[2] == 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir->d_name[1] == 0)
|
it->is_directory = file->d_type == DT_DIR;
|
||||||
continue;
|
it->filename = S8_CopyChar(it->arena, file->d_name);
|
||||||
}
|
|
||||||
|
|
||||||
S8_String n = S8_Format(scratch.arena, "%.*s/%s", S8_Expand(path), dir->d_name);
|
const char *is_dir = it->is_directory ? "/" : "";
|
||||||
if ((flags & OS_RELATIVE_PATHS) == 0) {
|
const char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/";
|
||||||
n = OS_GetAbsolutePath(scratch.arena, n);
|
it->relative_path = S8_Format(it->arena, "%.*s%s%s%s", S8_Expand(it->path), separator, file->d_name, is_dir);
|
||||||
}
|
it->absolute_path = OS_GetAbsolutePath(it->arena, it->relative_path);
|
||||||
if (dir->d_type == DT_DIR) {
|
it->is_valid = true;
|
||||||
n = S8_Format(scratch.arena, "%.*s/", S8_Expand(n));
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
S8_AddNode(arena, &result, S8_Copy(arena, n));
|
|
||||||
}
|
|
||||||
closedir(d);
|
|
||||||
}
|
}
|
||||||
|
it->is_valid = false;
|
||||||
|
closedir((DIR *)it->dir);
|
||||||
|
}
|
||||||
|
|
||||||
MA_ReleaseScratch(scratch);
|
OS_API OS_FileIter OS_IterateFiles(MA_Arena *arena, S8_String path) {
|
||||||
return result;
|
OS_FileIter it = {0};
|
||||||
|
it.arena = arena;
|
||||||
|
it.path = path = S8_Copy(arena, path);
|
||||||
|
it.dir = (void *)opendir((char *)path.str);
|
||||||
|
if (!it.dir) return it;
|
||||||
|
|
||||||
|
OS_Advance(&it);
|
||||||
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
OS_API OS_Result OS_MakeDir(S8_String path) {
|
OS_API OS_Result OS_MakeDir(S8_String path) {
|
||||||
@@ -651,7 +656,7 @@ OS_API OS_Result OS_WriteFile(S8_String path, S8_String string) {
|
|||||||
OS_API int OS_SystemF(const char *string, ...) {
|
OS_API int OS_SystemF(const char *string, ...) {
|
||||||
MA_Checkpoint scratch = MA_GetScratch();
|
MA_Checkpoint scratch = MA_GetScratch();
|
||||||
S8_FORMAT(scratch.arena, string, result);
|
S8_FORMAT(scratch.arena, string, result);
|
||||||
IO_Printf("Executing: %s\n", result.str);
|
IO_Printf("Executing: %.*s\n", S8_Expand(result));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
int error_code = system(result.str);
|
int error_code = system(result.str);
|
||||||
MA_ReleaseScratch(scratch);
|
MA_ReleaseScratch(scratch);
|
||||||
@@ -666,45 +671,6 @@ OS_API S8_String UTF_CreateStringFromWidechar(MA_Arena *arena, wchar_t *wstr, in
|
|||||||
return S8_Make(buffer, size);
|
return S8_Make(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
OS_API S8_List S8_SplitOnRegex(MA_Arena *arena, S8_String string, S8_String regex, unsigned flags) {
|
|
||||||
S8_List result = S8_MakeEmptyList();
|
|
||||||
int64_t index = 0;
|
|
||||||
|
|
||||||
char buff[4096];
|
|
||||||
RE_Regex *re = RE2_Parse(buff, sizeof(buff), regex.str, regex.len);
|
|
||||||
for (RE_Match match = RE3_Find(re, string.str, string.len); match.pos != -1; match = RE3_Find(re, string.str, string.len)) {
|
|
||||||
S8_String before_match = S8_Make(string.str, match.pos);
|
|
||||||
S8_String the_match = S8_Make(string.str + match.pos, match.size);
|
|
||||||
if (before_match.len) S8_AddNode(arena, &result, before_match);
|
|
||||||
if (flags & S8_SplitFlag_SplitInclusive) {
|
|
||||||
if (the_match.len) S8_AddNode(arena, &result, the_match);
|
|
||||||
}
|
|
||||||
string = S8_Skip(string, match.pos + match.size);
|
|
||||||
}
|
|
||||||
S8_AddNode(arena, &result, string);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_API S8_List OS_ListDirRegex(MA_Arena *arena, S8_String path, unsigned flags, char *regex) {
|
|
||||||
S8_List result = S8_MakeEmptyList();
|
|
||||||
|
|
||||||
char buff[4096];
|
|
||||||
RE_Regex *re = RE1_Parse(buff, sizeof(buff), regex);
|
|
||||||
S8_List files = OS_ListDir(arena, path, flags);
|
|
||||||
for (S8_Node *it = files.first; it; it = it->next) {
|
|
||||||
if (RE3_AreEqual(re, it->string.str, it->string.len)) {
|
|
||||||
S8_AddNode(arena, &result, it->string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_API S8_String OS_ListDirRegexAsString(MA_Arena *arena, S8_String path, unsigned flags, char *regex) {
|
|
||||||
S8_List files = OS_ListDirRegex(arena, path, flags, regex);
|
|
||||||
S8_String files_str = S8_MergeWithSeparator(arena, files, S8_Lit(" "));
|
|
||||||
return files_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath) {
|
OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath) {
|
||||||
S8_String c = OS_ReadFile(arena, filepath);
|
S8_String c = OS_ReadFile(arena, filepath);
|
||||||
if (c.str == 0) return false;
|
if (c.str == 0) return false;
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct OS_Date OS_Date;
|
|
||||||
|
|
||||||
typedef enum OS_Result {
|
typedef enum OS_Result {
|
||||||
OS_SUCCESS,
|
OS_SUCCESS,
|
||||||
OS_ALREADY_EXISTS,
|
OS_ALREADY_EXISTS,
|
||||||
@@ -23,6 +21,7 @@ enum {
|
|||||||
OS_RELATIVE_PATHS = 2,
|
OS_RELATIVE_PATHS = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct OS_Date OS_Date;
|
||||||
struct OS_Date {
|
struct OS_Date {
|
||||||
uint32_t year;
|
uint32_t year;
|
||||||
uint32_t month;
|
uint32_t month;
|
||||||
@@ -33,6 +32,22 @@ struct OS_Date {
|
|||||||
uint32_t milliseconds;
|
uint32_t milliseconds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct OS_FileIter OS_FileIter;
|
||||||
|
struct OS_FileIter {
|
||||||
|
bool is_valid;
|
||||||
|
bool is_directory;
|
||||||
|
S8_String absolute_path;
|
||||||
|
S8_String relative_path;
|
||||||
|
S8_String filename;
|
||||||
|
|
||||||
|
S8_String path;
|
||||||
|
MA_Arena *arena;
|
||||||
|
union {
|
||||||
|
struct OS_Win32_FileIter *w32;
|
||||||
|
void *dir;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
OS_API bool OS_IsAbsolute(S8_String path);
|
OS_API bool OS_IsAbsolute(S8_String path);
|
||||||
OS_API S8_String OS_GetExePath(MA_Arena *arena);
|
OS_API S8_String OS_GetExePath(MA_Arena *arena);
|
||||||
OS_API S8_String OS_GetExeDir(MA_Arena *arena);
|
OS_API S8_String OS_GetExeDir(MA_Arena *arena);
|
||||||
@@ -43,7 +58,6 @@ OS_API bool OS_FileExists(S8_String path);
|
|||||||
OS_API bool OS_IsDir(S8_String path);
|
OS_API bool OS_IsDir(S8_String path);
|
||||||
OS_API bool OS_IsFile(S8_String path);
|
OS_API bool OS_IsFile(S8_String path);
|
||||||
OS_API double OS_GetTime(void);
|
OS_API double OS_GetTime(void);
|
||||||
OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags); // @todo: this is poor API, we want absolute, relative, bool dir
|
|
||||||
OS_API OS_Result OS_MakeDir(S8_String path);
|
OS_API OS_Result OS_MakeDir(S8_String path);
|
||||||
OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite);
|
OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite);
|
||||||
OS_API OS_Result OS_DeleteFile(S8_String path);
|
OS_API OS_Result OS_DeleteFile(S8_String path);
|
||||||
@@ -55,9 +69,10 @@ OS_API int OS_SystemF(const char *string, ...);
|
|||||||
OS_API int64_t OS_GetFileModTime(S8_String file);
|
OS_API int64_t OS_GetFileModTime(S8_String file);
|
||||||
OS_API OS_Date OS_GetDate(void);
|
OS_API OS_Date OS_GetDate(void);
|
||||||
OS_API S8_String UTF_CreateStringFromWidechar(MA_Arena *arena, wchar_t *wstr, int64_t wsize);
|
OS_API S8_String UTF_CreateStringFromWidechar(MA_Arena *arena, wchar_t *wstr, int64_t wsize);
|
||||||
OS_API S8_List S8_SplitOnRegex(MA_Arena *arena, S8_String string, S8_String regex, unsigned flags);
|
|
||||||
OS_API S8_List OS_ListDirRegex(MA_Arena *arena, S8_String path, unsigned flags, char *regex);
|
|
||||||
OS_API S8_String OS_ListDirRegexAsString(MA_Arena *arena, S8_String path, unsigned flags, char *regex);
|
|
||||||
OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath);
|
OS_API bool OS_ExpandIncludesList(MA_Arena *arena, S8_List *out, S8_String filepath);
|
||||||
OS_API S8_String OS_ExpandIncludes(MA_Arena *arena, S8_String filepath);
|
OS_API S8_String OS_ExpandIncludes(MA_Arena *arena, S8_String filepath);
|
||||||
OS_API bool OS_EnableTerminalColors(void);
|
OS_API bool OS_EnableTerminalColors(void);
|
||||||
|
|
||||||
|
OS_API bool OS_IsValid(OS_FileIter it);
|
||||||
|
OS_API void OS_Advance(OS_FileIter *it);
|
||||||
|
OS_API OS_FileIter OS_IterateFiles(MA_Arena *scratch_arena, S8_String path);
|
||||||
@@ -111,6 +111,15 @@ S8_API S8_String S8_Copy(S8_Allocator allocator, S8_String string) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S8_API S8_String S8_CopyChar(S8_Allocator allocator, char *s) {
|
||||||
|
int64_t len = S8_Length(s);
|
||||||
|
char *copy = (char *)S8_ALLOCATE(allocator, sizeof(char) * (len + 1));
|
||||||
|
S8_MemoryCopy(copy, s, len);
|
||||||
|
copy[len] = 0;
|
||||||
|
S8_String result = S8_Make(copy, len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
S8_API void S8_NormalizePath(S8_String s) {
|
S8_API void S8_NormalizePath(S8_String s) {
|
||||||
for (int64_t i = 0; i < s.len; i++) {
|
for (int64_t i = 0; i < s.len; i++) {
|
||||||
if (s.str[i] == '\\')
|
if (s.str[i] == '\\')
|
||||||
@@ -169,7 +178,7 @@ S8_API S8_String S8_GetPrefix(S8_String string, int64_t len) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
S8_API S8_String S8_GetNameNoExtension(S8_String s) {
|
S8_API S8_String S8_GetNameNoExt(S8_String s) {
|
||||||
return S8_SkipToLastSlash(S8_ChopLastPeriod(s));
|
return S8_SkipToLastSlash(S8_ChopLastPeriod(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,19 +32,6 @@ struct S8_String {
|
|||||||
int64_t len;
|
int64_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
// #ifdef __cplusplus
|
|
||||||
// struct String : S8_String {
|
|
||||||
// String() = default;
|
|
||||||
// String(char *s) : S8_String{s, S8_Length(s)} {}
|
|
||||||
// String(char *s, int64_t l) : S8_String{s, l} {}
|
|
||||||
// String(const char *s) : S8_String{(char *)s, S8_Length((char *)s)} {}
|
|
||||||
// String(const char *s, int64_t l) : S8_String{(char *)s, l} {}
|
|
||||||
// String(S8_String s) : S8_String{s.str, s.len} {}
|
|
||||||
|
|
||||||
// // @todo add unicode iterator
|
|
||||||
// };
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
struct S8_Node {
|
struct S8_Node {
|
||||||
S8_Node *next;
|
S8_Node *next;
|
||||||
S8_String string;
|
S8_String string;
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
#include "../core_library/core.c"
|
#include "../core_library/core.c"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
MA_Scratch scratch;
|
||||||
|
for (OS_FileIter it = OS_IterateFiles(scratch, "../"_s); OS_IsValid(it); OS_Advance(&it)) {
|
||||||
|
IO_Printf("is_directory: %d\n", it.is_directory);
|
||||||
|
IO_Printf("absolute_path: %.*s\n", S8_Expand(it.absolute_path));
|
||||||
|
IO_Printf("relative_path: %.*s\n", S8_Expand(it.relative_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -74,28 +74,4 @@ int main() {
|
|||||||
IO_Assert(S8_Find(abs_path, S8_Lit("/tests/data"), 0, 0));
|
IO_Assert(S8_Find(abs_path, S8_Lit("/tests/data"), 0, 0));
|
||||||
IO_Assert(!S8_Find(abs_path, S8_Lit("../"), 0, 0));
|
IO_Assert(!S8_Find(abs_path, S8_Lit("../"), 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// List dir test
|
|
||||||
{
|
|
||||||
S8_List list = OS_ListDir(&arena, S8_Lit("../tests"), 0);
|
|
||||||
IO_Assert(list.node_count > 4);
|
|
||||||
int dir_count = 0;
|
|
||||||
S8_For(it, list) {
|
|
||||||
if (OS_IsDir(it->string)) {
|
|
||||||
IO_Assert(it->string.str[it->string.len - 1] == '/');
|
|
||||||
dir_count += 1;
|
|
||||||
}
|
|
||||||
IO_Assert(S8_Find(it->string, S8_Lit("/tests"), 0, 0));
|
|
||||||
IO_Assert(!S8_Find(it->string, S8_Lit("../tests"), 0, 0));
|
|
||||||
}
|
|
||||||
IO_Assert(dir_count > 0);
|
|
||||||
|
|
||||||
// relative
|
|
||||||
{
|
|
||||||
S8_List list = OS_ListDir(&arena, S8_Lit("../tests"), OS_RELATIVE_PATHS);
|
|
||||||
S8_For(it, list) {
|
|
||||||
IO_Assert(S8_Find(it->string, S8_Lit("../tests"), 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user