diff --git a/build.bat b/build.bat index 308ef81..acbf959 100644 --- a/build.bat +++ b/build.bat @@ -3,6 +3,6 @@ call ../misc/compile_setup.bat mkdir build cd build -cl -Fe:bld.exe ../build_tool/build_main.cpp -WX -W3 -wd4200 -diagnostics:column -nologo -Zi -D_CRT_SECURE_NO_WARNINGS +cl -Fe:bld.exe ../build_tool/build_main.cpp -FC -WX -W3 -wd4200 -diagnostics:column -nologo -Zi -D_CRT_SECURE_NO_WARNINGS cd .. build\bld.exe diff --git a/build_file.cpp b/build_file.cpp index 47ff140..ea645a3 100644 --- a/build_file.cpp +++ b/build_file.cpp @@ -8,7 +8,7 @@ int Main() { Strs files = ListDir("../tests"); CompileFiles(cc, {"../tests/main_core_as_header.cpp", "../core_library/core.c"}); For(files) { - if (S8_Find(it, "test_"_s, 0, 0)) { + if (S8_Find(it, "test_"_s)) { CompileFiles(cc, it); } } diff --git a/build_tool/build_lib.cpp b/build_tool/build_lib.cpp index 918ee49..38fd2e6 100644 --- a/build_tool/build_lib.cpp +++ b/build_tool/build_lib.cpp @@ -43,134 +43,11 @@ DEBUG = -fsanitize=address #define AND_CL_STRING_TERMINATE_ON_NEW_LINE #include "../standalone_libraries/clexer.c" -#define SRC_CACHE_ENTRY_COUNT 1024 -struct SRC_CacheEntry { - uint64_t filepath_hash; - uint64_t file_hash; - uint64_t includes_hash; - uint64_t total_hash; -}; - -struct SRC_Cache { - int entry_cap; - int entry_len; - SRC_CacheEntry entries[SRC_CACHE_ENTRY_COUNT]; -}; - -double SRC_Time; -SRC_Cache *SRC_InMemoryCache; -SRC_Cache *SRC_FromFileCache; -CL_ArenaTuple SRC_ArenaTuple; -S8_String SRC_CacheFilename; MA_Arena PernamentArena; MA_Arena *Perm = &PernamentArena; -CL_SearchPaths SRC_SearchPaths = {}; // @todo; Table CMDLine; -void SRC_InitCache(MA_Arena *arena, S8_String cachefilename) { - SRC_CacheFilename = cachefilename; - CL_InitDefaultTuple(&SRC_ArenaTuple); - - SRC_InMemoryCache = MA_PushStruct(arena, SRC_Cache); - SRC_InMemoryCache->entry_cap = SRC_CACHE_ENTRY_COUNT; - - SRC_FromFileCache = MA_PushStruct(arena, SRC_Cache); - SRC_FromFileCache->entry_cap = SRC_CACHE_ENTRY_COUNT; - - S8_String cache = OS_ReadFile(arena, SRC_CacheFilename); - if (cache.len) MA_MemoryCopy(SRC_FromFileCache, cache.str, cache.len); -} - -void SRC_SaveCache() { - S8_String dump = S8_Make((char *)SRC_InMemoryCache, sizeof(SRC_Cache)); - OS_WriteFile(SRC_CacheFilename, dump); -} - -SRC_CacheEntry *SRC_AddHash(uint64_t filepath, uint64_t file, uint64_t includes) { - IO_Assert(SRC_InMemoryCache->entry_len + 1 < SRC_InMemoryCache->entry_cap); - SRC_CacheEntry *result = SRC_InMemoryCache->entries + SRC_InMemoryCache->entry_len++; - result->filepath_hash = filepath; - result->file_hash = file; - result->includes_hash = includes; - result->total_hash = HashBytes(result, sizeof(uint64_t) * 3); - return result; -} - -SRC_CacheEntry *SRC_FindCache(SRC_Cache *cache, uint64_t filepath_hash) { - for (int cache_i = 0; cache_i < cache->entry_len; cache_i += 1) { - SRC_CacheEntry *it = cache->entries + cache_i; - if (it->filepath_hash == filepath_hash) { - return it; - } - } - return 0; -} - -SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) { - char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false); - if (!resolved_file) { - IO_Printf("Failed to resolve file: %s\n", file.str); - return 0; - } - - uint64_t filepath_hash = HashBytes(resolved_file, S8_Length(resolved_file)); - SRC_CacheEntry *entry = SRC_FindCache(SRC_InMemoryCache, filepath_hash); - if (entry) return entry; - - CL_LexResult *first_lex = CL_LexFile(&SRC_ArenaTuple, resolved_file); - IO_Assert(first_lex); - uint64_t file_hash = HashBytes(first_lex->stream_begin, first_lex->stream - first_lex->stream_begin); - uint64_t includes_hash = 13; - - CL_LexList list = CL_MakeLexList(first_lex); - for (CL_IncludeIter iter = CL_IterateIncludes(&list); iter.filename; CL_GetNextInclude(&iter)) { - if (iter.is_system_include) continue; - - S8_String file_it = S8_MakeFromChar(iter.filename); - SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file); - if (!cache) { - IO_Printf("Missing cache for: %s\n", file_it.str); - continue; - } - - includes_hash = HashMix(includes_hash, cache->total_hash); - } - - SRC_CacheEntry *result = SRC_AddHash(filepath_hash, file_hash, includes_hash); - return result; -} - -bool SRC_WasModified(S8_String file, S8_String artifact_path) { - double time_start = OS_GetTime(); - - if (OS_FileExists(file) == false) { - IO_Printf("FAILED File doesnt exist: %.*s\n", S8_Expand(file)); - exit(0); - } - if (OS_IsAbsolute(file) == false) { - file = OS_GetAbsolutePath(Perm, file); - } - - S8_String without_ext = S8_ChopLastPeriod(file); - S8_String name_only = S8_SkipToLastSlash(without_ext); - - if (artifact_path.len == 0) artifact_path = S8_Format(Perm, "%.*s.%s", S8_Expand(name_only), IF_WINDOWS_ELSE("obj", "o")); - bool modified = OS_FileExists(artifact_path) == false; - - SRC_CacheEntry *in_memory = SRC_HashFile(file, 0); - IO_Assert(in_memory); - - if (modified == false) { - SRC_CacheEntry *from_file = SRC_FindCache(SRC_FromFileCache, in_memory->filepath_hash); - if (from_file == 0 || (in_memory->total_hash != from_file->total_hash)) { - modified = true; - } - } - - SRC_Time = SRC_Time + (OS_GetTime() - time_start); - - return modified; -} +#include "cache.c" // // diff --git a/build_tool/build_main.cpp b/build_tool/build_main.cpp index 1403519..a709944 100644 --- a/build_tool/build_main.cpp +++ b/build_tool/build_main.cpp @@ -28,7 +28,7 @@ int main(int argument_count, char **arguments) { { S8_List files_current_dir = OS_ListDir(Perm, S8_Lit(".."), 0); for (S8_Node *it = files_current_dir.first; it; it = it->next) { - if (S8_Find(it->string, S8_Lit("build_file.c"), S8_IGNORE_CASE, 0)) { + if (S8_Find(it->string, S8_Lit("build_file.c"), S8_IgnoreCase)) { build_file = it->string; } } diff --git a/build_tool/cache.c b/build_tool/cache.c new file mode 100644 index 0000000..bf1ad75 --- /dev/null +++ b/build_tool/cache.c @@ -0,0 +1,126 @@ + +#define SRC_CACHE_ENTRY_COUNT 1024 +struct SRC_CacheEntry { + uint64_t filepath_hash; + uint64_t file_hash; + uint64_t includes_hash; + uint64_t total_hash; +}; + +struct SRC_Cache { + int entry_cap; + int entry_len; + SRC_CacheEntry entries[SRC_CACHE_ENTRY_COUNT]; +}; + +double SRC_Time; +SRC_Cache *SRC_InMemoryCache; +SRC_Cache *SRC_FromFileCache; +CL_ArenaTuple SRC_ArenaTuple; +S8_String SRC_CacheFilename; +CL_SearchPaths SRC_SearchPaths = {}; // @todo; + +void SRC_InitCache(MA_Arena *arena, S8_String cachefilename) { + SRC_CacheFilename = cachefilename; + CL_InitDefaultTuple(&SRC_ArenaTuple); + + SRC_InMemoryCache = MA_PushStruct(arena, SRC_Cache); + SRC_InMemoryCache->entry_cap = SRC_CACHE_ENTRY_COUNT; + + SRC_FromFileCache = MA_PushStruct(arena, SRC_Cache); + SRC_FromFileCache->entry_cap = SRC_CACHE_ENTRY_COUNT; + + S8_String cache = OS_ReadFile(arena, SRC_CacheFilename); + if (cache.len) MA_MemoryCopy(SRC_FromFileCache, cache.str, cache.len); +} + +void SRC_SaveCache() { + S8_String dump = S8_Make((char *)SRC_InMemoryCache, sizeof(SRC_Cache)); + OS_WriteFile(SRC_CacheFilename, dump); +} + +SRC_CacheEntry *SRC_AddHash(uint64_t filepath, uint64_t file, uint64_t includes) { + IO_Assert(SRC_InMemoryCache->entry_len + 1 < SRC_InMemoryCache->entry_cap); + SRC_CacheEntry *result = SRC_InMemoryCache->entries + SRC_InMemoryCache->entry_len++; + result->filepath_hash = filepath; + result->file_hash = file; + result->includes_hash = includes; + result->total_hash = HashBytes(result, sizeof(uint64_t) * 3); + return result; +} + +SRC_CacheEntry *SRC_FindCache(SRC_Cache *cache, uint64_t filepath_hash) { + for (int cache_i = 0; cache_i < cache->entry_len; cache_i += 1) { + SRC_CacheEntry *it = cache->entries + cache_i; + if (it->filepath_hash == filepath_hash) { + return it; + } + } + return 0; +} + +SRC_CacheEntry *SRC_HashFile(S8_String file, char *parent_file) { + char *resolved_file = CL_ResolveFilepath(Perm, &SRC_SearchPaths, file.str, parent_file, false); + if (!resolved_file) { + IO_Printf("Failed to resolve file: %s\n", file.str); + return 0; + } + + uint64_t filepath_hash = HashBytes(resolved_file, S8_Length(resolved_file)); + SRC_CacheEntry *entry = SRC_FindCache(SRC_InMemoryCache, filepath_hash); + if (entry) return entry; + + CL_LexResult *first_lex = CL_LexFile(&SRC_ArenaTuple, resolved_file); + IO_Assert(first_lex); + uint64_t file_hash = HashBytes(first_lex->stream_begin, first_lex->stream - first_lex->stream_begin); + uint64_t includes_hash = 13; + + CL_LexList list = CL_MakeLexList(first_lex); + for (CL_IncludeIter iter = CL_IterateIncludes(&list); iter.filename; CL_GetNextInclude(&iter)) { + if (iter.is_system_include) continue; + + S8_String file_it = S8_MakeFromChar(iter.filename); + SRC_CacheEntry *cache = SRC_HashFile(file_it, resolved_file); + if (!cache) { + IO_Printf("Missing cache for: %s\n", file_it.str); + continue; + } + + includes_hash = HashMix(includes_hash, cache->total_hash); + } + + SRC_CacheEntry *result = SRC_AddHash(filepath_hash, file_hash, includes_hash); + return result; +} + +bool SRC_WasModified(S8_String file, S8_String artifact_path) { + double time_start = OS_GetTime(); + + if (OS_FileExists(file) == false) { + IO_Printf("FAILED File doesnt exist: %.*s\n", S8_Expand(file)); + exit(0); + } + if (OS_IsAbsolute(file) == false) { + file = OS_GetAbsolutePath(Perm, file); + } + + S8_String without_ext = S8_ChopLastPeriod(file); + S8_String name_only = S8_SkipToLastSlash(without_ext); + + if (artifact_path.len == 0) artifact_path = S8_Format(Perm, "%.*s.%s", S8_Expand(name_only), IF_WINDOWS_ELSE("obj", "o")); + bool modified = OS_FileExists(artifact_path) == false; + + SRC_CacheEntry *in_memory = SRC_HashFile(file, 0); + IO_Assert(in_memory); + + if (modified == false) { + SRC_CacheEntry *from_file = SRC_FindCache(SRC_FromFileCache, in_memory->filepath_hash); + if (from_file == 0 || (in_memory->total_hash != from_file->total_hash)) { + modified = true; + } + } + + SRC_Time = SRC_Time + (OS_GetTime() - time_start); + + return modified; +} \ No newline at end of file diff --git a/core_library/core.c b/core_library/core.c index a3629b4..16fcf68 100644 --- a/core_library/core.c +++ b/core_library/core.c @@ -1,5 +1,19 @@ -#include "core.h" +/* +@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, + - also add String Arrays and String Builder, temp allocators hook ins for nicer api + - Iterating over unicode codepoints using For +- Redesign clexer because the Arena Tuple is hella weird + - Maybe remove token array stuff, do standard stream thing, then you need one arena ... + - Add filter stuff so we can get includes / comments / normal tokens etc. +*/ +#include "core.h" #define STB_SPRINTF_IMPLEMENTATION #include "../standalone_libraries/stb_sprintf.h" #define IO_VSNPRINTF stbsp_vsnprintf @@ -20,3 +34,7 @@ #include "../standalone_libraries/hash.c" #include "../standalone_libraries/load_library.c" #include "filesystem.c" + +// #if LANG_CPP +// #include "string.cpp" +// #endif \ No newline at end of file diff --git a/core_library/core.h b/core_library/core.h index 343ec26..a50bb14 100644 --- a/core_library/core.h +++ b/core_library/core.h @@ -12,7 +12,7 @@ #include "../standalone_libraries/load_library.h" #include "filesystem.h" -#ifdef __cplusplus +#if LANG_CPP #include "../standalone_libraries/defer.hpp" #define TABLE_ASSERT IO_Assert #define TABLE_Allocator M_Allocator @@ -28,4 +28,5 @@ #define ARRAY_SET_DEFAULT_ALLOCATOR \ if (!allocator.p) allocator = M_GetSystemAllocator(); #include "../standalone_libraries/array.hpp" +// #include "string.hpp" #endif diff --git a/core_library/filesystem.c b/core_library/filesystem.c index 24f5c76..6c17798 100644 --- a/core_library/filesystem.c +++ b/core_library/filesystem.c @@ -1,7 +1,3 @@ -#include "filesystem.h" - -#define OS_LENGTHOF(x) ((int64_t)((sizeof(x) / sizeof((x)[0])))) - #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX @@ -47,7 +43,7 @@ OS_API bool OS_IsAbsolute(S8_String path) { OS_API S8_String OS_GetExePath(MA_Arena *arena) { wchar_t wbuffer[1024]; - DWORD wsize = GetModuleFileNameW(0, wbuffer, OS_LENGTHOF(wbuffer)); + DWORD wsize = GetModuleFileNameW(0, wbuffer, MA_LENGTHOF(wbuffer)); IO_Assert(wsize != 0); S8_String path = UTF_CreateStringFromWidechar(arena, wbuffer, wsize); @@ -64,7 +60,7 @@ OS_API S8_String OS_GetExeDir(MA_Arena *arena) { OS_API S8_String OS_GetWorkingDir(MA_Arena *arena) { wchar_t wbuffer[1024]; - DWORD wsize = GetCurrentDirectoryW(OS_LENGTHOF(wbuffer), wbuffer); + DWORD wsize = GetCurrentDirectoryW(MA_LENGTHOF(wbuffer), wbuffer); IO_Assert(wsize != 0); IO_Assert(wsize < 1022); wbuffer[wsize++] = '/'; @@ -77,15 +73,15 @@ OS_API S8_String OS_GetWorkingDir(MA_Arena *arena) { OS_API void OS_SetWorkingDir(S8_String path) { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); SetCurrentDirectoryW(wpath); } OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative) { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), relative.str, relative.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), relative.str, relative.len); wchar_t wpath_abs[1024]; - DWORD written = GetFullPathNameW((wchar_t *)wpath, OS_LENGTHOF(wpath_abs), wpath_abs, 0); + DWORD written = GetFullPathNameW((wchar_t *)wpath, MA_LENGTHOF(wpath_abs), wpath_abs, 0); if (written == 0) return S8_MakeEmpty(); S8_String path = UTF_CreateStringFromWidechar(arena, wpath_abs, written); @@ -95,7 +91,7 @@ OS_API S8_String OS_GetAbsolutePath(MA_Arena *arena, S8_String relative) { OS_API bool OS_FileExists(S8_String path) { wchar_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, OS_LENGTHOF(wbuff), path.str, path.len); + UTF_CreateWidecharFromChar(wbuff, MA_LENGTHOF(wbuff), path.str, path.len); DWORD attribs = GetFileAttributesW(wbuff); bool result = attribs == INVALID_FILE_ATTRIBUTES ? false : true; return result; @@ -103,14 +99,14 @@ OS_API bool OS_FileExists(S8_String path) { OS_API bool OS_IsDir(S8_String path) { wchar_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, OS_LENGTHOF(wbuff), path.str, path.len); + UTF_CreateWidecharFromChar(wbuff, MA_LENGTHOF(wbuff), path.str, path.len); DWORD dwAttrib = GetFileAttributesW(wbuff); return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } OS_API bool OS_IsFile(S8_String path) { wchar_t wbuff[1024]; - UTF_CreateWidecharFromChar(wbuff, OS_LENGTHOF(wbuff), path.str, path.len); + UTF_CreateWidecharFromChar(wbuff, MA_LENGTHOF(wbuff), path.str, path.len); DWORD dwAttrib = GetFileAttributesW(wbuff); bool is_file = (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0; return dwAttrib != INVALID_FILE_ATTRIBUTES && is_file; @@ -143,8 +139,8 @@ OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) { for (S8_Node *it = dirs_to_read.first; it; it = it->next) { 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 < OS_LENGTHOF(wbuff)); - int64_t wsize = UTF_CreateWidecharFromChar(wbuff, OS_LENGTHOF(wbuff), modified_path.str, modified_path.len); + 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; @@ -197,7 +193,7 @@ OS_API S8_List OS_ListDir(MA_Arena *arena, S8_String path, unsigned flags) { OS_API OS_Result OS_MakeDir(S8_String path) { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); BOOL success = CreateDirectoryW(wpath, NULL); OS_Result result = OS_SUCCESS; if (success == 0) { @@ -217,10 +213,10 @@ OS_API OS_Result OS_MakeDir(S8_String path) { OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite) { wchar_t wfrom[1024]; - UTF_CreateWidecharFromChar(wfrom, OS_LENGTHOF(wfrom), from.str, from.len); + UTF_CreateWidecharFromChar(wfrom, MA_LENGTHOF(wfrom), from.str, from.len); wchar_t wto[1024]; - UTF_CreateWidecharFromChar(wto, OS_LENGTHOF(wto), to.str, to.len); + UTF_CreateWidecharFromChar(wto, MA_LENGTHOF(wto), to.str, to.len); BOOL fail_if_exists = !overwrite; BOOL success = CopyFileW(wfrom, wto, fail_if_exists); @@ -233,7 +229,7 @@ OS_API OS_Result OS_CopyFile(S8_String from, S8_String to, bool overwrite) { OS_API OS_Result OS_DeleteFile(S8_String path) { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); BOOL success = DeleteFileW(wpath); OS_Result result = OS_SUCCESS; if (success == 0) @@ -247,7 +243,7 @@ OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) { S8_List list = OS_ListDir(scratch.arena, path, OS_RECURSIVE); S8_Node *dirs_to_remove = 0; for (S8_Node *it = list.first; it; it = it->next) { - if (!S8_EndsWith(it->string, S8_Lit("/"), S8_IGNORE_CASE)) { + if (!S8_EndsWith(it->string, S8_Lit("/"), S8_IgnoreCase)) { OS_DeleteFile(it->string); } else { @@ -264,7 +260,7 @@ OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) { } else { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); BOOL success = RemoveDirectoryW(wpath); OS_Result result = OS_SUCCESS; if (success == 0) @@ -275,7 +271,7 @@ OS_API OS_Result OS_DeleteDir(S8_String path, unsigned flags) { static OS_Result OS__WriteFile(S8_String path, S8_String data, bool append) { wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); OS_Result result = OS_FAILURE; DWORD access = GENERIC_WRITE; @@ -316,7 +312,7 @@ OS_API S8_String OS_ReadFile(MA_Arena *arena, S8_String path) { MA_Checkpoint checkpoint = MA_Save(arena); wchar_t wpath[1024]; - UTF_CreateWidecharFromChar(wpath, OS_LENGTHOF(wpath), path.str, path.len); + UTF_CreateWidecharFromChar(wpath, MA_LENGTHOF(wpath), path.str, path.len); HANDLE handle = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handle != INVALID_HANDLE_VALUE) { LARGE_INTEGER file_size; @@ -680,7 +676,7 @@ OS_API S8_List S8_SplitOnRegex(MA_Arena *arena, S8_String string, S8_String rege 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_SPLIT_INCLUSIVE) { + if (flags & S8_SplitFlag_SplitInclusive) { if (the_match.len) S8_AddNode(arena, &result, the_match); } string = S8_Skip(string, match.pos + match.size); diff --git a/core_library/filesystem.h b/core_library/filesystem.h index 08aa283..f0ab35b 100644 --- a/core_library/filesystem.h +++ b/core_library/filesystem.h @@ -1,4 +1,3 @@ -#pragma once // Quick and dirty filesystem operations #ifndef OS_API diff --git a/standalone_libraries/string.c b/standalone_libraries/string.c index fa921f4..ae1138f 100644 --- a/standalone_libraries/string.c +++ b/standalone_libraries/string.c @@ -74,7 +74,7 @@ S8_API bool S8_AreEqual(S8_String a, S8_String b, unsigned ignore_case) { for (int64_t i = 0; i < a.len; i++) { char A = a.str[i]; char B = b.str[i]; - if (ignore_case & S8_IGNORE_CASE) { + if (ignore_case) { A = CHAR_ToLowerCase(A); B = CHAR_ToLowerCase(B); } @@ -169,6 +169,10 @@ S8_API S8_String S8_GetPrefix(S8_String string, int64_t len) { return result; } +S8_API S8_String S8_GetNameNoExtension(S8_String s) { + return S8_SkipToLastSlash(S8_ChopLastPeriod(s)); +} + S8_API S8_String S8_Slice(S8_String string, int64_t first_index, int64_t one_past_last_index) { if (one_past_last_index < 0) one_past_last_index = string.len + one_past_last_index + 1; if (first_index < 0) first_index = string.len + first_index; @@ -245,13 +249,14 @@ S8_API S8_String S8_ToUpperCase(S8_Allocator allocator, S8_String s) { return copy; } -S8_API bool S8_Find(S8_String string, S8_String find, unsigned flags, int64_t *index_out) { +S8_API bool S8_Find(S8_String string, S8_String find, S8_FindFlag flags, int64_t *index_out) { + bool ignore_case = flags & S8_FindFlag_IgnoreCase ? true : false; bool result = false; - if (flags & S8_MATCH_FIND_LAST) { + if (flags & S8_FindFlag_MatchFindLast) { for (int64_t i = string.len; i != 0; i--) { int64_t index = i - 1; S8_String substring = S8_Slice(string, index, index + find.len); - if (S8_AreEqual(substring, find, flags)) { + if (S8_AreEqual(substring, find, ignore_case)) { if (index_out) *index_out = index; result = true; @@ -262,7 +267,7 @@ S8_API bool S8_Find(S8_String string, S8_String find, unsigned flags, int64_t *i else { for (int64_t i = 0; i < string.len; i++) { S8_String substring = S8_Slice(string, i, i + find.len); - if (S8_AreEqual(substring, find, flags)) { + if (S8_AreEqual(substring, find, ignore_case)) { if (index_out) *index_out = i; result = true; @@ -274,14 +279,15 @@ S8_API bool S8_Find(S8_String string, S8_String find, unsigned flags, int64_t *i return result; } -S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, unsigned flags) { - S8_ASSERT((flags & S8_MATCH_FIND_LAST) == 0); +S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, S8_SplitFlag flags) { S8_List result = S8_MakeEmptyList(); int64_t index = 0; - while (S8_Find(string, find, flags, &index)) { + + S8_FindFlag find_flag = flags & S8_SplitFlag_IgnoreCase ? S8_FindFlag_IgnoreCase : S8_FindFlag_None; + while (S8_Find(string, find, find_flag, &index)) { S8_String before_match = S8_Make(string.str, index); S8_AddNode(allocator, &result, before_match); - if (flags & S8_SPLIT_INCLUSIVE) { + if (flags & S8_SplitFlag_SplitInclusive) { S8_String match = S8_Make(string.str + index, find.len); S8_AddNode(allocator, &result, match); } @@ -294,7 +300,7 @@ S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find S8_API S8_String S8_MergeWithSeparator(S8_Allocator allocator, S8_List list, S8_String separator) { if (list.node_count == 0) return S8_MakeEmpty(); if (list.char_count == 0) return S8_MakeEmpty(); - // S8_ASSERT((flags & S8_MATCH_FIND_LAST) == 0); + int64_t base_size = (list.char_count + 1); int64_t sep_size = (list.node_count - 1) * separator.len; int64_t size = base_size + sep_size; @@ -318,11 +324,11 @@ S8_API S8_String S8_Merge(S8_Allocator allocator, S8_List list) { return S8_MergeWithSeparator(allocator, list, S8_Lit("")); } -S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, unsigned flags) { - S8_ASSERT((flags & S8_MATCH_FIND_LAST) == 0); - S8_List list = S8_Split(allocator, string, replace, flags | S8_SPLIT_INCLUSIVE); +S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, bool ignore_case) { + S8_SplitFlag split_flag = ignore_case ? S8_SplitFlag_IgnoreCase : S8_SplitFlag_None; + S8_List list = S8_Split(allocator, string, replace, split_flag | S8_SplitFlag_SplitInclusive); for (S8_Node *it = list.first; it; it = it->next) { - if (S8_AreEqual(it->string, replace, flags)) { + if (S8_AreEqual(it->string, replace, ignore_case)) { S8_ReplaceNodeString(&list, it, with); } } @@ -330,11 +336,12 @@ S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_Stri return result; } -S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, unsigned flags) { // @untested - S8_ASSERT((flags & S8_MATCH_FIND_LAST) == 0); +S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, bool ignore_case) { // @untested S8_List result = S8_MakeEmptyList(); int64_t index = 0; - while (S8_Find(string, find, flags, &index)) { + + S8_FindFlag find_flag = ignore_case ? S8_FindFlag_IgnoreCase : 0; + while (S8_Find(string, find, find_flag, &index)) { S8_String match = S8_Make(string.str + index, find.len); S8_AddNode(allocator, &result, match); string = S8_Skip(string, index + find.len); @@ -344,20 +351,20 @@ S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String fi S8_API S8_String S8_ChopLastSlash(S8_String s) { S8_String result = s; - S8_Find(s, S8_Lit("/"), S8_MATCH_FIND_LAST, &result.len); + S8_Find(s, S8_Lit("/"), S8_FindFlag_MatchFindLast, &result.len); return result; } S8_API S8_String S8_ChopLastPeriod(S8_String s) { S8_String result = s; - S8_Find(s, S8_Lit("."), S8_MATCH_FIND_LAST, &result.len); + S8_Find(s, S8_Lit("."), S8_FindFlag_MatchFindLast, &result.len); return result; } S8_API S8_String S8_SkipToLastSlash(S8_String s) { int64_t pos; S8_String result = s; - if (S8_Find(s, S8_Lit("/"), S8_MATCH_FIND_LAST, &pos)) { + if (S8_Find(s, S8_Lit("/"), S8_FindFlag_MatchFindLast, &pos)) { result = S8_Skip(result, pos + 1); } return result; @@ -366,7 +373,7 @@ S8_API S8_String S8_SkipToLastSlash(S8_String s) { S8_API S8_String S8_SkipToLastPeriod(S8_String s) { int64_t pos; S8_String result = s; - if (S8_Find(s, S8_Lit("."), S8_MATCH_FIND_LAST, &pos)) { + if (S8_Find(s, S8_Lit("."), S8_FindFlag_MatchFindLast, &pos)) { result = S8_Skip(result, pos + 1); } return result; diff --git a/standalone_libraries/string.h b/standalone_libraries/string.h index 375bdc2..0e811b4 100644 --- a/standalone_libraries/string.h +++ b/standalone_libraries/string.h @@ -11,6 +11,12 @@ #endif #endif +#ifdef __cplusplus + #define S8_IF_CPP(x) x +#else + #define S8_IF_CPP(x) +#endif + #ifndef S8_Allocator struct MA_Arena; #define S8_Allocator MA_Arena * @@ -19,12 +25,26 @@ struct MA_Arena; typedef struct S8_String S8_String; typedef struct S8_Node S8_Node; typedef struct S8_List S8_List; +S8_API int64_t S8_Length(char *string); struct S8_String { char *str; 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 { S8_Node *next; S8_String string; @@ -37,11 +57,20 @@ struct S8_List { S8_Node *last; }; +const int S8_IgnoreCase = true; + +typedef int S8_FindFlag; enum { - S8_NO_FLAGS = 0, - S8_IGNORE_CASE = 1, - S8_SPLIT_INCLUSIVE = 4, - S8_MATCH_FIND_LAST = 32, + S8_FindFlag_None = 0, + S8_FindFlag_IgnoreCase = 1, + S8_FindFlag_MatchFindLast = 2, +}; + +typedef int S8_SplitFlag; +enum { + S8_SplitFlag_None = 0, + S8_SplitFlag_IgnoreCase = 1, + S8_SplitFlag_SplitInclusive = 2, }; #if defined(__has_attribute) @@ -80,9 +109,9 @@ S8_API bool CHAR_IsAlphabetic(char a); S8_API bool CHAR_IsIdent(char a); S8_API bool CHAR_IsDigit(char a); S8_API bool CHAR_IsAlphanumeric(char a); -S8_API bool S8_AreEqual(S8_String a, S8_String b, unsigned ignore_case); -S8_API bool S8_EndsWith(S8_String a, S8_String end, unsigned ignore_case); -S8_API bool S8_StartsWith(S8_String a, S8_String start, unsigned ignore_case); +S8_API bool S8_AreEqual(S8_String a, S8_String b, unsigned ignore_case S8_IF_CPP(= false)); +S8_API bool S8_EndsWith(S8_String a, S8_String end, unsigned ignore_case S8_IF_CPP(= false)); +S8_API bool S8_StartsWith(S8_String a, S8_String start, unsigned ignore_case S8_IF_CPP(= false)); S8_API S8_String S8_Make(char *str, int64_t len); S8_API S8_String S8_Copy(S8_Allocator allocator, S8_String string); S8_API void S8_NormalizePath(S8_String s); @@ -95,26 +124,28 @@ S8_API S8_String S8_Trim(S8_String string); S8_API S8_String S8_TrimEnd(S8_String string); S8_API S8_String S8_ToLowerCase(S8_Allocator allocator, S8_String s); S8_API S8_String S8_ToUpperCase(S8_Allocator allocator, S8_String s); -S8_API bool S8_Find(S8_String string, S8_String find, unsigned flags, int64_t *index_out); -S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, unsigned flags); -S8_API S8_String S8_MergeWithSeparator(S8_Allocator allocator, S8_List list, S8_String separator); -S8_API S8_String S8_Merge(S8_Allocator allocator, S8_List list); -S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, unsigned flags); -S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, unsigned flags); +S8_API bool S8_Find(S8_String string, S8_String find, S8_FindFlag flags S8_IF_CPP(= S8_FindFlag_None), int64_t *index_out S8_IF_CPP(= 0)); S8_API S8_String S8_ChopLastSlash(S8_String s); S8_API S8_String S8_ChopLastPeriod(S8_String s); S8_API S8_String S8_SkipToLastSlash(S8_String s); S8_API S8_String S8_SkipToLastPeriod(S8_String s); +S8_API S8_String S8_GetNameNoExt(S8_String s); S8_API bool S8_IsPointerInside(S8_String string, char *p); S8_API S8_String S8_SkipToP(S8_String string, char *p); S8_API S8_String S8_SkipPast(S8_String string, S8_String a); -S8_API int64_t S8_Length(char *string); S8_API int64_t S8_WideLength(wchar_t *string); S8_API S8_String S8_MakeFromChar(char *string); S8_API S8_String S8_MakeEmpty(void); S8_API S8_List S8_MakeEmptyList(void); S8_API S8_String S8_FormatV(S8_Allocator allocator, const char *str, va_list args1); S8_API S8_String S8_Format(S8_Allocator allocator, const char *str, ...) S8__PrintfFormat(2, 3); + +S8_API S8_List S8_Split(S8_Allocator allocator, S8_String string, S8_String find, S8_SplitFlag flags S8_IF_CPP(= S8_SplitFlag_None)); +S8_API S8_String S8_MergeWithSeparator(S8_Allocator allocator, S8_List list, S8_String separator S8_IF_CPP(= " "_s)); +S8_API S8_String S8_Merge(S8_Allocator allocator, S8_List list); +S8_API S8_String S8_ReplaceAll(S8_Allocator allocator, S8_String string, S8_String replace, S8_String with, bool ignore_case S8_IF_CPP(= false)); +S8_API S8_List S8_FindAll(S8_Allocator allocator, S8_String string, S8_String find, bool ignore_case S8_IF_CPP(= false)); + S8_API S8_Node *S8_CreateNode(S8_Allocator allocator, S8_String string); S8_API void S8_ReplaceNodeString(S8_List *list, S8_Node *node, S8_String new_string); S8_API void S8_AddExistingNode(S8_List *list, S8_Node *node); diff --git a/tests/1test_string.cpp b/tests/1test_string.cpp new file mode 100644 index 0000000..7330dd2 --- /dev/null +++ b/tests/1test_string.cpp @@ -0,0 +1,4 @@ +#include "../core_library/core.c" + +int main() { +} \ No newline at end of file