sanity tests, path handling, file lister update and began working on saving files

This commit is contained in:
Peter Slattery 2021-03-06 18:17:00 -08:00
parent c68cb80ca4
commit bb9c9b3e26
14 changed files with 353 additions and 47 deletions

View File

@ -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

View File

@ -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);

View File

@ -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")))

View File

@ -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"));
{ {
if (ui_Button(&State->Interface, MakeString("Exit")))
ui_BeginRow(&State->Interface, 3);
{ {
FileView_Exit_(Panel, State, Context); if (FileViewState->Mode == FileViewMode_Save)
{
if (ui_Button(&State->Interface, MakeString("Save")))
{
FileView_Exit_(Panel, State, Context);
}
}
if (ui_Button(&State->Interface, MakeString("Exit")))
{
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);
@ -150,8 +163,19 @@ FileView_Render(panel* Panel, rect2 PanelBounds, render_command_buffer* RenderBu
} }
else else
{ {
FileViewState->SelectedFile = File; switch (FileViewState->Mode)
FileView_Exit_(Panel, State, Context); {
FileViewState->SelectedFile = File;
case FileViewMode_Load:
{
FileView_Exit_(Panel, State, Context);
} break;
case FileViewMode_Save:
{
} break;
}
} }
} }
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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
{ {

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }

106
src/gs_libs/gs_path.h Normal file
View File

@ -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

72
src/gs_libs/gs_tests.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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