sanity tests, path handling, file lister update and began working on saving files
This commit is contained in:
parent
c68cb80ca4
commit
bb9c9b3e26
|
@ -34,6 +34,11 @@ cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial
|
||||||
|
|
||||||
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||||
|
|
||||||
|
REM COMPILE AND RUN TESTS
|
||||||
|
cl %CommonCompilerFlags% %ProjectDevPath%\src\tests\sanity_tests.cpp /Fesanity_tests.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib
|
||||||
|
|
||||||
|
sanity_tests.exe
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
call %MyPath%\_postbuild_win32.bat
|
call %MyPath%\_postbuild_win32.bat
|
|
@ -126,7 +126,9 @@ BlumenLumen_CustomInit(app_state* State, context Context)
|
||||||
BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue;
|
BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue;
|
||||||
BLState->MicListenJobData.ListenSocket = CreateSocket(Context.SocketManager, "127.0.0.1", "20185");
|
BLState->MicListenJobData.ListenSocket = CreateSocket(Context.SocketManager, "127.0.0.1", "20185");
|
||||||
|
|
||||||
|
#if 0
|
||||||
BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData);
|
BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData);
|
||||||
|
#endif
|
||||||
|
|
||||||
gs_const_string SculpturePath = ConstString("data/test_blumen.fold");
|
gs_const_string SculpturePath = ConstString("data/test_blumen.fold");
|
||||||
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
|
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
|
||||||
|
|
|
@ -792,6 +792,29 @@ TimeRange_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
AnimInfoView_SaveAnimFile (gs_const_string Path, app_state* State, context Context)
|
||||||
|
{
|
||||||
|
u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex;
|
||||||
|
animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex];
|
||||||
|
|
||||||
|
gs_string FileText = AnimSerializer_Serialize(ActiveAnimation, State->Patterns, State->Transient);
|
||||||
|
|
||||||
|
if (!WriteEntireFile(Context.ThreadContext.FileHandler, Path, StringToData(FileText)))
|
||||||
|
{
|
||||||
|
InvalidCodePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PANEL_MODAL_OVERRIDE_CALLBACK(AnimInfoView_SaveAnimFileCallback)
|
||||||
|
{
|
||||||
|
Assert(ReturningFrom->TypeIndex == PanelType_FileView);
|
||||||
|
file_view_state* FileViewState = Panel_GetStateStruct(ReturningFrom, file_view_state);
|
||||||
|
gs_file_info FileInfo = FileViewState->SelectedFile;
|
||||||
|
|
||||||
|
AnimInfoView_SaveAnimFile(FileInfo.Path, State, Context);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Panel, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||||
{
|
{
|
||||||
|
@ -833,10 +856,14 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel
|
||||||
// need to use the file browser to create a file
|
// need to use the file browser to create a file
|
||||||
u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex;
|
u32 ActiveAnimIndex = State->AnimationSystem.ActiveAnimationIndex;
|
||||||
animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex];
|
animation ActiveAnimation = State->AnimationSystem.Animations.Values[ActiveAnimIndex];
|
||||||
gs_string FileText = AnimSerializer_Serialize(ActiveAnimation, State->Patterns, State->Transient);
|
|
||||||
if (WriteEntireFile(Context.ThreadContext.FileHandler, ActiveAnimation.FileInfo.Path, StringToData(FileText)))
|
if (!ActiveAnimation.FileInfo.Path.Str)
|
||||||
{
|
{
|
||||||
InvalidCodePath;
|
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
||||||
|
FileView_SetMode(FileBrowser, FileViewMode_Save);
|
||||||
|
Panel_PushModalOverride(Panel, FileBrowser, AnimInfoView_SaveAnimFileCallback);
|
||||||
|
} else {
|
||||||
|
AnimInfoView_SaveAnimFile(ActiveAnimation.FileInfo.Path, State, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ui_Button(Interface, MakeString("Load")))
|
if (ui_Button(Interface, MakeString("Load")))
|
||||||
|
|
|
@ -49,30 +49,31 @@ s32 FileView_CommandsCount = 0;
|
||||||
internal void
|
internal void
|
||||||
FileView_UpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context)
|
FileView_UpdateWorkingDirectory(gs_const_string WorkingDirectory, file_view_state* State, context Context)
|
||||||
{
|
{
|
||||||
|
// NOTE(pjs): make sure we're only passing valid directory paths to the
|
||||||
|
// function
|
||||||
|
char LastChar = WorkingDirectory.Str[WorkingDirectory.Length - 1];
|
||||||
|
Assert(LastChar == '\\' || LastChar == '/');
|
||||||
ClearArena(&State->FileNamesArena);
|
ClearArena(&State->FileNamesArena);
|
||||||
|
|
||||||
gs_const_string SanitizedDirectory = WorkingDirectory;
|
gs_string SanitizedDir = PushString(Context.ThreadContext.Transient, WorkingDirectory.Length + 2);
|
||||||
|
SanitizePath(WorkingDirectory, &SanitizedDir, Context.ThreadContext.Transient);
|
||||||
u32 LastSlashIndex = FindLast(SanitizedDirectory, '\\');
|
if (SanitizedDir.Str[SanitizedDir.Length - 1] != '\\')
|
||||||
gs_const_string LastDir = Substring(SanitizedDirectory, LastSlashIndex + 1, SanitizedDirectory.Length);
|
|
||||||
if (StringsEqual(LastDir, ConstString("..")))
|
|
||||||
{
|
{
|
||||||
u32 SecondLastSlashIndex = FindLast(SanitizedDirectory, LastSlashIndex - 1, '\\');
|
AppendPrintF(&SanitizedDir, "\\");
|
||||||
SanitizedDirectory = Substring(SanitizedDirectory, 0, SecondLastSlashIndex);
|
|
||||||
}
|
|
||||||
else if (StringsEqual(LastDir, ConstString(".")) && LastDir.Length > 1)
|
|
||||||
{
|
|
||||||
SanitizedDirectory = Substring(SanitizedDirectory, 0, LastSlashIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gs_file_info NewWorkingDirectory = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDirectory);
|
gs_file_info NewWorkingDir = GetFileInfo(Context.ThreadContext.FileHandler, SanitizedDir.ConstString);
|
||||||
if (NewWorkingDirectory.IsDirectory)
|
if (NewWorkingDir.IsDirectory)
|
||||||
{
|
{
|
||||||
|
AppendPrintF(&SanitizedDir, "*");
|
||||||
|
NullTerminate(&SanitizedDir);
|
||||||
|
|
||||||
|
State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, SanitizedDir.ConstString, EnumerateDirectory_IncludeDirectories);
|
||||||
|
|
||||||
// NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory
|
// NOTE(pjs): we might be printing from State->WorkingDirectory to State->WorkingDirectory
|
||||||
// in some cases. Shouldn't be a problem but it is unnecessary
|
// in some cases. Shouldn't be a problem but it is unnecessary
|
||||||
PrintF(&State->WorkingDirectory, "%S", WorkingDirectory);
|
PrintF(&State->WorkingDirectory, "%S", SanitizedDir.ConstString);
|
||||||
|
|
||||||
State->FileNames = EnumerateDirectory(Context.ThreadContext.FileHandler, &State->FileNamesArena, State->WorkingDirectory.ConstString, EnumerateDirectory_IncludeDirectories);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ FileView_Init(panel* Panel, app_state* State, context Context)
|
||||||
|
|
||||||
// TODO(pjs): this shouldn't be stored in permanent
|
// TODO(pjs): this shouldn't be stored in permanent
|
||||||
FileViewState->WorkingDirectory = PushString(&State->Permanent, 256);
|
FileViewState->WorkingDirectory = PushString(&State->Permanent, 256);
|
||||||
FileView_UpdateWorkingDirectory(ConstString("."), FileViewState, Context);
|
FileView_UpdateWorkingDirectory(ConstString(".\\"), FileViewState, Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSMetaTag(panel_cleanup);
|
GSMetaTag(panel_cleanup);
|
||||||
|
@ -105,14 +106,26 @@ internal void
|
||||||
FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBuffer, app_state* State, context Context)
|
||||||
{
|
{
|
||||||
file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state);
|
file_view_state* FileViewState = Panel_GetStateStruct(Panel, file_view_state);
|
||||||
Assert(FileViewState->Mode == FileViewMode_Save);
|
|
||||||
|
|
||||||
ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout"));
|
ui_PushLayout(&State->Interface, PanelBounds, LayoutDirection_TopDown, MakeString("FileView Layout"));
|
||||||
{
|
{
|
||||||
|
|
||||||
|
ui_BeginRow(&State->Interface, 3);
|
||||||
|
{
|
||||||
|
if (FileViewState->Mode == FileViewMode_Save)
|
||||||
|
{
|
||||||
|
if (ui_Button(&State->Interface, MakeString("Save")))
|
||||||
|
{
|
||||||
|
FileView_Exit_(Panel, State, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ui_Button(&State->Interface, MakeString("Exit")))
|
if (ui_Button(&State->Interface, MakeString("Exit")))
|
||||||
{
|
{
|
||||||
FileView_Exit_(Panel, State, Context);
|
FileView_Exit_(Panel, State, Context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ui_EndRow(&State->Interface);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->WorkingDirectory))
|
if (ui_TextEntry(&State->Interface, MakeString("pwd"), &FileViewState->WorkingDirectory))
|
||||||
|
@ -137,7 +150,7 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu
|
||||||
{
|
{
|
||||||
gs_file_info File = FileViewState->FileNames.Values[i];
|
gs_file_info File = FileViewState->FileNames.Values[i];
|
||||||
|
|
||||||
u32 LastSlashIndex = FindLast(File.Path, '\\');
|
u32 LastSlashIndex = FindLast(File.Path, File.Path.Length - 2, '\\');
|
||||||
gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length);
|
gs_const_string FileName = Substring(File.Path, LastSlashIndex + 1, File.Path.Length);
|
||||||
gs_string PathString = PushString(State->Transient, FileName.Length);
|
gs_string PathString = PushString(State->Transient, FileName.Length);
|
||||||
PrintF(&PathString, "%S", FileName);
|
PrintF(&PathString, "%S", FileName);
|
||||||
|
@ -149,9 +162,20 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu
|
||||||
FileView_UpdateWorkingDirectory(File.Path, FileViewState, Context);
|
FileView_UpdateWorkingDirectory(File.Path, FileViewState, Context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
switch (FileViewState->Mode)
|
||||||
{
|
{
|
||||||
FileViewState->SelectedFile = File;
|
FileViewState->SelectedFile = File;
|
||||||
|
case FileViewMode_Load:
|
||||||
|
{
|
||||||
FileView_Exit_(Panel, State, Context);
|
FileView_Exit_(Panel, State, Context);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case FileViewMode_Save:
|
||||||
|
{
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ HierarchyView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* Ren
|
||||||
if (ui_Button(&State->Interface, MakeString("+ Add Assembly")))
|
if (ui_Button(&State->Interface, MakeString("+ Add Assembly")))
|
||||||
{
|
{
|
||||||
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
panel* FileBrowser = PanelSystem_PushPanel(&State->PanelSystem, PanelType_FileView, State, Context);
|
||||||
FileView_SetMode(FileBrowser, FileViewMode_Save);
|
FileView_SetMode(FileBrowser, FileViewMode_Load);
|
||||||
Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback);
|
Panel_PushModalOverride(Panel, FileBrowser, LoadAssemblyCallback);
|
||||||
}
|
}
|
||||||
ui_EndRow(&State->Interface);
|
ui_EndRow(&State->Interface);
|
||||||
|
|
|
@ -57,7 +57,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
State->LedSystem = LedSystem_Create(Context.ThreadContext.Allocator, 128);
|
State->LedSystem = LedSystem_Create(Context.ThreadContext.Allocator, 128);
|
||||||
State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent);
|
State->AssemblyDebugState = AssemblyDebug_Create(&State->Permanent);
|
||||||
State->AssemblyDebugState.Brightness = 255;
|
State->AssemblyDebugState.Brightness = 255;
|
||||||
State->AssemblyDebugState.Override = ADS_Override_AllBlue;
|
State->AssemblyDebugState.Override = ADS_Override_None;
|
||||||
|
|
||||||
GlobalDebugServices->Interface.RenderSculpture = true;
|
GlobalDebugServices->Interface.RenderSculpture = true;
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
Panel_SetType(Profiler, &State->PanelSystem, PanelType_ProfilerView, State, Context);
|
Panel_SetType(Profiler, &State->PanelSystem, PanelType_ProfilerView, State, Context);
|
||||||
|
|
||||||
panel* Hierarchy = LeftPanel->Left;
|
panel* Hierarchy = LeftPanel->Left;
|
||||||
Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_HierarchyView, State, Context);
|
Panel_SetType(Hierarchy, &State->PanelSystem, PanelType_AssemblyDebug, State, Context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "..\gs_libs\gs_types.h"
|
#include "..\gs_libs\gs_types.h"
|
||||||
#include "..\gs_libs\gs_types.cpp"
|
#include "..\gs_libs\gs_types.cpp"
|
||||||
|
#include "..\gs_libs\gs_path.h"
|
||||||
|
|
||||||
struct handle
|
struct handle
|
||||||
{
|
{
|
||||||
|
|
|
@ -523,6 +523,8 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "../../gs_libs/gs_path.h"
|
||||||
|
|
||||||
int WINAPI
|
int WINAPI
|
||||||
WinMain (
|
WinMain (
|
||||||
HINSTANCE HInstance,
|
HINSTANCE HInstance,
|
||||||
|
@ -533,6 +535,11 @@ WinMain (
|
||||||
{
|
{
|
||||||
gs_thread_context ThreadContext = Win32CreateThreadContext();
|
gs_thread_context ThreadContext = Win32CreateThreadContext();
|
||||||
|
|
||||||
|
gs_file_info A = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium"));
|
||||||
|
|
||||||
|
gs_file_info B = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium\\"));
|
||||||
|
|
||||||
|
|
||||||
if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1;
|
if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1;
|
||||||
|
|
||||||
MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
|
MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
|
||||||
|
@ -629,7 +636,7 @@ WinMain (
|
||||||
|
|
||||||
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
|
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
|
||||||
|
|
||||||
bool Multithread = false;
|
bool Multithread = true;
|
||||||
if (Multithread)
|
if (Multithread)
|
||||||
{
|
{
|
||||||
for (addressed_data_buffer* At = OutputData.Root;
|
for (addressed_data_buffer* At = OutputData.Root;
|
||||||
|
|
|
@ -178,28 +178,39 @@ Win32SetFileInfoFromFindFileData(gs_file_info* Info, WIN32_FIND_DATA FindFileDat
|
||||||
{
|
{
|
||||||
u32 FileNameLength = CharArrayLength(FindFileData.cFileName);
|
u32 FileNameLength = CharArrayLength(FindFileData.cFileName);
|
||||||
|
|
||||||
// NOTE(Peter): String Storage
|
|
||||||
// Storing the string in the final storage means we don't have to copy the string later, and all
|
|
||||||
// strings will be continguous in memory at the calling site, though they will be before the array
|
|
||||||
gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 1);
|
|
||||||
PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName);
|
|
||||||
NullTerminate(&FileName);
|
|
||||||
|
|
||||||
Info->FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh);
|
Info->FileSize = Win32HighLowToU64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh);
|
||||||
Info->CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime);
|
Info->CreationTime = Win32FileTimeToU64(FindFileData.ftCreationTime);
|
||||||
Info->LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime);
|
Info->LastWriteTime = Win32FileTimeToU64(FindFileData.ftLastWriteTime);
|
||||||
Info->Path = FileName.ConstString;
|
|
||||||
Info->IsDirectory = HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
Info->IsDirectory = HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
|
// NOTE(Peter): String Storage
|
||||||
|
// Storing the string in the final storage means we don't have to copy the string later, and all
|
||||||
|
// strings will be continguous in memory at the calling site, though they will be before the array
|
||||||
|
gs_string FileName = PushString(Storage, SearchPath.Length + FileNameLength + 2);
|
||||||
|
PrintF(&FileName, "%S%.*s", SearchPath, FileName.Size, FindFileData.cFileName);
|
||||||
|
if (Info->IsDirectory)
|
||||||
|
{
|
||||||
|
AppendPrintF(&FileName, "\\");
|
||||||
|
}
|
||||||
|
NullTerminate(&FileName);
|
||||||
|
|
||||||
|
Info->Path = FileName.ConstString;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u32
|
internal u32
|
||||||
Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags)
|
Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list* TempList, gs_const_string Path, gs_memory_arena* Storage, b32 Flags)
|
||||||
{
|
{
|
||||||
u32 FilesCount = 0;
|
u32 FilesCount = 0;
|
||||||
|
Assert(Path.Str[Path.Length - 1] != '\\' &&
|
||||||
|
Path.Str[Path.Length - 1] != '/');
|
||||||
|
gs_const_string SearchPath = Path;
|
||||||
|
|
||||||
s64 IndexOfLastSlash = FindLastFromSet(Path, "\\/");
|
gs_const_string SearchPathDir = SearchPath;
|
||||||
Assert(IndexOfLastSlash >= 0);
|
s64 LastSlash = FindLastFromSet(SearchPath, "\\/");
|
||||||
gs_const_string SearchPath = Substring(Path, 0, IndexOfLastSlash + 1);
|
if (LastSlash >= 0)
|
||||||
|
{
|
||||||
|
SearchPathDir = Substring(SearchPath, 0, LastSlash + 1);
|
||||||
|
}
|
||||||
|
|
||||||
WIN32_FIND_DATA FindFileData;
|
WIN32_FIND_DATA FindFileData;
|
||||||
HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData);
|
HANDLE SearchHandle = FindFirstFile(Path.Str, &FindFileData);
|
||||||
|
@ -211,15 +222,18 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list*
|
||||||
|
|
||||||
if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
|
if (HasFlag(FindFileData.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
|
||||||
{
|
{
|
||||||
|
gs_const_string SubDirName = ConstString(FindFileData.cFileName);
|
||||||
|
bool IsNav = (StringsEqual(SubDirName, ConstString(".")) ||
|
||||||
|
StringsEqual(SubDirName, ConstString("..")));
|
||||||
|
|
||||||
if (HasFlag(Flags, EnumerateDirectory_Recurse))
|
if (HasFlag(Flags, EnumerateDirectory_Recurse))
|
||||||
{
|
{
|
||||||
gs_const_string SubDirName = ConstString(FindFileData.cFileName);
|
if (!IsNav)
|
||||||
if (!StringsEqual(SubDirName, ConstString(".")) &&
|
|
||||||
!StringsEqual(SubDirName, ConstString("..")))
|
|
||||||
{
|
{
|
||||||
gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3);
|
gs_string SubDirectoryPath = PushString(FileHandler.Transient, SearchPath.Length + SubDirName.Length + 3);
|
||||||
PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName);
|
PrintF(&SubDirectoryPath, "%S%S/*\0", SearchPath, SubDirName);
|
||||||
FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString, Storage, Flags);
|
FilesCount += Win32EnumerateDirectoryIntoTempList(FileHandler, TempList, SubDirectoryPath.ConstString,
|
||||||
|
Storage, Flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +244,7 @@ Win32EnumerateDirectoryIntoTempList(gs_file_handler FileHandler, temp_file_list*
|
||||||
{
|
{
|
||||||
temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry);
|
temp_file_list_entry* File = PushStruct(FileHandler.Transient, temp_file_list_entry);
|
||||||
*File = {0};
|
*File = {0};
|
||||||
Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPath, Storage);
|
Win32SetFileInfoFromFindFileData(&File->Info, FindFileData, SearchPathDir, Storage);
|
||||||
SLLPushOrInit(TempList->First, TempList->Last, File);
|
SLLPushOrInit(TempList->First, TempList->Last, File);
|
||||||
FilesCount += 1;
|
FilesCount += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,11 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
|
||||||
// ie. the usb stick was removed
|
// ie. the usb stick was removed
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
{
|
||||||
|
// ??
|
||||||
|
}break;
|
||||||
|
|
||||||
case ERROR_INVALID_HANDLE:
|
case ERROR_INVALID_HANDLE:
|
||||||
InvalidDefaultCase;
|
InvalidDefaultCase;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// File: gs_path.h
|
||||||
|
// Author: Peter Slattery
|
||||||
|
// Creation Date: 2021-03-06
|
||||||
|
//
|
||||||
|
#ifndef GS_PATH_H
|
||||||
|
|
||||||
|
internal gs_const_string
|
||||||
|
ClearString()
|
||||||
|
{
|
||||||
|
gs_const_string R = {};
|
||||||
|
R.Str = 0;
|
||||||
|
R.Length = 0;
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
SanitizePath (gs_const_string Path, gs_string* Dest, gs_memory_arena* Scratch)
|
||||||
|
{
|
||||||
|
Dest->Length = 0;
|
||||||
|
|
||||||
|
// Put all slashes in the same format
|
||||||
|
s32 SlashCount = 0;
|
||||||
|
for (u64 i = 0; i < Path.Length; i++)
|
||||||
|
{
|
||||||
|
char At = Path.Str[i];
|
||||||
|
if (At == '\\' || At == '/') {
|
||||||
|
SlashCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we add one to slash count in case the last element is a file or
|
||||||
|
// doesn't end in a slash (even if it should)
|
||||||
|
u32 PathEleCountMax = SlashCount + 1;
|
||||||
|
u32 PathEleCount = 0;
|
||||||
|
gs_const_string* PathEle = PushArray(Scratch, gs_const_string, PathEleCountMax);
|
||||||
|
|
||||||
|
u64 OnePastLastEleEnd = 0;
|
||||||
|
for (s64 i = 0; i < (s64)Path.Length; i++)
|
||||||
|
{
|
||||||
|
char At = Path.Str[i];
|
||||||
|
if (At == '\\' || At == '/')
|
||||||
|
{
|
||||||
|
gs_const_string* NewEle = PathEle + PathEleCount++;
|
||||||
|
*NewEle = Substring(Path, OnePastLastEleEnd, i + 1);
|
||||||
|
OnePastLastEleEnd = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OnePastLastEleEnd != Path.Length)
|
||||||
|
{
|
||||||
|
gs_const_string* NewEle = PathEle + PathEleCount++;
|
||||||
|
*NewEle = Substring(Path, OnePastLastEleEnd, Path.Length);
|
||||||
|
OnePastLastEleEnd = Path.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove redundant elements
|
||||||
|
for (u32 i = 0; i < PathEleCount; i++)
|
||||||
|
{
|
||||||
|
gs_const_string* At = PathEle + i;
|
||||||
|
bool ShouldRemove = false;
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
if (StringsEqual(*At, ConstString(".\\")) ||
|
||||||
|
StringsEqual(*At, ConstString("./")))
|
||||||
|
{
|
||||||
|
*At = ClearString();
|
||||||
|
}
|
||||||
|
else if (StringsEqual(*At, ConstString("..\\")) ||
|
||||||
|
StringsEqual(*At, ConstString("../")))
|
||||||
|
{
|
||||||
|
PathEle[i - 1] = ClearString();
|
||||||
|
if (i != 1) {
|
||||||
|
PathEle[i] = ClearString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < PathEleCount; i++)
|
||||||
|
{
|
||||||
|
if (PathEle[i].Str) {
|
||||||
|
AppendPrintF(Dest, "%S", PathEle[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put all slashes in the same format
|
||||||
|
for (u64 i = 0; i < Dest->Length; i++)
|
||||||
|
{
|
||||||
|
if (Dest->Str[i] == '/') {
|
||||||
|
Dest->Str[i] = '\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal gs_const_string
|
||||||
|
SanitizePath (gs_const_string Path, gs_memory_arena* Scratch)
|
||||||
|
{
|
||||||
|
gs_string Result = PushString(Scratch, Path.Length);
|
||||||
|
SanitizePath(Path, &Result, Scratch);
|
||||||
|
return Result.ConstString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define GS_PATH_H
|
||||||
|
#endif // GS_PATH_H
|
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// File: gs_tests.h
|
||||||
|
// Author: Peter Slattery
|
||||||
|
// Creation Date: 2021-03-06
|
||||||
|
//
|
||||||
|
#ifndef GS_TESTS_H
|
||||||
|
|
||||||
|
int CStringLen(char* Str)
|
||||||
|
{
|
||||||
|
char* At = Str;
|
||||||
|
while (*At != 0) { At++; }
|
||||||
|
int Result = At - Str;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct test_ctx
|
||||||
|
{
|
||||||
|
int TestsCount;
|
||||||
|
int TestsPassedCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static test_ctx TestCtx = {0};
|
||||||
|
|
||||||
|
static void
|
||||||
|
BeginTest(char* Name)
|
||||||
|
{
|
||||||
|
int Length = CStringLen(Name);
|
||||||
|
int Spaces = 25 - Length;
|
||||||
|
if(Spaces < 0)
|
||||||
|
{
|
||||||
|
Spaces = 0;
|
||||||
|
}
|
||||||
|
printf("\"%s\" %.*s [", Name, Spaces, "------------------------------");
|
||||||
|
TestCtx.TestsCount = 0;
|
||||||
|
TestCtx.TestsPassedCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TestResult(bool Result)
|
||||||
|
{
|
||||||
|
TestCtx.TestsCount += 1;
|
||||||
|
if (Result) {
|
||||||
|
TestCtx.TestsPassedCount += 1;
|
||||||
|
}
|
||||||
|
printf(Result ? "." : "X");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
EndTest(void)
|
||||||
|
{
|
||||||
|
int Spaces = 10 - TestCtx.TestsCount;
|
||||||
|
if(Spaces < 0) { Spaces = 0; }
|
||||||
|
printf("]%.*s ", Spaces, " ");
|
||||||
|
printf("[%i/%i] %i passed, %i tests, ",
|
||||||
|
TestCtx.TestsPassedCount, TestCtx.TestsCount,
|
||||||
|
TestCtx.TestsPassedCount, TestCtx.TestsCount);
|
||||||
|
if(TestCtx.TestsCount == TestCtx.TestsPassedCount)
|
||||||
|
{
|
||||||
|
printf("SUCCESS ( )");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("FAILED (X)");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Test(name) for(int _i_ = (BeginTest(name), 0); !_i_; _i_ += 1, EndTest())
|
||||||
|
|
||||||
|
|
||||||
|
#define GS_TESTS_H
|
||||||
|
#endif // GS_TESTS_H
|
|
@ -191,7 +191,7 @@ int main(int ArgCount, char** Args)
|
||||||
u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) };
|
u32 BloomInnerChannels[] = { FSC(0, 0), FSC(0, 1), FSC(0, 2), FSC(0, 3), FSC(0, 4), FSC(0, 5) };
|
||||||
flower_desc F0 = {};
|
flower_desc F0 = {};
|
||||||
F0.Pos = v3{-1, 0, 0};
|
F0.Pos = v3{-1, 0, 0};
|
||||||
F0.ComPort = "\\\\.\\COM4";
|
F0.ComPort = "\\\\.\\COM11";
|
||||||
F0.FlowerTagValue = "left";
|
F0.FlowerTagValue = "left";
|
||||||
F0.StemChannels = StemChannels;
|
F0.StemChannels = StemChannels;
|
||||||
F0.BloomOuterChannels = BloomOuterChannels;
|
F0.BloomOuterChannels = BloomOuterChannels;
|
||||||
|
@ -200,7 +200,7 @@ int main(int ArgCount, char** Args)
|
||||||
|
|
||||||
flower_desc F1 = {};
|
flower_desc F1 = {};
|
||||||
F1.Pos = v3{0, 0, 0};
|
F1.Pos = v3{0, 0, 0};
|
||||||
F1.ComPort = "\\\\.\\COM5";
|
F1.ComPort = "\\\\.\\COM12";
|
||||||
F1.FlowerTagValue = "center";
|
F1.FlowerTagValue = "center";
|
||||||
F1.StemChannels = StemChannels;
|
F1.StemChannels = StemChannels;
|
||||||
F1.BloomInnerChannels = BloomInnerChannels;
|
F1.BloomInnerChannels = BloomInnerChannels;
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// File: sanity_tests.cpp
|
||||||
|
// Author: Peter Slattery
|
||||||
|
// Creation Date: 2021-03-06
|
||||||
|
//
|
||||||
|
#ifndef SANITY_TESTS_CPP
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../gs_libs/gs_types.h"
|
||||||
|
#include "../gs_libs/gs_types.cpp"
|
||||||
|
#include "../gs_libs/gs_tests.h"
|
||||||
|
|
||||||
|
#include "../gs_libs/gs_path.h"
|
||||||
|
|
||||||
|
gs_memory_arena Scratch = {};
|
||||||
|
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
|
||||||
|
void Free(void* Ptr, u64 Size) { return free(Ptr); }
|
||||||
|
|
||||||
|
bool PathTest (char* In, char* Out) {
|
||||||
|
return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int ArgCount, char** Args)
|
||||||
|
{
|
||||||
|
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free));
|
||||||
|
|
||||||
|
Test("gs_path.h")
|
||||||
|
{
|
||||||
|
TestResult(PathTest(".", "."));
|
||||||
|
TestResult(PathTest(".\\", ".\\"));
|
||||||
|
TestResult(PathTest("./", ".\\"));
|
||||||
|
TestResult(PathTest("./../", "..\\"));
|
||||||
|
TestResult(PathTest("C:/users/pslattery\\test.foo", "C:\\users\\pslattery\\test.foo"));
|
||||||
|
TestResult(PathTest("./test/../foo.bar", ".\\foo.bar"));
|
||||||
|
TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define SANITY_TESTS_CPP
|
||||||
|
#endif // SANITY_TESTS_CPP
|
Loading…
Reference in New Issue