From b843937295d92d003bf8b9fbd57a738a1127d6d1 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 21 Mar 2020 22:44:44 -0700 Subject: [PATCH] Refactored rect functionality of gs_vector_matrix to make it not conflict with windows headers (just added gs_ to all functions). refactored Profiler interface code to use the new interface layout system. --- gs_libs/gs_string.h | 4389 ++++++++--------- gs_libs/gs_vector_matrix.h | 318 +- src/assembly_parser.cpp | 3 +- src/foldhaus_app.cpp | 48 +- src/foldhaus_interface.cpp | 24 +- src/interface.h | 75 +- .../foldhaus_panel_animation_timeline.h | 44 +- src/panels/foldhaus_panel_file_view.h | 6 +- src/panels/foldhaus_panel_hierarchy.h | 2 +- src/panels/foldhaus_panel_node_graph.h | 38 +- src/panels/foldhaus_panel_profiler.h | 191 +- todo.txt | 84 +- 12 files changed, 2643 insertions(+), 2579 deletions(-) diff --git a/gs_libs/gs_string.h b/gs_libs/gs_string.h index 8fb9ac8..1f335a4 100644 --- a/gs_libs/gs_string.h +++ b/gs_libs/gs_string.h @@ -7,7 +7,7 @@ #include //////////////////////////////////////////////////////////////// -// String +// String //////////////////////////////////////////////////////////////// struct string @@ -151,8 +151,8 @@ struct contiguous_slot_count_result #if !defined GS_LANGUAGE_H static void GSZeroMemory (u8* Memory, s32 Size); -static s32 GSMin (s32 A, s32 B); -static s32 GSAbs (s32 A); +static s32 GSMin (s32 A, s32 B); +static s32 GSAbs (s32 A); static float GSAbsF (float A); static float GSPowF (float N, s32 Power); @@ -224,2207 +224,2206 @@ static b32 CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckF // String -#define MakeStringBuffer(name, size) \ -char name##Backbuffer[(size)]; \ -string name = MakeString(name##Backbuffer, size); - - static string MakeString (char* Array, s32 Length, s32 Max); - static string MakeString (char* Array, s32 Length); - static string MakeString (char* Array); - static string MakeStringLiteral(char* Data); - - static bool StringsEqual (string A, string B); - static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); - static bool StringEqualsCharArray (string String, char* CharArray); - static s32 FindFirstChar (string String, char C); - - static void SetStringToChar (string* Dest, char C, s32 Count); - static void SetStringToCharArray (string* Dest, char* Source); - - static void ConcatString (string Source, string* Dest); - static void ConcatString (string Source, s32 Length, string* Dest); - static void ConcatCharToString(string* Dest, char C); - static void ConcatCharArrayToString (char* Source, string* Dest); - static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); - - static void CopyStringTo (string Source, string* Dest); - static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); - static void CopyCharArrayToString (char* Src, string* Dest); - static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); - static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); - static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); - - static void InsertChar (string* String, char Char, s32 Index); - static void InsertStringAt (string* Dest, string Source, s32 At); - static void RemoveCharAt (string* String, s32 Index); - - static s32 IndexOfChar(string String, char C); - static s32 LastIndexOfChar(string String, char C); - static s32 SearchForCharInSet(string String, char* Set); - static s32 ReverseSearchForCharInSet(string String, char* Set); - static string Substring (string* String, s32 Start, s32 End); - static string Substring (string* String, s32 Start); - - static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); - static b32 StringContainsString(string SearchIn, string SearchFor); - static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); - static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); - - static void NullTerminate (string* String); - - static u32 HashString(string String); - - // Parsing - enum parse_type - { - ParseType_UnsignedInt, - ParseType_SignedInt, - ParseType_Float, - }; - - struct parse_result - { - parse_type Type; - char* OnePastLast; - union - { - u32 UnsignedIntValue; - s32 SignedIntValue; - r32 FloatValue; - }; - }; - - enum format_flags - { - FormatFlags_LeftJustify = 0x1, - FormatFlags_ForceSign = 0x2, - FormatFlags_ForceSpaceInsteadOfSign = 0x4, - FormatFlags_ForceDecimalOrPrependOx = 0x8, - FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, - }; - - static parse_result ParseUnsignedInt (s32 Length, char* String); - static parse_result ParseSignedInt (s32 Length, char* String); - static parse_result ParseFloat (s32 Length, char* String); - - // PrintF - +#define MakeStringBuffer(name, size) char name##Backbuffer[(size)]; string name = MakeString(name##Backbuffer, size); + +static string MakeString (char* Array, s32 Length, s32 Max); +static string MakeString (char* Array, s32 Length); +static string MakeString (char* Array); +static string MakeStringLiteral(char* Data); + +static bool StringsEqual (string A, string B); +static bool StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength); +static bool StringEqualsCharArray (string String, char* CharArray); +static s32 FindFirstChar (string String, char C); + +static void SetStringToChar (string* Dest, char C, s32 Count); +static void SetStringToCharArray (string* Dest, char* Source); + +static void ConcatString (string Source, string* Dest); +static void ConcatString (string Source, s32 Length, string* Dest); +static void ConcatCharToString(string* Dest, char C); +static void ConcatCharArrayToString (char* Source, string* Dest); +static void ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest); + +static void CopyStringTo (string Source, string* Dest); +static s32 CopyStringToCharArray (string Source, char* Dest, s32 DestLength); +static void CopyCharArrayToString (char* Src, string* Dest); +static void CopyCharArrayToString (char* Src, s32 SrcLength, string* Dest); +static s32 CopyCharArray (char* Source, char* Dest, s32 DestLength); +static s32 CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset); + +static void InsertChar (string* String, char Char, s32 Index); +static void InsertStringAt (string* Dest, string Source, s32 At); +static void RemoveCharAt (string* String, s32 Index); + +static s32 IndexOfChar(string String, char C); +static s32 LastIndexOfChar(string String, char C); +static s32 SearchForCharInSet(string String, char* Set); +static s32 ReverseSearchForCharInSet(string String, char* Set); +static string Substring (string* String, s32 Start, s32 End); +static string Substring (string* String, s32 Start); + +static b32 StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength); +static b32 StringContainsString(string SearchIn, string SearchFor); +static b32 StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength); +static b32 StringContainsStringCaseInsensitive(string SearchIn, string SearchFor); + +static void NullTerminate (string* String); + +static u32 HashString(string String); + +// Parsing +enum parse_type +{ + ParseType_UnsignedInt, + ParseType_SignedInt, + ParseType_Float, +}; + +struct parse_result +{ + parse_type Type; + char* OnePastLast; + union + { + u32 UnsignedIntValue; + s32 SignedIntValue; + r32 FloatValue; + }; +}; + +enum format_flags +{ + FormatFlags_LeftJustify = 0x1, + FormatFlags_ForceSign = 0x2, + FormatFlags_ForceSpaceInsteadOfSign = 0x4, + FormatFlags_ForceDecimalOrPrependOx = 0x8, + FormatFlags_PadWithZeroesInsteadOfSpaces = 0x16, +}; + +static parse_result ParseUnsignedInt (s32 Length, char* String); +static parse_result ParseSignedInt (s32 Length, char* String); +static parse_result ParseFloat (s32 Length, char* String); + +// PrintF + #define StringExpand(str) (str).Length, (str).Memory - static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); - static void PrintF(string* String, char* Format, ...); - - // Printing Helper Functions - static u32 GetU32NumberOfCharactersNeeded(u32 Value, u32 Base = 10); - static u32 GetS32NumberOfCharactersNeeded(u32 Value, s32 Base = 10); - - //////////////////////////////////////////////////////////////// - // String Memory Function Declarations - //////////////////////////////////////////////////////////////// - - static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); - static bool SlotsAreContiguous (slot_header* First, slot_header* Second); - static contiguous_slot_count_result CountContiguousSlots (slot_header* First); - static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); - static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); - static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); - static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); - static void FreeToStringArena (string* String, slot_arena* Storage); - static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); - - //////////////////////////////////////////////////////////////// - // String Utility Functions - //////////////////////////////////////////////////////////////// - +static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args); +static void PrintF(string* String, char* Format, ...); + +// Printing Helper Functions +static u32 GetU32NumberOfCharactersNeeded(u32 Value, u32 Base = 10); +static u32 GetS32NumberOfCharactersNeeded(u32 Value, s32 Base = 10); + +//////////////////////////////////////////////////////////////// +// String Memory Function Declarations +//////////////////////////////////////////////////////////////// + +static s32 CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize); +static bool SlotsAreContiguous (slot_header* First, slot_header* Second); +static contiguous_slot_count_result CountContiguousSlots (slot_header* First); +static slot_header* GetSlotAtOffset(slot_header* First, s32 Offset); +static slot_header* InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart); +static void AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage); +static string AllocStringFromStringArena (s32 Size, slot_arena* Storage); +static void FreeToStringArena (string* String, slot_arena* Storage); +static void ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage); + +//////////////////////////////////////////////////////////////// +// String Utility Functions +//////////////////////////////////////////////////////////////// + #if !defined GS_LANGUAGE_H - - static void - GSZeroMemory (u8* Memory, s32 Size) - { - for (int i = 0; i < Size; i++) { Memory[i] = 0; } - } - - static s32 - GSMin (s32 A, s32 B) - { - return (A < B ? A : B); - } - - static s32 - GSAbs (s32 A) - { - return (A < 0 ? -A : A); - } - - static float - GSAbs (float A) - { - return (A < 0 ? -A : A); - } - - static float - GSPow (float N, s32 Power) - { - float Result = N; - for(s32 i = 1; i < Power; i++) { Result *= N; } - return Result; - } - + +static void +GSZeroMemory (u8* Memory, s32 Size) +{ + for (int i = 0; i < Size; i++) { Memory[i] = 0; } +} + +static s32 +GSMin (s32 A, s32 B) +{ + return (A < B ? A : B); +} + +static s32 +GSAbs (s32 A) +{ + return (A < 0 ? -A : A); +} + +static float +GSAbs (float A) +{ + return (A < 0 ? -A : A); +} + +static float +GSPow (float N, s32 Power) +{ + float Result = N; + for(s32 i = 1; i < Power; i++) { Result *= N; } + return Result; +} + #endif - - //////////////////////////////////////////////////////////////// - // Init and Clear - //////////////////////////////////////////////////////////////// - - static void - InitializeEmptyString (string* String, char* Data, s32 DataSize) - { - String->Memory = Data; - String->Max = DataSize; - String->Length = 0; - } - - static void - InitializeString(string* String, char* Data, s32 Used, s32 Max) - { - String->Memory = Data; - String->Max = Max; - String->Length = Used; - } - - static string - InitializeEmptyString (char* Data, s32 DataSize) - { - string Result = {}; - Result.Memory = Data; - Result.Max = DataSize; - Result.Length = 0; - return Result; - } - - static string - InitializeString (char* Data, s32 Used, s32 Max) - { - string Result = {}; - Result.Memory = Data; - Result.Max = Max; - Result.Length = Used; - return Result; - } - - static void - ClearString (string* String) - { - String->Memory = 0; - String->Max = 0; - String->Length = 0; - } - - //////////////////////////////////////////////////////////////// - // Char Value Types - //////////////////////////////////////////////////////////////// - - static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } - static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } - static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t'); } - static bool IsNewlineOrWhitespace (char C) { return (IsWhitespace(C) || IsNewline(C)); } - static bool IsAlpha (char C) - { - // TODO(Peter): support UTF8 chars - return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); - } - static bool IsUpper (char C) - { - return ((C >= 'A') && (C <= 'Z')); - } - static bool IsLower (char C) - { - return ((C >= 'a') && (C <= 'z')); - } - static bool IsNumeric (char C) - { - return (C >= '0') && (C <= '9'); - } - static bool IsNumericExtended (char C) - { - return (IsNumeric(C) || (C == 'x') || (C == 'f') || (C == '.')); - } - static bool IsAlphaNumeric (char C) - { - return IsAlpha(C) || IsNumeric(C); - } - static bool IsOperator (char C) - { - return ((C == '+') || - (C == '-') || - (C == '*') || - (C == '/') || - (C == '=') || - (C == '%') || - (C == '<') || - (C == '>')); - } - static char ToUpper (char A) - { - char Result = A; - if (IsLower(A)) - { - Result += 'A' - 'a'; - } - return Result; - } - static char ToLower (char A) - { - char Result = A; - if (IsUpper(A)) - { - Result -= 'A' - 'a'; - } - return Result; - } - static bool CharsEqualCaseInsensitive (char A, char B) - { - b32 Result = (ToLower(A) == ToLower(B)); - return Result; - } - - //////////////////////////////////////////////////////////////// - // Tokenizing - //////////////////////////////////////////////////////////////// - - static void - EatChar (tokenizer* T) - { - if (AtValidPosition(*T)) - { - if (IsNewline(*T->At)) - { - T->LineNumber++; - T->At++; - T->LineStart = T->At; - } - else - { - T->At++; - } - } - } - - static b32 - AtValidPosition (tokenizer Tokenizer) - { - b32 Result = (Tokenizer.At - Tokenizer.Memory) <= Tokenizer.MemoryLength; - return Result; - } - - static b32 - AtValidToken(tokenizer Tokenizer) - { - b32 Result = *Tokenizer.At && Tokenizer.At < (Tokenizer.Memory + Tokenizer.MemoryLength); - return Result; - } - - static char* - EatToNewLine(char* C) - { - char* Result = C; - while (*Result && !IsNewline(*Result)) - { - Result++; - } - return Result; - } - - static s32 - EatToNewLine(tokenizer* T) - { - char* TStart = T->At; - while (AtValidPosition(*T) && !IsNewline(*T->At)) - { - EatChar(T); - } - return T->At - TStart; - } - - static char* - EatPastNewLine(char* C) - { - char* Result = EatToNewLine(C); - while(*Result && IsNewline(*Result)) - { - Result++; - } - return Result; - } - - static s32 - EatPastNewLine(tokenizer* T) - { - char* TStart = T->At; - - EatToNewLine(T); - while(AtValidPosition(*T) && IsNewline(*T->At)) - { - EatChar(T); - } - - return T->At - TStart; - } - - static char* - EatWhitespace(char* C) - { - char* Result = C; - while (*Result && IsNewlineOrWhitespace(*Result)) { Result++; } - return Result; - } - - static s32 - EatWhitespace(tokenizer* T) - { - char* TStart = T->At; - while (AtValidPosition(*T) && IsNewlineOrWhitespace(*T->At)) { EatChar(T); } - return T->At - TStart; - } - - static char* - EatToNonWhitespaceOrNewline(char* C) - { - char* Result = C; - while (*Result && IsWhitespace(*Result)) { Result++; } - return Result; - } - - static s32 - EatToNonWhitespaceOrNewline(tokenizer* T) - { - char* TStart = T->At; - while (AtValidPosition(*T) && IsWhitespace(*T->At)) { EatChar(T); } - return T->At - TStart; - } - - static char* - EatToWhitespace(char* C) - { - char* Result = C; - while (*Result && !IsWhitespace(*Result)) { Result++; } - return Result; - } - - static s32 - EatToWhitespace(tokenizer* T) - { - char* TStart = T->At; - while (AtValidPosition(*T) && !IsWhitespace(*T->At)) { EatChar(T); } - return T->At - TStart; - } - - static char* - EatToCharacter(char* C, char Char) - { - char* Result = C; - while (*Result && *Result != Char) { Result++; } - return Result; - } - - static s32 - EatToCharacter(tokenizer* T, char Char) - { - char* TStart = T->At; - while (AtValidPosition(*T) && *T->At != Char) { EatChar(T); } - return T->At - TStart; - } - - static char* - EatPastCharacter(char* C, char Char) - { - char* Result = EatToCharacter(C, Char); - if (*Result && *Result == Char) { Result++; } - return Result; - } - - static s32 - EatPastCharacter(tokenizer* T, char Char) - { - char* TStart = T->At; - EatToCharacter(T, Char); - if (AtValidPosition(*T) && *T->At == Char) { EatChar(T); } - return T->At - TStart; - } - - static char* - EatNumber(char* C) - { - char* Result = C; - while (*Result && IsNumericExtended(*Result)) { Result++; } - return Result; - } - - static s32 - EatNumber(tokenizer* T) - { - char* TStart = T->At; - while (AtValidPosition(*T) && IsNumericExtended(*T->At)) { EatChar(T); } - return T->At - TStart; - } - - //////////////////////////////////////////////////////////////// - // Basic Char Operations - //////////////////////////////////////////////////////////////// - - static u32 CharToUInt (char C) { - u32 Result = (C - '0'); - return Result; - } - - static s32 - CharArrayLength (char* Array) - { - char* C = Array; - s32 Result = 0; - while (*C) - { - *C++; - Result++; - } - return Result; - } - - static s32 - NullTerminatedCharArrayLength (char* CharArray) - { - char* Iter = CharArray; - while (*Iter) - { - *Iter++; - } - return (Iter - CharArray); - } - - static bool - CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) - { - bool Result = false; - if (ALength == BLength) - { - Result = true; - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < ALength; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - return Result; - } - - static bool - CharArraysEqualUnsafe (char* A, char* B) - { - bool Result = true; - - char* AIter = A; - char* BIter = B; - while(*AIter && *BIter) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - if((*AIter && !*BIter) || (!*AIter && *BIter)) - { - Result = false; - } - - return Result; - } - - static bool - CharArraysEqualUpToLength (char* A, char* B, s32 Length) - { - bool Result = true; - - char* AIter = A; - char* BIter = B; - for (s32 i = 0; i < Length; i++) - { - if(*AIter++ != *BIter++) - { - Result = false; - break; - } - } - - return Result; - } - - static void - ReverseCharArray (char* Array, s32 Length) - { - char* ForwardIter = Array; - char* BackwardIter = Array + Length - 1; - for (s32 i = 0; i < (Length / 2); i++) - { - char F = *ForwardIter; - char B = *BackwardIter; - *ForwardIter++ = B; - *BackwardIter-- = F; - } - } - - static s32 - IndexOfChar (char* Array, s32 After, char Find) - { - s32 Result = -1; - - s32 Counter = After; - char* Iter = Array + After; - while (*Iter) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - Counter++; - *Iter++; - } - - return Result; - } - - static s32 - FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) - { - s32 Result = -1; - - s32 Counter = Length - OffsetFromEnd; - char* Iter = Array + Length - OffsetFromEnd; - for (int i = 0; i < (Length - OffsetFromEnd); i++) - { - if (*Iter == Find) - { - Result = Counter; - break; - } - - *Iter--; - Counter--; - } - - return Result; - } - - static s32 - ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) - { - s32 StringLength = NullTerminatedCharArrayLength(Array); - return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); - } - - static b32 - CharArrayContains(char* Array, char* CheckFor) - { - b32 Result = false; - - char* Src = Array; - while (*Src) - { - if (*Src == *CheckFor) - { - char* A = CheckFor; - char* B = Src; - while (*B && *A && *A == *B) - { - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - - return Result; - } - - static b32 - CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) - { - b32 Result = false; - - if (ArrayLength >= CheckForLength) - { - char* Src = Array; - for (s32 s = 0; s < ArrayLength; s++) - { - if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) - { - char* A = CheckFor; - char* B = Src; - for (s32 d = 0; d < CheckForLength; d++) - { - if (*B != *A) { break; } - *B++; *A++; - } - - if (*A == 0) - { - Result = true; - break; - } - } - - Src++; - } - } - - return Result; - } - - //////////////////////////////////////////////////////////////// - // Basic String Operations - //////////////////////////////////////////////////////////////// - - static bool - StringsEqual (string A, string B) - { - bool Result = false; - - if (A.Length == B.Length) - { - Result = true; - char* AIter = A.Memory; - char* BIter = B.Memory; - for (s32 i = 0; i < A.Length; i++) - { - if (*AIter++ != *BIter++) - { - Result = false; - break; - } - } - } - - return Result; - } - - static string - MakeString (char* Array, s32 Length, s32 Max) - { - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Max; - return Result; - } - - static string - MakeString (char* Array, s32 Length) - { - string Result = {}; - Result.Memory = Array; - Result.Length = Length; - Result.Max = Length; - return Result; - } - - static string - MakeString (char* Array) - { - s32 Length = CharArrayLength (Array); - return MakeString(Array, Length); - } - - static string - MakeStringLiteral (char* String) - { - string Result = {}; - Result.Memory = String; - Result.Max = CharArrayLength(String); - Result.Length = Result.Max; - return Result; - } - - static bool - StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) - { - bool Result = false; - - if (CharArrayLength == String.Length) - { - Result = true; - - char* S = String.Memory; - char* C = CharArray; - for (s32 i = 0; i < String.Length; i++) - { - if (*C++ != *S++) - { - Result = false; - break; - } - } - } - - return Result; - } - - static bool - StringEqualsCharArray (string String, char* CharArray) - { - s32 CLength = CharArrayLength(CharArray); - return StringEqualsCharArray(String, CharArray, CLength); - } - - static s32 - FindFirstChar (string String, char C) - { - s32 Result = -1; - - char* Iter = String.Memory; - for (int i = 0; i < String.Length; i++) - { - if (*Iter++ == C) - { - Result = i; - break; - } - } - - return Result; - } - - static void - SetStringToChar (string* Dest, char C, s32 Count) - { - Assert(Count <= Dest->Max); - - char* Iter = Dest->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = C; - } - Dest->Length = Count; - } - - static void - SetStringToCharArray (string* Dest, char* Source) - { - Dest->Length = 0; - - char* Src = Source; - char* Dst = Dest->Memory; - while (*Src && Dest->Length < Dest->Max) - { - *Dst++ = *Src++; - Dest->Length++; - } - } - - static void - ConcatString (string Source, string* Dest) - { - Assert((Dest->Length + Source.Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Source.Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } - } - - static void - ConcatString (string Source, s32 Length, string* Dest) - { - Assert(Length <= Source.Length); - Assert((Dest->Length + Length) <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source.Memory; - for (s32 i = 0; i < Length; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } - } - - static void - ConcatCharToString (string* Dest, char C) - { - Assert(Dest->Length + 1 <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - *Dst = C; - Dest->Length++; - } - - static void - ConcatCharArrayToString (char* Source, string* Dest) - { - Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - while (Dest->Length < Dest->Max && - *Src) - { - *Dst++ = *Src++; - Dest->Length++; - } - } - - static void - ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) - { - Assert(SourceLength + Dest->Length <= Dest->Max); - - char* Dst = Dest->Memory + Dest->Length; - char* Src = Source; - for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) - { - *Dst++ = *Src++; - Dest->Length++; - } - } - - static void - CopyStringTo (string Source, string* Dest) - { - char* Src = Source.Memory; - char* Dst = Dest->Memory; - s32 CopyLength = GSMin(Source.Length, Dest->Max); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - Dest->Length = Source.Length; - } - - static s32 - CopyStringToCharArray (string Source, char* Dest, s32 DestLength) - { - char* Src = Source.Memory; - char* Dst = Dest; - s32 CopyLength = GSMin(Source.Length, DestLength); - for (int i = 0; i < CopyLength; i++) - { - *Dst++ = *Src++; - } - return CopyLength; - } - - static void - CopyCharArrayToString (char* Source, string* Dest) - { - char* Src = Source; - char* Dst = Dest->Memory; - s32 Copied = 0; - while (*Src && Copied < Dest->Max) - { - *Dst++ = *Src++; - Copied++; - } - *Dst++ = 0; - Dest->Length = Copied; - } - - static void - CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) - { - Assert(SourceLength <= Dest->Max); - - char* Src = Source; - char* Dst = Dest->Memory; - for (s32 i = 0; i < SourceLength; i++) - { - *Dst++ = *Src++; - } - *Dst++ = 0; - Dest->Length = SourceLength; - } - - static s32 - CopyCharArray (char* Source, char* Dest, s32 DestLength) - { - char* Src = Source; - char* Dst = Dest; - s32 i = 0; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i; - } - - static s32 - CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) - { - Assert(Offset < DestLength); - - char* Src = Source; - char* Dst = Dest + Offset; - s32 i = Offset; - while (*Src && i < DestLength) - { - *Dst++ = *Src++; - i++; - } - return i - Offset; - } - - static void - InsertChar (string* String, char Char, s32 Index) - { - Assert(Index >= 0 && Index < String->Max); - Assert(String->Length < String->Max); - - char* Src = String->Memory + String->Length - 1; - char* Dst = Src + 1; - for (int i = String->Length - 1; i >= Index; i--) - { - *Dst-- = *Src--; - } - - *(String->Memory + Index) = Char; - String->Length++; - } - - static void - RemoveCharAt (string* String, s32 Index) - { - Assert(Index >= 0 && Index < String->Max); - - char* Dst = String->Memory + Index; - char* Src = Dst + 1; - for (int i = Index; i < String->Length; i++) - { - *Dst++ = *Src++; - } - *Dst = 0; - String->Length--; - } - - static s32 - IndexOfChar(string String, char C) - { - s32 Result = -1; - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = i; - break; - } - At++; - } - return Result; - } - - static s32 - LastIndexOfChar(string String, char C) - { - s32 Result = -1; - char* At = String.Memory + String.Length - 1; - for (s32 i = 0; i < String.Length; i++) - { - if (*At == C) - { - Result = String.Length - i; - break; - } - At--; - } - return Result; - } - - static s32 - SearchForCharInSet(string String, char* Set) - { - s32 Index = -1; - - char* At = String.Memory; - for (s32 i = 0; i < String.Length; i++) - { - char* Needle = Set; - while (*Needle) - { - if (*At == *Needle) - { - Index = String.Length - i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - - At++; - } - - return Index; - } - - static s32 - ReverseSearchForCharInSet(string String, char* Set) - { - s32 Index = -1; - - for (s32 i = String.Length - 1; i >= 0; i--) - { - char* Needle = Set; - while (*Needle) - { - if (String.Memory[i] == *Needle) - { - Index = i; - break; - } - - Needle++; - } - - if (Index >= 0) - { - break; - } - } - - return Index; - } - - static string - Substring (string String, s32 Start, s32 End) - { - Assert(Start >= 0 && End > Start && End <= String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = End - Start; - return Result; - } - - static string - Substring (string String, s32 Start) - { - Assert(Start >= 0 && Start < String.Length); - - string Result = {}; - Result.Memory = String.Memory + Start; - Result.Length = String.Length - Start; - return Result; - } - - static b32 - StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) - { - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (*InAt == *ForAt) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; - } - - static b32 - StringContainsString(string SearchIn, string SearchFor) - { - return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); - } - - static b32 - StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) - { - b32 Result = false; - - char* SearchInAt = SearchIn.Memory; - for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) - { - char* InAt = SearchInAt; - char* ForAt = SearchFor; - s32 LengthMatch = 0; - while (CharsEqualCaseInsensitive(*InAt, *ForAt)) - { - InAt++; - ForAt++; - LengthMatch++; - } - if (LengthMatch == SearchForLength) - { - Result = true; - break; - } - SearchInAt++; - } - - return Result; - } - - static b32 - StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) - { - return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); - } - - static void - NullTerminate (string* String) - { - Assert(String->Length + 1 <= String->Max); - *(String->Memory + String->Length) = 0; - String->Length++; - } - - // http://www.cse.yorku.ca/~oz/hash.html - // djb2 hash - static u32 - HashString(string String) - { - u32 Hash = 5381; - for (s32 i = 0; i < String.Length; i++) - { - Hash = ((Hash << 5) + Hash) + (u32)String.Memory[i]; /* hash * 33 + c */ - } - return Hash; - } - - static void - InsertStringAt (string* Dest, string Source, s32 At) - { - Assert(At + Source.Length < Dest->Max); - Assert(At < Dest->Length); - - char* Src = Dest->Memory + Dest->Length; - char* Dst = Dest->Memory + Source.Length + Dest->Length; - for (s32 i = Dest->Length - 1; i >= At; i--) - { - *--Dst = *--Src; - } - - Src = Source.Memory; - Dst = Dest->Memory + At; - for (s32 j = 0; j < Source.Length; j++) - { - *Dst++ = *Src++; - } - - Dest->Length += Source.Length; - } - - //////////////////////////////////////////////////////////////// - // String Parsing - //////////////////////////////////////////////////////////////// - - // NOTE(Peter): parameters are all in order Length, String because - // that matches the order of C's printf %.*s format specifier. This - // is convenient because you can use StringExpand to parse a string - // struct - // :StringExpandNote - static parse_result - ParseUnsignedInt (s32 Length, char* String) - { - Assert(IsNumeric(*String)); - parse_result Result = {}; - Result.Type = ParseType_UnsignedInt; - - char* Iter = String; - u32 ResultValue = 0; - for (s32 i = 0; i < Length; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - Result.UnsignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; - } - - static parse_result - ParseUnsignedIntUnsafe (char* String) - { - char* Start = String; - char* End = EatNumber(String + 1); - return ParseUnsignedInt(End - Start, String); - } - - // :StringExpandNote - static parse_result - ParseSignedInt (s32 Length, char* String) - { - Assert(Length > 0); - parse_result Result = {}; - Result.Type = ParseType_SignedInt; - - s32 Negative = 1; - s32 LengthRemaining = Length; - s32 ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); - } - - ResultValue *= Negative; - - Result.SignedIntValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; - } - - static parse_result - ParseSignedIntUnsafe (char* String) - { - char* Start = String; - char* End = EatNumber(String + 1); - return ParseSignedInt(End - Start, String); - } - - // :StringExpandNote - static parse_result - ParseFloat (s32 Length, char* String) - { - parse_result Result = {}; - Result.Type = ParseType_Float; - - s32 Negative = 1; - s32 LengthRemaining = Length; - float ResultValue = 0; - char* Iter = String; - - if (*Iter == '-') { - LengthRemaining--; - *Iter++; - Negative = -1; - } - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); - } - else if (*Iter == '.' || *Iter == 0) - { - LengthRemaining -= i; - break; - } - } - - if (*Iter == '.') - { - *Iter++; - float AfterPoint = 0; - s32 PlacesAfterPoint = 0; - - for (s32 i = 0; i < LengthRemaining; i++) - { - if (IsNumeric(*Iter)) - { - AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); - PlacesAfterPoint++; - } - else - { - break; - } - } - - AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); - ResultValue += AfterPoint; - } - - ResultValue *= Negative; - - Result.FloatValue = ResultValue; - Result.OnePastLast = Iter; - - return Result; - } - - static parse_result - ParseFloatUnsafe (char* String) - { - char* Start = String; - char* End = EatNumber(String + 1); - return ParseFloat(End - Start, String); - } - - static s32 - UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) - { - s32 Remaining = Int; - char* Iter = String; - while (Remaining > 0 && (Iter - String) < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - } - s32 CharsCopied = Iter - String; - ReverseCharArray(String, CharsCopied); - return CharsCopied; - } - - static s32 - IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) - { - s32 Remaining = Int; - s32 CharsCopied = 0; - - char* Iter = String; - - bool Negative = Remaining < 0; - Remaining = GSAbs(Remaining); - - if (Remaining > 0) - { - while (Remaining > 0 && CharsCopied < MaxLength) - { - *Iter++ = '0' + (Remaining % 10); - Remaining /= 10; - CharsCopied++; - } - } - else if (Remaining == 0) - { - *Iter++ = '0'; - } - - if (Negative) - { - *Iter++ = '-'; - CharsCopied++; - } - - ReverseCharArray(String, CharsCopied); - return CharsCopied; - } - - static s32 - IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) - { - char* StringStart = String + Offset; - s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); - return LengthWritten; - } - - static s32 - FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) - { - s32 IPart = (s32)Float; - float FPart = GSAbs(Float - (float)IPart); - - s32 i = IntToString(IPart, String, MaxLength); - - if (AfterPoint > 1) - { - String[i++] = '.'; - - s32 FPartInt = FPart * GSPow(10, AfterPoint); - i += IntToString(FPartInt, String, MaxLength, i, 0, 0); - } - - return i; - } - - //////////////////////////////////////////////////////////////// - // PrintF - //////////////////////////////////////////////////////////////// - - static void - OutChar (string* String, char C) - { - if (String->Length < String->Max) - { - String->Memory[String->Length] = C; - String->Length++; - } - } - - char OctalDigits[] = "01234567"; - char DecimalDigits[] = "0123456789"; - char HexDigits[] = "0123456789ABCDEF"; - - static void - U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) - { - u64 ValueRemaining = Value; - char* Start = String->Memory + String->Length; - do { - s32 DigitsIndex = ValueRemaining % Base; - char Digit = Digits[DigitsIndex]; - OutChar(String, Digit); - ValueRemaining /= Base; - }while (ValueRemaining); - char* End = String->Memory + String->Length; - - while (Start < End) - { - End--; - char Temp = *End; - *End = *Start; - *Start = Temp; - *Start++; - } - } - - static void - F64ToASCII (string* String, r64 Value, s32 Precision) - { - if (Value < 0) - { - OutChar(String, '-'); - Value = -Value; - } - - u64 IntegerPart = (u64)Value; - Value -= IntegerPart; - - U64ToASCII(String, IntegerPart, 10, DecimalDigits); - - OutChar(String, '.'); - - for (s32 i = 0; i < Precision; i++) - { - Value *= 10.f; - u32 DecimalPlace = Value; - Value -= DecimalPlace; - OutChar(String, DecimalDigits[DecimalPlace]); - } - } - - internal s64 - ReadVarArgsSignedInteger (s32 Width, va_list* Args) - { - s64 Result = 0; - switch (Width) - { - case 1: { Result = (s64)va_arg(*Args, s8); } break; - case 2: { Result = (s64)va_arg(*Args, s16); } break; - case 4: { Result = (s64)va_arg(*Args, s32); } break; - case 8: { Result = (s64)va_arg(*Args, s64); } break; - InvalidDefaultCase; - } - return Result; - } - - internal r64 - ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) - { - u64 Result = 0; - switch (Width) - { - case 1: { Result = (u64)va_arg(*Args, u8); } break; - case 2: { Result = (u64)va_arg(*Args, u16); } break; - case 4: { Result = (u64)va_arg(*Args, u32); } break; - case 8: { Result = (u64)va_arg(*Args, u64); } break; - InvalidDefaultCase; - } - return Result; - } - - internal r64 - ReadVarArgsFloat (s32 Width, va_list* Args) - { - r64 Result = 0; - switch (Width) - { - case 4: { Result = (r64)va_arg(*Args, r64); } break; - case 8: { Result = (r64)va_arg(*Args, r64); } break; - InvalidDefaultCase; - } - return Result; - } - - internal s32 - PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) - { - char* DestAt = Dest; - - char* FormatAt = Format; - while (*FormatAt) - { - if (FormatAt[0] != '%') - { - *DestAt++ = *FormatAt++; - } - else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol - { - *DestAt++ = *FormatAt++; - } - else - { - FormatAt++; - - // Flags - if (FormatAt[0] == '-') - { - FormatAt++; - } - else if (FormatAt[0] == '+') - { - FormatAt++; - } - else if (FormatAt[0] == ' ') - { - FormatAt++; - } - else if (FormatAt[0] == '#') - { - FormatAt++; - } - else if (FormatAt[0] == '0') - { - FormatAt++; - } - - // Width - b32 WidthSpecified = false; - s32 Width = 0; - - if (IsNumeric(FormatAt[0])) - { - WidthSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Width = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - WidthSpecified = true; - Width = va_arg(Args, s32); - Assert(Width >= 0); - FormatAt++; - } - - // Precision - b32 PrecisionSpecified = false; - s32 Precision = 0; - - if (FormatAt[0] == '.') - { - FormatAt++; - if (IsNumeric(FormatAt[0])) - { - PrecisionSpecified = true; - parse_result Parse = ParseSignedIntUnsafe(FormatAt); - FormatAt = Parse.OnePastLast; - Precision = Parse.SignedIntValue; - } - else if (FormatAt[0] == '*') - { - PrecisionSpecified = true; - Precision = va_arg(Args, s32); - Assert(Precision >= 0); - FormatAt++; - } - } - - // Length - b32 LengthSpecified = false; - s32 Length = 4; - - if (FormatAt[0] == 'h' && FormatAt[1] == 'h') - { - LengthSpecified = true; - LengthSpecified = 1; - FormatAt += 2; - } - else if (FormatAt[0] == 'h') - { - LengthSpecified = true; - LengthSpecified = 2; - FormatAt++; - } - else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt += 2; - } - else if (FormatAt[0] == 'l') - { - LengthSpecified = true; - LengthSpecified = 4; - FormatAt++; - } - else if (FormatAt[0] == 'j') - { - LengthSpecified = true; - LengthSpecified = 8; - FormatAt++; - } - else if (FormatAt[0] == 'z') - { - FormatAt++; - } - else if (FormatAt[0] == 't') - { - FormatAt++; - } - else if (FormatAt[0] == 'L') - { - FormatAt++; - } - - // Format Specifier - s32 DestLengthRemaining = DestMax - (DestAt - Dest); - - char Temp[64]; - string TempDest = MakeString(Temp, 0, 64); - - if (FormatAt[0] == 'd' || FormatAt[0] == 'i') - { - s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); - if (SignedInt < 0) - { - OutChar(&TempDest, '-'); - SignedInt *= -1; - } - U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'u') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); - } - else if (FormatAt[0] == 'o') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); - } - else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') - { - u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); - U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); - } - else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') - { - r64 Float = ReadVarArgsFloat(Length, &Args); - s32 AfterPoint = 6; - if (PrecisionSpecified) - { - AfterPoint = Precision; - } - F64ToASCII(&TempDest, Float, AfterPoint); - } - else if (FormatAt[0] == 'c') - { - char InsertChar = va_arg(Args, char); - OutChar(&TempDest, InsertChar); - } - else if (FormatAt[0] == 's') - { - char* InsertString = va_arg(Args, char*); - - s32 InsertStringLength = CharArrayLength(InsertString); - if (PrecisionSpecified) - { - InsertStringLength = GSMin(InsertStringLength, Precision); - } - InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); - - for (s32 c = 0; c < InsertStringLength; c++) - { - OutChar(&TempDest, *InsertString++); - } - } - else if (FormatAt[0] == 'S') - { - string InsertString = va_arg(Args, string); - - for (s32 c = 0; c < InsertString.Length; c++) - { - OutChar(&TempDest, InsertString.Memory[c]); - } - } - else if (FormatAt[0] == 'p') - { - // TODO(Peter): Pointer Address - } - else - { - // NOTE(Peter): Non-specifier character found - InvalidCodePath; - } - - for (s32 i = 0; i < TempDest.Length; i++) - { - *DestAt++ = TempDest.Memory[i]; - } - - *FormatAt++; - } - } - - s32 FormattedLength = DestAt - Dest; - return FormattedLength; - } - - static void - PrintF (string* String, char* Format, ...) - { - va_list Args; - va_start(Args, Format); - String->Length = 0; - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); - } - - static void - AppendPrintF (string* String, char* Format, ...) - { - va_list Args; - va_start(Args, Format); - String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); - va_end(Args); - } - - // Printing Helper Functions - static u32 - GetU32NumberOfCharactersNeeded(u32 Value, u32 Base) - { - u32 Result = 0; - u32 ValueLeft = Value; - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; - } - - static u32 - GetS32NumberOfCharactersNeeded(s32 Value, s32 Base) - { - u32 Result = 0; - s32 ValueLeft = Value; - if (Value < 0) - { - Result += 1; - ValueLeft = Value * -1; - } - // NOTE(Peter): This is in a do while loop because even if the number is 0, - // it'll still take one character to display that. - do - { - Result += 1; - ValueLeft /= Base; - }while (ValueLeft > 0); - return Result; - } - - //////////////////////////////////////////////////////////////// - // String Memory Function Definitions - //////////////////////////////////////////////////////////////// - - static s32 - CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) - { - s32 SlotCount = RequestedSize / SlotSize; - if (SlotCount * SlotSize < RequestedSize) - { - SlotCount += 1; - } - return SlotCount; - } - - static bool - SlotsAreContiguous (slot_header* First, slot_header* Second) - { - bool Result = false; - u8* FirstSlotNextAddress = (u8*)First + First->Size; - u8* SecondAddress = (u8*)Second; - Result = FirstSlotNextAddress == SecondAddress; - return Result; - } - - static contiguous_slot_count_result - CountContiguousSlots (slot_header* First) - { - Assert(First != 0); - - contiguous_slot_count_result Result = {}; - Result.Count = 1; - - slot_header* IterPrev = First; - slot_header* Iter = First->Next; - while (Iter && SlotsAreContiguous(IterPrev, Iter)) - { - Result.Count++; - IterPrev = Iter; - Iter = Iter->Next; - } - - Result.LastContiguousSlot = IterPrev; - return Result; - } - - static slot_header* - GetSlotAtOffset(slot_header* First, s32 Offset) - { - slot_header* Iter = First; - s32 Count = 0; - while (Count < Offset && Iter) - { - Iter = Iter->Next; - Count++; - } - return Iter; - } - - static slot_header* - InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) - { - slot_header* List = ListStart; - if (NewSlot < List) - { - NewSlot->Next = List; - List = NewSlot; - } - else - { - slot_header* PrevIter = List; - slot_header* Iter = List->Next; - while (Iter && NewSlot > Iter) - { - PrevIter = Iter; - Iter = Iter->Next; - } - - Assert(PrevIter); - if (PrevIter) - { - PrevIter->Next = NewSlot; - } - - if (Iter) - { - NewSlot->Next = Iter; - } - } - return List; - } - - static void - AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) - { - s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); - slot_header* Slot = Storage->FreeList; - slot_header* PrevSlot = 0; - while (Slot) - { - contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); - if (ContiguousSlots.Count >= SlotCount) - { - slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); - if (PrevSlot) - { - PrevSlot->Next = NextStartSlot; - } - else - { - Storage->FreeList = NextStartSlot; - } - break; - } - else - { - PrevSlot = Slot; - Slot = Slot->Next; - } - } - - if (Slot) - { - String->Memory = (char*)Slot; - GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); - String->Max = SlotCount * Storage->SlotSize; - String->Length = 0; - } - } - - static string - AllocStringFromStringArena (s32 Size, slot_arena* Storage) - { - string Result = {0}; - AllocStringFromStringArena(&Result, Size, Storage); - return Result; - } - - static void - FreeToStringArena (string* String, slot_arena* Storage) - { - u8* Base = (u8*)(String->Memory); - u8* End = Base + String->Max - 1; - u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); - Assert((Base >= Storage->Memory) && (End < MemoryEnd)); - Assert((String->Max % Storage->SlotSize) == 0); - - s32 SizeReclaimed = 0; - slot_header* Slot = (slot_header*)Base; - while (SizeReclaimed < String->Max) - { - Slot->Size = Storage->SlotSize; - Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); - SizeReclaimed += Storage->SlotSize; - Slot = (slot_header*)(Base + SizeReclaimed); - } - - String->Memory = 0; - String->Length = 0; - String->Max = 0; - } - - static void - ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) - { - string NewString = AllocStringFromStringArena(NewSize, Storage); - CopyStringTo(*String, &NewString); - FreeToStringArena(String, Storage); - *String = NewString; - } - + +//////////////////////////////////////////////////////////////// +// Init and Clear +//////////////////////////////////////////////////////////////// + +static void +InitializeEmptyString (string* String, char* Data, s32 DataSize) +{ + String->Memory = Data; + String->Max = DataSize; + String->Length = 0; +} + +static void +InitializeString(string* String, char* Data, s32 Used, s32 Max) +{ + String->Memory = Data; + String->Max = Max; + String->Length = Used; +} + +static string +InitializeEmptyString (char* Data, s32 DataSize) +{ + string Result = {}; + Result.Memory = Data; + Result.Max = DataSize; + Result.Length = 0; + return Result; +} + +static string +InitializeString (char* Data, s32 Used, s32 Max) +{ + string Result = {}; + Result.Memory = Data; + Result.Max = Max; + Result.Length = Used; + return Result; +} + +static void +ClearString (string* String) +{ + String->Memory = 0; + String->Max = 0; + String->Length = 0; +} + +//////////////////////////////////////////////////////////////// +// Char Value Types +//////////////////////////////////////////////////////////////// + +static bool IsSlash (char C) { return ((C == '\\') || (C == '/')); } +static bool IsNewline (char C) { return (C == '\n') || (C == '\r'); } +static bool IsWhitespace (char C) { return (C == ' ') || (C == '\t'); } +static bool IsNewlineOrWhitespace (char C) { return (IsWhitespace(C) || IsNewline(C)); } +static bool IsAlpha (char C) +{ + // TODO(Peter): support UTF8 chars + return ((C >= 'A') && (C <= 'Z')) || ((C >= 'a') && (C <= 'z')) || (C == '_'); +} +static bool IsUpper (char C) +{ + return ((C >= 'A') && (C <= 'Z')); +} +static bool IsLower (char C) +{ + return ((C >= 'a') && (C <= 'z')); +} +static bool IsNumeric (char C) +{ + return (C >= '0') && (C <= '9'); +} +static bool IsNumericExtended (char C) +{ + return (IsNumeric(C) || (C == 'x') || (C == 'f') || (C == '.')); +} +static bool IsAlphaNumeric (char C) +{ + return IsAlpha(C) || IsNumeric(C); +} +static bool IsOperator (char C) +{ + return ((C == '+') || + (C == '-') || + (C == '*') || + (C == '/') || + (C == '=') || + (C == '%') || + (C == '<') || + (C == '>')); +} +static char ToUpper (char A) +{ + char Result = A; + if (IsLower(A)) + { + Result += 'A' - 'a'; + } + return Result; +} +static char ToLower (char A) +{ + char Result = A; + if (IsUpper(A)) + { + Result -= 'A' - 'a'; + } + return Result; +} +static bool CharsEqualCaseInsensitive (char A, char B) +{ + b32 Result = (ToLower(A) == ToLower(B)); + return Result; +} + +//////////////////////////////////////////////////////////////// +// Tokenizing +//////////////////////////////////////////////////////////////// + +static void +EatChar (tokenizer* T) +{ + if (AtValidPosition(*T)) + { + if (IsNewline(*T->At)) + { + T->LineNumber++; + T->At++; + T->LineStart = T->At; + } + else + { + T->At++; + } + } +} + +static b32 +AtValidPosition (tokenizer Tokenizer) +{ + b32 Result = (Tokenizer.At - Tokenizer.Memory) <= Tokenizer.MemoryLength; + return Result; +} + +static b32 +AtValidToken(tokenizer Tokenizer) +{ + b32 Result = *Tokenizer.At && Tokenizer.At < (Tokenizer.Memory + Tokenizer.MemoryLength); + return Result; +} + +static char* +EatToNewLine(char* C) +{ + char* Result = C; + while (*Result && !IsNewline(*Result)) + { + Result++; + } + return Result; +} + +static s32 +EatToNewLine(tokenizer* T) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && !IsNewline(*T->At)) + { + EatChar(T); + } + return T->At - TStart; +} + +static char* +EatPastNewLine(char* C) +{ + char* Result = EatToNewLine(C); + while(*Result && IsNewline(*Result)) + { + Result++; + } + return Result; +} + +static s32 +EatPastNewLine(tokenizer* T) +{ + char* TStart = T->At; + + EatToNewLine(T); + while(AtValidPosition(*T) && IsNewline(*T->At)) + { + EatChar(T); + } + + return T->At - TStart; +} + +static char* +EatWhitespace(char* C) +{ + char* Result = C; + while (*Result && IsNewlineOrWhitespace(*Result)) { Result++; } + return Result; +} + +static s32 +EatWhitespace(tokenizer* T) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && IsNewlineOrWhitespace(*T->At)) { EatChar(T); } + return T->At - TStart; +} + +static char* +EatToNonWhitespaceOrNewline(char* C) +{ + char* Result = C; + while (*Result && IsWhitespace(*Result)) { Result++; } + return Result; +} + +static s32 +EatToNonWhitespaceOrNewline(tokenizer* T) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && IsWhitespace(*T->At)) { EatChar(T); } + return T->At - TStart; +} + +static char* +EatToWhitespace(char* C) +{ + char* Result = C; + while (*Result && !IsWhitespace(*Result)) { Result++; } + return Result; +} + +static s32 +EatToWhitespace(tokenizer* T) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && !IsWhitespace(*T->At)) { EatChar(T); } + return T->At - TStart; +} + +static char* +EatToCharacter(char* C, char Char) +{ + char* Result = C; + while (*Result && *Result != Char) { Result++; } + return Result; +} + +static s32 +EatToCharacter(tokenizer* T, char Char) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && *T->At != Char) { EatChar(T); } + return T->At - TStart; +} + +static char* +EatPastCharacter(char* C, char Char) +{ + char* Result = EatToCharacter(C, Char); + if (*Result && *Result == Char) { Result++; } + return Result; +} + +static s32 +EatPastCharacter(tokenizer* T, char Char) +{ + char* TStart = T->At; + EatToCharacter(T, Char); + if (AtValidPosition(*T) && *T->At == Char) { EatChar(T); } + return T->At - TStart; +} + +static char* +EatNumber(char* C) +{ + char* Result = C; + while (*Result && IsNumericExtended(*Result)) { Result++; } + return Result; +} + +static s32 +EatNumber(tokenizer* T) +{ + char* TStart = T->At; + while (AtValidPosition(*T) && IsNumericExtended(*T->At)) { EatChar(T); } + return T->At - TStart; +} + +//////////////////////////////////////////////////////////////// +// Basic Char Operations +//////////////////////////////////////////////////////////////// + +static u32 CharToUInt (char C) { + u32 Result = (C - '0'); + return Result; +} + +static s32 +CharArrayLength (char* Array) +{ + char* C = Array; + s32 Result = 0; + while (*C) + { + *C++; + Result++; + } + return Result; +} + +static s32 +NullTerminatedCharArrayLength (char* CharArray) +{ + char* Iter = CharArray; + while (*Iter) + { + *Iter++; + } + return (Iter - CharArray); +} + +static bool +CharArraysEqual (char* A, s32 ALength, char* B, s32 BLength) +{ + bool Result = false; + if (ALength == BLength) + { + Result = true; + char* AIter = A; + char* BIter = B; + for (s32 i = 0; i < ALength; i++) + { + if(*AIter++ != *BIter++) + { + Result = false; + break; + } + } + } + return Result; +} + +static bool +CharArraysEqualUnsafe (char* A, char* B) +{ + bool Result = true; + + char* AIter = A; + char* BIter = B; + while(*AIter && *BIter) + { + if(*AIter++ != *BIter++) + { + Result = false; + break; + } + } + + if((*AIter && !*BIter) || (!*AIter && *BIter)) + { + Result = false; + } + + return Result; +} + +static bool +CharArraysEqualUpToLength (char* A, char* B, s32 Length) +{ + bool Result = true; + + char* AIter = A; + char* BIter = B; + for (s32 i = 0; i < Length; i++) + { + if(*AIter++ != *BIter++) + { + Result = false; + break; + } + } + + return Result; +} + +static void +ReverseCharArray (char* Array, s32 Length) +{ + char* ForwardIter = Array; + char* BackwardIter = Array + Length - 1; + for (s32 i = 0; i < (Length / 2); i++) + { + char F = *ForwardIter; + char B = *BackwardIter; + *ForwardIter++ = B; + *BackwardIter-- = F; + } +} + +static s32 +IndexOfChar (char* Array, s32 After, char Find) +{ + s32 Result = -1; + + s32 Counter = After; + char* Iter = Array + After; + while (*Iter) + { + if (*Iter == Find) + { + Result = Counter; + break; + } + Counter++; + *Iter++; + } + + return Result; +} + +static s32 +FastReverseIndexOfChar (char* Array, s32 Length, s32 OffsetFromEnd, char Find) +{ + s32 Result = -1; + + s32 Counter = Length - OffsetFromEnd; + char* Iter = Array + Length - OffsetFromEnd; + for (int i = 0; i < (Length - OffsetFromEnd); i++) + { + if (*Iter == Find) + { + Result = Counter; + break; + } + + *Iter--; + Counter--; + } + + return Result; +} + +static s32 +ReverseIndexOfChar (char* Array, s32 OffsetFromEnd, char Find) +{ + s32 StringLength = NullTerminatedCharArrayLength(Array); + return FastReverseIndexOfChar(Array, StringLength, OffsetFromEnd, Find); +} + +static b32 +CharArrayContains(char* Array, char* CheckFor) +{ + b32 Result = false; + + char* Src = Array; + while (*Src) + { + if (*Src == *CheckFor) + { + char* A = CheckFor; + char* B = Src; + while (*B && *A && *A == *B) + { + *B++; *A++; + } + + if (*A == 0) + { + Result = true; + break; + } + } + + Src++; + } + + return Result; +} + +static b32 +CharArrayContainsSafe(char* Array, s32 ArrayLength, char* CheckFor, s32 CheckForLength) +{ + b32 Result = false; + + if (ArrayLength >= CheckForLength) + { + char* Src = Array; + for (s32 s = 0; s < ArrayLength; s++) + { + if (*Src == *CheckFor && (s + CheckForLength <= ArrayLength)) + { + char* A = CheckFor; + char* B = Src; + for (s32 d = 0; d < CheckForLength; d++) + { + if (*B != *A) { break; } + *B++; *A++; + } + + if (*A == 0) + { + Result = true; + break; + } + } + + Src++; + } + } + + return Result; +} + +//////////////////////////////////////////////////////////////// +// Basic String Operations +//////////////////////////////////////////////////////////////// + +static bool +StringsEqual (string A, string B) +{ + bool Result = false; + + if (A.Length == B.Length) + { + Result = true; + char* AIter = A.Memory; + char* BIter = B.Memory; + for (s32 i = 0; i < A.Length; i++) + { + if (*AIter++ != *BIter++) + { + Result = false; + break; + } + } + } + + return Result; +} + +static string +MakeString (char* Array, s32 Length, s32 Max) +{ + string Result = {}; + Result.Memory = Array; + Result.Length = Length; + Result.Max = Max; + return Result; +} + +static string +MakeString (char* Array, s32 Length) +{ + string Result = {}; + Result.Memory = Array; + Result.Length = Length; + Result.Max = Length; + return Result; +} + +static string +MakeString (char* Array) +{ + s32 Length = CharArrayLength (Array); + return MakeString(Array, Length); +} + +static string +MakeStringLiteral (char* String) +{ + string Result = {}; + Result.Memory = String; + Result.Max = CharArrayLength(String); + Result.Length = Result.Max; + return Result; +} + +static bool +StringEqualsCharArray (string String, char* CharArray, s32 CharArrayLength) +{ + bool Result = false; + + if (CharArrayLength == String.Length) + { + Result = true; + + char* S = String.Memory; + char* C = CharArray; + for (s32 i = 0; i < String.Length; i++) + { + if (*C++ != *S++) + { + Result = false; + break; + } + } + } + + return Result; +} + +static bool +StringEqualsCharArray (string String, char* CharArray) +{ + s32 CLength = CharArrayLength(CharArray); + return StringEqualsCharArray(String, CharArray, CLength); +} + +static s32 +FindFirstChar (string String, char C) +{ + s32 Result = -1; + + char* Iter = String.Memory; + for (int i = 0; i < String.Length; i++) + { + if (*Iter++ == C) + { + Result = i; + break; + } + } + + return Result; +} + +static void +SetStringToChar (string* Dest, char C, s32 Count) +{ + Assert(Count <= Dest->Max); + + char* Iter = Dest->Memory; + for (int i = 0; i < Count; i++) + { + *Iter++ = C; + } + Dest->Length = Count; +} + +static void +SetStringToCharArray (string* Dest, char* Source) +{ + Dest->Length = 0; + + char* Src = Source; + char* Dst = Dest->Memory; + while (*Src && Dest->Length < Dest->Max) + { + *Dst++ = *Src++; + Dest->Length++; + } +} + +static void +ConcatString (string Source, string* Dest) +{ + Assert((Dest->Length + Source.Length) <= Dest->Max); + + char* Dst = Dest->Memory + Dest->Length; + char* Src = Source.Memory; + for (s32 i = 0; i < Source.Length; i++) + { + *Dst++ = *Src++; + Dest->Length++; + } +} + +static void +ConcatString (string Source, s32 Length, string* Dest) +{ + Assert(Length <= Source.Length); + Assert((Dest->Length + Length) <= Dest->Max); + + char* Dst = Dest->Memory + Dest->Length; + char* Src = Source.Memory; + for (s32 i = 0; i < Length; i++) + { + *Dst++ = *Src++; + Dest->Length++; + } +} + +static void +ConcatCharToString (string* Dest, char C) +{ + Assert(Dest->Length + 1 <= Dest->Max); + + char* Dst = Dest->Memory + Dest->Length; + *Dst = C; + Dest->Length++; +} + +static void +ConcatCharArrayToString (char* Source, string* Dest) +{ + Assert(CharArrayLength(Source) + Dest->Length <= Dest->Max); + + char* Dst = Dest->Memory + Dest->Length; + char* Src = Source; + while (Dest->Length < Dest->Max && + *Src) + { + *Dst++ = *Src++; + Dest->Length++; + } +} + +static void +ConcatCharArrayToString (char* Source, s32 SourceLength, string* Dest) +{ + Assert(SourceLength + Dest->Length <= Dest->Max); + + char* Dst = Dest->Memory + Dest->Length; + char* Src = Source; + for (int i = 0; i < SourceLength && Dest->Length < Dest->Max; i++) + { + *Dst++ = *Src++; + Dest->Length++; + } +} + +static void +CopyStringTo (string Source, string* Dest) +{ + char* Src = Source.Memory; + char* Dst = Dest->Memory; + s32 CopyLength = GSMin(Source.Length, Dest->Max); + for (int i = 0; i < CopyLength; i++) + { + *Dst++ = *Src++; + } + Dest->Length = Source.Length; +} + +static s32 +CopyStringToCharArray (string Source, char* Dest, s32 DestLength) +{ + char* Src = Source.Memory; + char* Dst = Dest; + s32 CopyLength = GSMin(Source.Length, DestLength); + for (int i = 0; i < CopyLength; i++) + { + *Dst++ = *Src++; + } + return CopyLength; +} + +static void +CopyCharArrayToString (char* Source, string* Dest) +{ + char* Src = Source; + char* Dst = Dest->Memory; + s32 Copied = 0; + while (*Src && Copied < Dest->Max) + { + *Dst++ = *Src++; + Copied++; + } + *Dst++ = 0; + Dest->Length = Copied; +} + +static void +CopyCharArrayToString (char* Source, s32 SourceLength, string* Dest) +{ + Assert(SourceLength <= Dest->Max); + + char* Src = Source; + char* Dst = Dest->Memory; + for (s32 i = 0; i < SourceLength; i++) + { + *Dst++ = *Src++; + } + *Dst++ = 0; + Dest->Length = SourceLength; +} + +static s32 +CopyCharArray (char* Source, char* Dest, s32 DestLength) +{ + char* Src = Source; + char* Dst = Dest; + s32 i = 0; + while (*Src && i < DestLength) + { + *Dst++ = *Src++; + i++; + } + return i; +} + +static s32 +CopyCharArrayAt (char* Source, char* Dest, s32 DestLength, s32 Offset) +{ + Assert(Offset < DestLength); + + char* Src = Source; + char* Dst = Dest + Offset; + s32 i = Offset; + while (*Src && i < DestLength) + { + *Dst++ = *Src++; + i++; + } + return i - Offset; +} + +static void +InsertChar (string* String, char Char, s32 Index) +{ + Assert(Index >= 0 && Index < String->Max); + Assert(String->Length < String->Max); + + char* Src = String->Memory + String->Length - 1; + char* Dst = Src + 1; + for (int i = String->Length - 1; i >= Index; i--) + { + *Dst-- = *Src--; + } + + *(String->Memory + Index) = Char; + String->Length++; +} + +static void +RemoveCharAt (string* String, s32 Index) +{ + Assert(Index >= 0 && Index < String->Max); + + char* Dst = String->Memory + Index; + char* Src = Dst + 1; + for (int i = Index; i < String->Length; i++) + { + *Dst++ = *Src++; + } + *Dst = 0; + String->Length--; +} + +static s32 +IndexOfChar(string String, char C) +{ + s32 Result = -1; + char* At = String.Memory; + for (s32 i = 0; i < String.Length; i++) + { + if (*At == C) + { + Result = i; + break; + } + At++; + } + return Result; +} + +static s32 +LastIndexOfChar(string String, char C) +{ + s32 Result = -1; + char* At = String.Memory + String.Length - 1; + for (s32 i = 0; i < String.Length; i++) + { + if (*At == C) + { + Result = String.Length - i; + break; + } + At--; + } + return Result; +} + +static s32 +SearchForCharInSet(string String, char* Set) +{ + s32 Index = -1; + + char* At = String.Memory; + for (s32 i = 0; i < String.Length; i++) + { + char* Needle = Set; + while (*Needle) + { + if (*At == *Needle) + { + Index = String.Length - i; + break; + } + + Needle++; + } + + if (Index >= 0) + { + break; + } + + At++; + } + + return Index; +} + +static s32 +ReverseSearchForCharInSet(string String, char* Set) +{ + s32 Index = -1; + + for (s32 i = String.Length - 1; i >= 0; i--) + { + char* Needle = Set; + while (*Needle) + { + if (String.Memory[i] == *Needle) + { + Index = i; + break; + } + + Needle++; + } + + if (Index >= 0) + { + break; + } + } + + return Index; +} + +static string +Substring (string String, s32 Start, s32 End) +{ + Assert(Start >= 0 && End > Start && End <= String.Length); + + string Result = {}; + Result.Memory = String.Memory + Start; + Result.Length = End - Start; + return Result; +} + +static string +Substring (string String, s32 Start) +{ + Assert(Start >= 0 && Start < String.Length); + + string Result = {}; + Result.Memory = String.Memory + Start; + Result.Length = String.Length - Start; + return Result; +} + +static b32 +StringContainsCharArray(string SearchIn, char* SearchFor, s32 SearchForLength) +{ + b32 Result = false; + + char* SearchInAt = SearchIn.Memory; + for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) + { + char* InAt = SearchInAt; + char* ForAt = SearchFor; + s32 LengthMatch = 0; + while (*InAt == *ForAt) + { + InAt++; + ForAt++; + LengthMatch++; + } + if (LengthMatch == SearchForLength) + { + Result = true; + break; + } + SearchInAt++; + } + + return Result; +} + +static b32 +StringContainsString(string SearchIn, string SearchFor) +{ + return StringContainsCharArray(SearchIn, SearchFor.Memory, SearchFor.Length); +} + +static b32 +StringContainsCharArrayCaseInsensitive(string SearchIn, char* SearchFor, s32 SearchForLength) +{ + b32 Result = false; + + char* SearchInAt = SearchIn.Memory; + for (s32 i = 0; i < (SearchIn.Length - SearchForLength) + 1; i++) + { + char* InAt = SearchInAt; + char* ForAt = SearchFor; + s32 LengthMatch = 0; + while (CharsEqualCaseInsensitive(*InAt, *ForAt)) + { + InAt++; + ForAt++; + LengthMatch++; + } + if (LengthMatch == SearchForLength) + { + Result = true; + break; + } + SearchInAt++; + } + + return Result; +} + +static b32 +StringContainsStringCaseInsensitive(string SearchIn, string SearchFor) +{ + return StringContainsCharArrayCaseInsensitive(SearchIn, SearchFor.Memory, SearchFor.Length); +} + +static void +NullTerminate (string* String) +{ + Assert(String->Length + 1 <= String->Max); + *(String->Memory + String->Length) = 0; + String->Length++; +} + +// http://www.cse.yorku.ca/~oz/hash.html +// djb2 hash +static u32 +HashString(string String) +{ + u32 Hash = 5381; + for (s32 i = 0; i < String.Length; i++) + { + Hash = ((Hash << 5) + Hash) + (u32)String.Memory[i]; /* hash * 33 + c */ + } + return Hash; +} + +static void +InsertStringAt (string* Dest, string Source, s32 At) +{ + Assert(At + Source.Length < Dest->Max); + Assert(At < Dest->Length); + + char* Src = Dest->Memory + Dest->Length; + char* Dst = Dest->Memory + Source.Length + Dest->Length; + for (s32 i = Dest->Length - 1; i >= At; i--) + { + *--Dst = *--Src; + } + + Src = Source.Memory; + Dst = Dest->Memory + At; + for (s32 j = 0; j < Source.Length; j++) + { + *Dst++ = *Src++; + } + + Dest->Length += Source.Length; +} + +//////////////////////////////////////////////////////////////// +// String Parsing +//////////////////////////////////////////////////////////////// + +// NOTE(Peter): parameters are all in order Length, String because +// that matches the order of C's printf %.*s format specifier. This +// is convenient because you can use StringExpand to parse a string +// struct +// :StringExpandNote +static parse_result +ParseUnsignedInt (s32 Length, char* String) +{ + Assert(IsNumeric(*String)); + parse_result Result = {}; + Result.Type = ParseType_UnsignedInt; + + char* Iter = String; + u32 ResultValue = 0; + for (s32 i = 0; i < Length; i++) + { + ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); + } + + Result.UnsignedIntValue = ResultValue; + Result.OnePastLast = Iter; + + return Result; +} + +static parse_result +ParseUnsignedIntUnsafe (char* String) +{ + char* Start = String; + char* End = EatNumber(String + 1); + return ParseUnsignedInt(End - Start, String); +} + +// :StringExpandNote +static parse_result +ParseSignedInt (s32 Length, char* String) +{ + Assert(Length > 0); + parse_result Result = {}; + Result.Type = ParseType_SignedInt; + + s32 Negative = 1; + s32 LengthRemaining = Length; + s32 ResultValue = 0; + char* Iter = String; + + if (*Iter == '-') { + LengthRemaining--; + *Iter++; + Negative = -1; + } + + for (s32 i = 0; i < LengthRemaining; i++) + { + ResultValue = CharToUInt(*Iter++) + (ResultValue * 10); + } + + ResultValue *= Negative; + + Result.SignedIntValue = ResultValue; + Result.OnePastLast = Iter; + + return Result; +} + +static parse_result +ParseSignedIntUnsafe (char* String) +{ + char* Start = String; + char* End = EatNumber(String + 1); + return ParseSignedInt(End - Start, String); +} + +// :StringExpandNote +static parse_result +ParseFloat (s32 Length, char* String) +{ + parse_result Result = {}; + Result.Type = ParseType_Float; + + s32 Negative = 1; + s32 LengthRemaining = Length; + float ResultValue = 0; + char* Iter = String; + + if (*Iter == '-') { + LengthRemaining--; + *Iter++; + Negative = -1; + } + + for (s32 i = 0; i < LengthRemaining; i++) + { + if (IsNumeric(*Iter)) + { + ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10); + } + else if (*Iter == '.' || *Iter == 0) + { + LengthRemaining -= i; + break; + } + } + + if (*Iter == '.') + { + *Iter++; + float AfterPoint = 0; + s32 PlacesAfterPoint = 0; + + for (s32 i = 0; i < LengthRemaining; i++) + { + if (IsNumeric(*Iter)) + { + AfterPoint = (float)CharToUInt(*Iter++) + (AfterPoint * 10); + PlacesAfterPoint++; + } + else + { + break; + } + } + + AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint); + ResultValue += AfterPoint; + } + + ResultValue *= Negative; + + Result.FloatValue = ResultValue; + Result.OnePastLast = Iter; + + return Result; +} + +static parse_result +ParseFloatUnsafe (char* String) +{ + char* Start = String; + char* End = EatNumber(String + 1); + return ParseFloat(End - Start, String); +} + +static s32 +UIntToString (u32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) +{ + s32 Remaining = Int; + char* Iter = String; + while (Remaining > 0 && (Iter - String) < MaxLength) + { + *Iter++ = '0' + (Remaining % 10); + Remaining /= 10; + } + s32 CharsCopied = Iter - String; + ReverseCharArray(String, CharsCopied); + return CharsCopied; +} + +static s32 +IntToString (s32 Int, char* String, s32 MaxLength, b32 FormatFlags = 0, s32 MinimumLength = 0) +{ + s32 Remaining = Int; + s32 CharsCopied = 0; + + char* Iter = String; + + bool Negative = Remaining < 0; + Remaining = GSAbs(Remaining); + + if (Remaining > 0) + { + while (Remaining > 0 && CharsCopied < MaxLength) + { + *Iter++ = '0' + (Remaining % 10); + Remaining /= 10; + CharsCopied++; + } + } + else if (Remaining == 0) + { + *Iter++ = '0'; + } + + if (Negative) + { + *Iter++ = '-'; + CharsCopied++; + } + + ReverseCharArray(String, CharsCopied); + return CharsCopied; +} + +static s32 +IntToString (s32 Int, char* String, s32 MaxLength, s32 Offset, b32 FormatFlags = 0, s32 MinimumWidth = 0) +{ + char* StringStart = String + Offset; + s32 LengthWritten = IntToString(Int, StringStart, MaxLength - Offset); + return LengthWritten; +} + +static s32 +FloatToString(float Float, char *String, s32 MaxLength, s32 AfterPoint = 0, b32 FormatFlags = 0, s32 MinimumWidth = 0) +{ + s32 IPart = (s32)Float; + float FPart = GSAbs(Float - (float)IPart); + + s32 i = IntToString(IPart, String, MaxLength); + + if (AfterPoint > 1) + { + String[i++] = '.'; + + s32 FPartInt = FPart * GSPow(10, AfterPoint); + i += IntToString(FPartInt, String, MaxLength, i, 0, 0); + } + + return i; +} + +//////////////////////////////////////////////////////////////// +// PrintF +//////////////////////////////////////////////////////////////// + +static void +OutChar (string* String, char C) +{ + if (String->Length < String->Max) + { + String->Memory[String->Length] = C; + String->Length++; + } +} + +char OctalDigits[] = "01234567"; +char DecimalDigits[] = "0123456789"; +char HexDigits[] = "0123456789ABCDEF"; + +static void +U64ToASCII (string* String, u64 Value, s32 Base, char* Digits) +{ + u64 ValueRemaining = Value; + char* Start = String->Memory + String->Length; + do { + s32 DigitsIndex = ValueRemaining % Base; + char Digit = Digits[DigitsIndex]; + OutChar(String, Digit); + ValueRemaining /= Base; + }while (ValueRemaining); + char* End = String->Memory + String->Length; + + while (Start < End) + { + End--; + char Temp = *End; + *End = *Start; + *Start = Temp; + *Start++; + } +} + +static void +F64ToASCII (string* String, r64 Value, s32 Precision) +{ + if (Value < 0) + { + OutChar(String, '-'); + Value = -Value; + } + + u64 IntegerPart = (u64)Value; + Value -= IntegerPart; + + U64ToASCII(String, IntegerPart, 10, DecimalDigits); + + OutChar(String, '.'); + + for (s32 i = 0; i < Precision; i++) + { + Value *= 10.f; + u32 DecimalPlace = Value; + Value -= DecimalPlace; + OutChar(String, DecimalDigits[DecimalPlace]); + } +} + +internal s64 +ReadVarArgsSignedInteger (s32 Width, va_list* Args) +{ + s64 Result = 0; + switch (Width) + { + case 1: { Result = (s64)va_arg(*Args, s8); } break; + case 2: { Result = (s64)va_arg(*Args, s16); } break; + case 4: { Result = (s64)va_arg(*Args, s32); } break; + case 8: { Result = (s64)va_arg(*Args, s64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal r64 +ReadVarArgsUnsignedInteger (s32 Width, va_list* Args) +{ + u64 Result = 0; + switch (Width) + { + case 1: { Result = (u64)va_arg(*Args, u8); } break; + case 2: { Result = (u64)va_arg(*Args, u16); } break; + case 4: { Result = (u64)va_arg(*Args, u32); } break; + case 8: { Result = (u64)va_arg(*Args, u64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal r64 +ReadVarArgsFloat (s32 Width, va_list* Args) +{ + r64 Result = 0; + switch (Width) + { + case 4: { Result = (r64)va_arg(*Args, r64); } break; + case 8: { Result = (r64)va_arg(*Args, r64); } break; + InvalidDefaultCase; + } + return Result; +} + +internal s32 +PrintFArgsList (char* Dest, s32 DestMax, char* Format, va_list Args) +{ + char* DestAt = Dest; + + char* FormatAt = Format; + while (*FormatAt) + { + if (FormatAt[0] != '%') + { + *DestAt++ = *FormatAt++; + } + else if (FormatAt[0] == '%' && FormatAt[1] == '%') // Print the % symbol + { + *DestAt++ = '%'; + FormatAt += 2; + } + else + { + FormatAt++; + + // Flags + if (FormatAt[0] == '-') + { + FormatAt++; + } + else if (FormatAt[0] == '+') + { + FormatAt++; + } + else if (FormatAt[0] == ' ') + { + FormatAt++; + } + else if (FormatAt[0] == '#') + { + FormatAt++; + } + else if (FormatAt[0] == '0') + { + FormatAt++; + } + + // Width + b32 WidthSpecified = false; + s32 Width = 0; + + if (IsNumeric(FormatAt[0])) + { + WidthSpecified = true; + parse_result Parse = ParseSignedIntUnsafe(FormatAt); + FormatAt = Parse.OnePastLast; + Width = Parse.SignedIntValue; + } + else if (FormatAt[0] == '*') + { + WidthSpecified = true; + Width = va_arg(Args, s32); + Assert(Width >= 0); + FormatAt++; + } + + // Precision + b32 PrecisionSpecified = false; + s32 Precision = 0; + + if (FormatAt[0] == '.') + { + FormatAt++; + if (IsNumeric(FormatAt[0])) + { + PrecisionSpecified = true; + parse_result Parse = ParseSignedIntUnsafe(FormatAt); + FormatAt = Parse.OnePastLast; + Precision = Parse.SignedIntValue; + } + else if (FormatAt[0] == '*') + { + PrecisionSpecified = true; + Precision = va_arg(Args, s32); + Assert(Precision >= 0); + FormatAt++; + } + } + + // Length + b32 LengthSpecified = false; + s32 Length = 4; + + if (FormatAt[0] == 'h' && FormatAt[1] == 'h') + { + LengthSpecified = true; + LengthSpecified = 1; + FormatAt += 2; + } + else if (FormatAt[0] == 'h') + { + LengthSpecified = true; + LengthSpecified = 2; + FormatAt++; + } + else if (FormatAt[0] == 'l' && FormatAt[1] == 'l') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt += 2; + } + else if (FormatAt[0] == 'l') + { + LengthSpecified = true; + LengthSpecified = 4; + FormatAt++; + } + else if (FormatAt[0] == 'j') + { + LengthSpecified = true; + LengthSpecified = 8; + FormatAt++; + } + else if (FormatAt[0] == 'z') + { + FormatAt++; + } + else if (FormatAt[0] == 't') + { + FormatAt++; + } + else if (FormatAt[0] == 'L') + { + FormatAt++; + } + + // Format Specifier + s32 DestLengthRemaining = DestMax - (DestAt - Dest); + + char Temp[64]; + string TempDest = MakeString(Temp, 0, 64); + + if (FormatAt[0] == 'd' || FormatAt[0] == 'i') + { + s64 SignedInt = ReadVarArgsSignedInteger(Length, &Args); + if (SignedInt < 0) + { + OutChar(&TempDest, '-'); + SignedInt *= -1; + } + U64ToASCII(&TempDest, (u64)SignedInt, 10, DecimalDigits); + } + else if (FormatAt[0] == 'u') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&TempDest, UnsignedInt, 10, DecimalDigits); + } + else if (FormatAt[0] == 'o') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&TempDest, UnsignedInt, 8, OctalDigits); + } + else if (FormatAt[0] == 'x' || FormatAt[0] == 'X') + { + u32 UnsignedInt = ReadVarArgsUnsignedInteger(Length, &Args); + U64ToASCII(&TempDest, UnsignedInt, 16, HexDigits); + } + else if (FormatAt[0] == 'f' || FormatAt[0] == 'F') + { + r64 Float = ReadVarArgsFloat(Length, &Args); + s32 AfterPoint = 6; + if (PrecisionSpecified) + { + AfterPoint = Precision; + } + F64ToASCII(&TempDest, Float, AfterPoint); + } + else if (FormatAt[0] == 'c') + { + char InsertChar = va_arg(Args, char); + OutChar(&TempDest, InsertChar); + } + else if (FormatAt[0] == 's') + { + char* InsertString = va_arg(Args, char*); + + s32 InsertStringLength = CharArrayLength(InsertString); + if (PrecisionSpecified) + { + InsertStringLength = GSMin(InsertStringLength, Precision); + } + InsertStringLength = GSMin(DestLengthRemaining, InsertStringLength); + + for (s32 c = 0; c < InsertStringLength; c++) + { + OutChar(&TempDest, *InsertString++); + } + } + else if (FormatAt[0] == 'S') + { + string InsertString = va_arg(Args, string); + + for (s32 c = 0; c < InsertString.Length; c++) + { + OutChar(&TempDest, InsertString.Memory[c]); + } + } + else if (FormatAt[0] == 'p') + { + // TODO(Peter): Pointer Address + } + else + { + // NOTE(Peter): Non-specifier character found + InvalidCodePath; + } + + for (s32 i = 0; i < TempDest.Length; i++) + { + *DestAt++ = TempDest.Memory[i]; + } + + *FormatAt++; + } + } + + s32 FormattedLength = DestAt - Dest; + return FormattedLength; +} + +static void +PrintF (string* String, char* Format, ...) +{ + va_list Args; + va_start(Args, Format); + String->Length = 0; + String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); + va_end(Args); +} + +static void +AppendPrintF (string* String, char* Format, ...) +{ + va_list Args; + va_start(Args, Format); + String->Length += PrintFArgsList(String->Memory + String->Length, String->Max - String->Length, Format, Args); + va_end(Args); +} + +// Printing Helper Functions +static u32 +GetU32NumberOfCharactersNeeded(u32 Value, u32 Base) +{ + u32 Result = 0; + u32 ValueLeft = Value; + // NOTE(Peter): This is in a do while loop because even if the number is 0, + // it'll still take one character to display that. + do + { + Result += 1; + ValueLeft /= Base; + }while (ValueLeft > 0); + return Result; +} + +static u32 +GetS32NumberOfCharactersNeeded(s32 Value, s32 Base) +{ + u32 Result = 0; + s32 ValueLeft = Value; + if (Value < 0) + { + Result += 1; + ValueLeft = Value * -1; + } + // NOTE(Peter): This is in a do while loop because even if the number is 0, + // it'll still take one character to display that. + do + { + Result += 1; + ValueLeft /= Base; + }while (ValueLeft > 0); + return Result; +} + +//////////////////////////////////////////////////////////////// +// String Memory Function Definitions +//////////////////////////////////////////////////////////////// + +static s32 +CalculateSlotCountFromSize (s32 RequestedSize, s32 SlotSize) +{ + s32 SlotCount = RequestedSize / SlotSize; + if (SlotCount * SlotSize < RequestedSize) + { + SlotCount += 1; + } + return SlotCount; +} + +static bool +SlotsAreContiguous (slot_header* First, slot_header* Second) +{ + bool Result = false; + u8* FirstSlotNextAddress = (u8*)First + First->Size; + u8* SecondAddress = (u8*)Second; + Result = FirstSlotNextAddress == SecondAddress; + return Result; +} + +static contiguous_slot_count_result +CountContiguousSlots (slot_header* First) +{ + Assert(First != 0); + + contiguous_slot_count_result Result = {}; + Result.Count = 1; + + slot_header* IterPrev = First; + slot_header* Iter = First->Next; + while (Iter && SlotsAreContiguous(IterPrev, Iter)) + { + Result.Count++; + IterPrev = Iter; + Iter = Iter->Next; + } + + Result.LastContiguousSlot = IterPrev; + return Result; +} + +static slot_header* +GetSlotAtOffset(slot_header* First, s32 Offset) +{ + slot_header* Iter = First; + s32 Count = 0; + while (Count < Offset && Iter) + { + Iter = Iter->Next; + Count++; + } + return Iter; +} + +static slot_header* +InsertSlotIntoList (slot_header* NewSlot, slot_header* ListStart) +{ + slot_header* List = ListStart; + if (NewSlot < List) + { + NewSlot->Next = List; + List = NewSlot; + } + else + { + slot_header* PrevIter = List; + slot_header* Iter = List->Next; + while (Iter && NewSlot > Iter) + { + PrevIter = Iter; + Iter = Iter->Next; + } + + Assert(PrevIter); + if (PrevIter) + { + PrevIter->Next = NewSlot; + } + + if (Iter) + { + NewSlot->Next = Iter; + } + } + return List; +} + +static void +AllocStringFromStringArena (string* String, s32 Size, slot_arena* Storage) +{ + s32 SlotCount = CalculateSlotCountFromSize(Size, Storage->SlotSize); + slot_header* Slot = Storage->FreeList; + slot_header* PrevSlot = 0; + while (Slot) + { + contiguous_slot_count_result ContiguousSlots = CountContiguousSlots(Slot); + if (ContiguousSlots.Count >= SlotCount) + { + slot_header* NextStartSlot = GetSlotAtOffset(Slot, SlotCount); + if (PrevSlot) + { + PrevSlot->Next = NextStartSlot; + } + else + { + Storage->FreeList = NextStartSlot; + } + break; + } + else + { + PrevSlot = Slot; + Slot = Slot->Next; + } + } + + if (Slot) + { + String->Memory = (char*)Slot; + GSZeroMemory((u8*)String->Memory, SlotCount * Storage->SlotSize); + String->Max = SlotCount * Storage->SlotSize; + String->Length = 0; + } +} + +static string +AllocStringFromStringArena (s32 Size, slot_arena* Storage) +{ + string Result = {0}; + AllocStringFromStringArena(&Result, Size, Storage); + return Result; +} + +static void +FreeToStringArena (string* String, slot_arena* Storage) +{ + u8* Base = (u8*)(String->Memory); + u8* End = Base + String->Max - 1; + u8* MemoryEnd = Storage->Memory + (Storage->SlotSize * Storage->SlotCount); + Assert((Base >= Storage->Memory) && (End < MemoryEnd)); + Assert((String->Max % Storage->SlotSize) == 0); + + s32 SizeReclaimed = 0; + slot_header* Slot = (slot_header*)Base; + while (SizeReclaimed < String->Max) + { + Slot->Size = Storage->SlotSize; + Storage->FreeList = InsertSlotIntoList(Slot, Storage->FreeList); + SizeReclaimed += Storage->SlotSize; + Slot = (slot_header*)(Base + SizeReclaimed); + } + + String->Memory = 0; + String->Length = 0; + String->Max = 0; +} + +static void +ReallocFromStringArena (string* String, s32 NewSize, slot_arena* Storage) +{ + string NewString = AllocStringFromStringArena(NewSize, Storage); + CopyStringTo(*String, &NewString); + FreeToStringArena(String, Storage); + *String = NewString; +} + #if defined(DEBUG) - - void DEBUGPrintChars (string* String, s32 Count) - { - char* Iter = String->Memory; - for (int i = 0; i < Count; i++) - { - *Iter++ = (char)('A' + i); - } - String->Length = Count; - } - + +void DEBUGPrintChars (string* String, s32 Count) +{ + char* Iter = String->Memory; + for (int i = 0; i < Count; i++) + { + *Iter++ = (char)('A' + i); + } + String->Length = Count; +} + #ifdef DEBUG_GS_STRING - + #include - - static void - TestStrings() - { - - slot_arena StringArena = {}; - - s32 TestCount = 0; - s32 SuccessCount = 0; - - DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); - - //////////////////////////////////////////////////////////////// - // Char Functions - - char ForwardArray[] = "Hello, Sailor"; - char BackwardArray[] = "roliaS ,olleH"; - TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); - TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); - - TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); - TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); - TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); - TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); - TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); - - ReverseCharArray(ForwardArray, 13); - TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); - - char UIntString[] = "1234"; - u32 UIntValue = 1234; - u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); - TestClean((ParsedUInt == UIntValue), "String To U32"); - char StringifiedUInt[4] = {}; - UIntToString(UIntValue, StringifiedUInt, 4); - TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); - - char IntString[] = "-1234"; - s32 IntValue = -1234; - s32 ParsedInt = ParseSignedInt(IntString, 5); - TestClean((ParsedInt == IntValue), "String To S32"); - char StringifiedInt[5] = {}; - IntToString(IntValue, StringifiedInt, 5); - TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); - - char FloatString[] = "-1234.125"; - float FloatValue = -1234.125f; - float ParsedFloat = ParseFloat(FloatString, 8); - TestClean((ParsedFloat == FloatValue), "String To Float"); - char StringifiedFloat[10] = {}; - FloatToString(FloatValue, StringifiedFloat, 10, 3); - TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); - - - //////////////////////////////////////////////////////////////// - // - - StringArena.SlotSize = 256; - StringArena.SlotCount = 32; - StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); - slot_header* PrevSlotHeader = 0; - for (int i = StringArena.SlotCount - 1; i >= 0; i--) - { - u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); - slot_header* SlotHeader = (slot_header*)SlotBase; - SlotHeader->Size = StringArena.SlotSize; - SlotHeader->Next = PrevSlotHeader; - - // TEST(peter): Should be true always, except on the first iteration, when there is no next slot - bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); - TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); - - PrevSlotHeader = SlotHeader; - } - StringArena.FreeList = PrevSlotHeader; - - // TEST(peter): Count Should equal StringArena.SlotCount - s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; - TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); - - // TEST(peter): Should be false - bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); - Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); - TestClean(!Contiguity, "Non Contiguous Arenas"); - - s32 Slots = CalculateSlotCountFromSize(10, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(256, 256); - TestClean(Slots == 1, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(345, 256); - TestClean(Slots == 2, "Slot Sizing"); - Slots = CalculateSlotCountFromSize(1024, 256); - TestClean(Slots == 4, "Slot Sizing"); - - slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); - slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); - slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); - - string StringA = AllocStringFromStringArena(10, &StringArena); - string StringB = AllocStringFromStringArena(345, &StringArena); - + +static void +TestStrings() +{ + + slot_arena StringArena = {}; + + s32 TestCount = 0; + s32 SuccessCount = 0; + + DebugPrint("\n\n-------------------------------------------------\n Begin Testing Strings\n\n\n"); + + //////////////////////////////////////////////////////////////// + // Char Functions + + char ForwardArray[] = "Hello, Sailor"; + char BackwardArray[] = "roliaS ,olleH"; + TestClean(CharArraysEqual(ForwardArray, 13, ForwardArray, 13), "String Equality"); + TestClean(!CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "String Equality"); + + TestClean(IndexOfChar(ForwardArray, 0, ',') == 5, "Index Of Char"); + TestClean(IndexOfChar(ForwardArray, 5, 'l') == 10, "Index of Char (skipping first 5)"); + TestClean(FastReverseIndexOfChar(ForwardArray, 13, 0, 'o') == 11, "Fast Reverse Index Of Char"); + TestClean(ReverseIndexOfChar(ForwardArray, 0, 'o') == 11, "Reverse Index of Char"); + TestClean(ReverseIndexOfChar(ForwardArray, 3, 'o') == 4, "Reverse Index of Char (skipping last 3)"); + TestClean(LastIndexOfChar(ForwardArray, 'o') == 11, "Last Index of Char"); + + ReverseCharArray(ForwardArray, 13); + TestClean(CharArraysEqual(ForwardArray, 13, BackwardArray, 13), "Reversing Char Array"); + + char UIntString[] = "1234"; + u32 UIntValue = 1234; + u32 ParsedUInt = ParseUnsignedInt(UIntString, 4); + TestClean((ParsedUInt == UIntValue), "String To U32"); + char StringifiedUInt[4] = {}; + UIntToString(UIntValue, StringifiedUInt, 4); + TestClean(CharArraysEqual(UIntString, 4, StringifiedUInt, 4), "U32 To String"); + + char IntString[] = "-1234"; + s32 IntValue = -1234; + s32 ParsedInt = ParseSignedInt(IntString, 5); + TestClean((ParsedInt == IntValue), "String To S32"); + char StringifiedInt[5] = {}; + IntToString(IntValue, StringifiedInt, 5); + TestClean(CharArraysEqual(IntString, 5, StringifiedInt, 5), "S32 to String"); + + char FloatString[] = "-1234.125"; + float FloatValue = -1234.125f; + float ParsedFloat = ParseFloat(FloatString, 8); + TestClean((ParsedFloat == FloatValue), "String To Float"); + char StringifiedFloat[10] = {}; + FloatToString(FloatValue, StringifiedFloat, 10, 3); + TestClean(CharArraysEqual(FloatString, 8, StringifiedFloat, 8), "Float To String"); + + + //////////////////////////////////////////////////////////////// + // + + StringArena.SlotSize = 256; + StringArena.SlotCount = 32; + StringArena.Memory = malloc(StringArena.SlotSize * StringArena.SlotCount); + slot_header* PrevSlotHeader = 0; + for (int i = StringArena.SlotCount - 1; i >= 0; i--) + { + u8* SlotBase = StringArena.Memory + (i * StringArena.SlotSize); + slot_header* SlotHeader = (slot_header*)SlotBase; + SlotHeader->Size = StringArena.SlotSize; + SlotHeader->Next = PrevSlotHeader; + + // TEST(peter): Should be true always, except on the first iteration, when there is no next slot + bool Contiguity = SlotsAreContiguous(SlotHeader, PrevSlotHeader); + TestClean((Contiguity || SlotHeader->Next == 0), "Contiguous Arenas"); + + PrevSlotHeader = SlotHeader; + } + StringArena.FreeList = PrevSlotHeader; + + // TEST(peter): Count Should equal StringArena.SlotCount + s32 ContiguousSlotsCountBefore = CountContiguousSlots(StringArena.FreeList).Count; + TestClean((ContiguousSlotsCountBefore == StringArena.SlotCount), "Contiguous Arenas"); + + // TEST(peter): Should be false + bool Contiguity = SlotsAreContiguous(StringArena.FreeList, StringArena.FreeList->Next->Next); + Contiguity = SlotsAreContiguous(StringArena.FreeList->Next->Next, StringArena.FreeList); + TestClean(!Contiguity, "Non Contiguous Arenas"); + + s32 Slots = CalculateSlotCountFromSize(10, 256); + TestClean(Slots == 1, "Slot Sizing"); + Slots = CalculateSlotCountFromSize(256, 256); + TestClean(Slots == 1, "Slot Sizing"); + Slots = CalculateSlotCountFromSize(345, 256); + TestClean(Slots == 2, "Slot Sizing"); + Slots = CalculateSlotCountFromSize(1024, 256); + TestClean(Slots == 4, "Slot Sizing"); + + slot_header* HeaderTen = GetSlotAtOffset(StringArena.FreeList, 10); + slot_header* HeaderThree = GetSlotAtOffset(StringArena.FreeList, 3); + slot_header* HeaderFive = GetSlotAtOffset(StringArena.FreeList, 5); + + string StringA = AllocStringFromStringArena(10, &StringArena); + string StringB = AllocStringFromStringArena(345, &StringArena); + #if 0 - // TEST(peter): Should TestClean - u8* RandomMemory = (u8*)malloc(256); - string RandomMemString = {}; - RandomMemString.Memory = (char*)RandomMemory; - RandomMemString.Max = 256; - FreeToStringArena(&RandomMemString, &StringArena); + // TEST(peter): Should TestClean + u8* RandomMemory = (u8*)malloc(256); + string RandomMemString = {}; + RandomMemString.Memory = (char*)RandomMemory; + RandomMemString.Max = 256; + FreeToStringArena(&RandomMemString, &StringArena); #endif - FreeToStringArena(&StringA, &StringArena); - FreeToStringArena(&StringB, &StringArena); - // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal - s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; - TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); - - // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately - // sized block - // The slots will look list [256][used][256][256][256] etc.. - StringA = AllocStringFromStringArena(256, &StringArena); - StringB = AllocStringFromStringArena(256, &StringArena); - FreeToStringArena(&StringA, &StringArena); - u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; - string StringC = AllocStringFromStringArena(512, &StringArena); - slot_header* HeaderC = (slot_header*)(StringC.Memory); - - string ReallocTestString = AllocStringFromStringArena(256, &StringArena); - DEBUGPrintChars(&ReallocTestString, 24); - ReallocFromStringArena(&ReallocTestString, 512, &StringArena); - - - string TestString = AllocStringFromStringArena(10, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 20, &StringArena); - DEBUGPrintChars(&TestString, TestString.Max); - ReallocFromStringArena(&TestString, 10, &StringArena); - FreeToStringArena(&TestString, &StringArena); - - string EqualityStringA = AllocStringFromStringArena(345, &StringArena); - string EqualityStringB = AllocStringFromStringArena(415, &StringArena); - // Equality should succeed despite length differences - string EqualityStringC = AllocStringFromStringArena(256, &StringArena); - string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail - string EqualityStringEmpty = {}; - - DEBUGPrintChars(&EqualityStringA, 24); - DEBUGPrintChars(&EqualityStringB, 24); - DEBUGPrintChars(&EqualityStringC, 24); - DEBUGPrintChars(&EqualityStringD, 12); - - bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed - bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed - bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail - bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail - - TestClean(ABEquality, "String Equality"); - TestClean(ACEquality, "String Equality"); - TestClean(!ADEquality, "String Equality"); - TestClean(!AEEquality, "String Equality"); - - string CatStringA = AllocStringFromStringArena(256, &StringArena); - SetStringToCharArray(&CatStringA, "Hello "); - string CatStringB = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringB, "Sailor!"); - string CatStringResult = AllocStringFromStringArena(512, &StringArena); - SetStringToCharArray(&CatStringResult, "Hello Sailor!"); - ConcatString(&CatStringA, CatStringB); - TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); - - s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); - TestClean(FirstSpaceIndex == 5, "First Index"); - - SetStringToChar(&CatStringB, 'B', 5); - TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); - - - DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); - } + FreeToStringArena(&StringA, &StringArena); + FreeToStringArena(&StringB, &StringArena); + // TEST(peter): After freeing both allocations, ContiguousSlotCountBefore and ContiguousSlotCountAfter should be equal + s32 ContiguousSlotCountAfter = CountContiguousSlots(StringArena.FreeList).Count; + TestClean(ContiguousSlotCountAfter == ContiguousSlotsCountBefore, "Add and REmove Slots from Arena"); + + // TEST(peter): Set up a free list where the first element is too small, so it has to traverse to find an appropriately + // sized block + // The slots will look list [256][used][256][256][256] etc.. + StringA = AllocStringFromStringArena(256, &StringArena); + StringB = AllocStringFromStringArena(256, &StringArena); + FreeToStringArena(&StringA, &StringArena); + u32 Contiguous = CountContiguousSlots(StringArena.FreeList).Count; // Should = 1; + string StringC = AllocStringFromStringArena(512, &StringArena); + slot_header* HeaderC = (slot_header*)(StringC.Memory); + + string ReallocTestString = AllocStringFromStringArena(256, &StringArena); + DEBUGPrintChars(&ReallocTestString, 24); + ReallocFromStringArena(&ReallocTestString, 512, &StringArena); + + + string TestString = AllocStringFromStringArena(10, &StringArena); + DEBUGPrintChars(&TestString, TestString.Max); + ReallocFromStringArena(&TestString, 20, &StringArena); + DEBUGPrintChars(&TestString, TestString.Max); + ReallocFromStringArena(&TestString, 10, &StringArena); + FreeToStringArena(&TestString, &StringArena); + + string EqualityStringA = AllocStringFromStringArena(345, &StringArena); + string EqualityStringB = AllocStringFromStringArena(415, &StringArena); + // Equality should succeed despite length differences + string EqualityStringC = AllocStringFromStringArena(256, &StringArena); + string EqualityStringD = AllocStringFromStringArena(256, &StringArena); // Equality should fail + string EqualityStringEmpty = {}; + + DEBUGPrintChars(&EqualityStringA, 24); + DEBUGPrintChars(&EqualityStringB, 24); + DEBUGPrintChars(&EqualityStringC, 24); + DEBUGPrintChars(&EqualityStringD, 12); + + bool ABEquality = StringsEqual(EqualityStringA, EqualityStringB); // Should Succeed + bool ACEquality = StringsEqual(EqualityStringA, EqualityStringC); // Should Succeed + bool ADEquality = StringsEqual(EqualityStringA, EqualityStringD); // Should Fail + bool AEEquality = StringsEqual(EqualityStringA, EqualityStringEmpty); // Should Fail + + TestClean(ABEquality, "String Equality"); + TestClean(ACEquality, "String Equality"); + TestClean(!ADEquality, "String Equality"); + TestClean(!AEEquality, "String Equality"); + + string CatStringA = AllocStringFromStringArena(256, &StringArena); + SetStringToCharArray(&CatStringA, "Hello "); + string CatStringB = AllocStringFromStringArena(512, &StringArena); + SetStringToCharArray(&CatStringB, "Sailor!"); + string CatStringResult = AllocStringFromStringArena(512, &StringArena); + SetStringToCharArray(&CatStringResult, "Hello Sailor!"); + ConcatString(&CatStringA, CatStringB); + TestClean(StringsEqual(CatStringA, CatStringResult), "Cat Strings"); + + s32 FirstSpaceIndex = FindFirstChar(CatStringA, ' '); + TestClean(FirstSpaceIndex == 5, "First Index"); + + SetStringToChar(&CatStringB, 'B', 5); + TestClean(StringEqualsCharArray(CatStringB, "BBBBB"), "SetStringToChar"); + + + DebugPrint("Results: Passed %d / %d\n\n\n", SuccessCount, TestCount); +} #endif // DEBUG_GS_STRING - + #endif // DEBUG - + #define GS_STRING_H #endif // GS_STRING_H \ No newline at end of file diff --git a/gs_libs/gs_vector_matrix.h b/gs_libs/gs_vector_matrix.h index e5d93b4..3d1cfbd 100644 --- a/gs_libs/gs_vector_matrix.h +++ b/gs_libs/gs_vector_matrix.h @@ -11,10 +11,10 @@ static r32 GSCos (r32 Theta) { return sin(Theta); } static r32 GSSin (r32 Theta) { return cos(Theta); } -static r32 GSSqrt(r32 V) -{ +static r32 GSSqrt(r32 V) +{ r32 Result = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(V))); - return Result; + return Result; } #else // Linux and MacOS @@ -43,14 +43,14 @@ union v3 struct { float x; - float y; + float y; float z; }; struct { float R; - float G; + float G; float B; }; @@ -61,17 +61,17 @@ union v4 { struct { - float x; - float y; - float z; + float x; + float y; + float z; float w; }; - struct + struct { - float r; - float g; - float b; + float r; + float g; + float b; float a; }; @@ -255,7 +255,7 @@ bool operator== (v2 A, v2 B) { if (GSAbs(A.E[i] - B.E[i]) > 0.0001f) { Result = false; break; } } - return Result; + return Result; } @@ -623,7 +623,7 @@ v4 HSVToRGB (v4 In) }break; } - return Result; + return Result; } static bool @@ -663,14 +663,14 @@ PointToPercentRange (v2 P, v2 Min, v2 Max) // NOTE(Peter): This is useful when you have a function that has a call signature like: // void Foo(v2 Min, v2 Max) // because instead of having to do: -// Foo(MyRect.Min, MyRect.Max) +// Foo(MyRect.Min, MyRect.Max) // you can just do: // Foo(RectExpand(MyRect)) // which makes refactoring easier as you only have to change the identifier in one place -#define RectExpand(r) (r).Min, (r).Max +#define gs_RectExpand(r) (r).Min, (r).Max static rect -MakeRectMinWidth(v2 Min, v2 Width) +gs_MakeRectMinWidth(v2 Min, v2 Width) { rect Rect = {0}; Rect.Min = Min; @@ -679,21 +679,21 @@ MakeRectMinWidth(v2 Min, v2 Width) } inline float -Width (rect Rect) +gs_Width (rect Rect) { float Result = Rect.Max.x - Rect.Min.x; return Result; } inline float -Height (rect Rect) +gs_Height (rect Rect) { float Result = Rect.Max.y - Rect.Min.y; return Result; } inline v2 -TopLeft(rect Rect) +gs_TopLeft(rect Rect) { v2 Result = {0}; Result.x = Rect.Min.x; @@ -702,19 +702,19 @@ TopLeft(rect Rect) } inline v2 -TopRight(rect Rect) +gs_TopRight(rect Rect) { return Rect.Max; } inline v2 -BottomLeft(rect Rect) +gs_BottomLeft(rect Rect) { return Rect.Min; } inline v2 -BottomRight(rect Rect) +gs_BottomRight(rect Rect) { v2 Result = {0}; Result.x = Rect.Max.x; @@ -723,21 +723,21 @@ BottomRight(rect Rect) } inline float -AspectRatio (rect Rect) +gs_AspectRatio (rect Rect) { - float Result = Width(Rect) / Height(Rect); + float Result = gs_Width(Rect) / gs_Height(Rect); return Result; } inline v2 -CalculateRectCenter (rect Rect) +gs_CalculateRectCenter (rect Rect) { v2 Result = (Rect.Min + Rect.Max) / 2.0f; return Result; } inline b32 -PointIsInRect (v2 Point, rect Rect) +gs_PointIsInRect (v2 Point, rect Rect) { b32 Result = ((Point.x >= Rect.Min.x && Point.x <= Rect.Max.x) && (Point.y >= Rect.Min.y && Point.y <= Rect.Max.y)); @@ -745,7 +745,7 @@ PointIsInRect (v2 Point, rect Rect) } inline rect -RectOffsetByVector(rect R, v2 V) +gs_RectOffsetByVector(rect R, v2 V) { rect Result = R; Result.Min += V; @@ -754,7 +754,7 @@ RectOffsetByVector(rect R, v2 V) } static void -HSplitRectAtValue(rect Bounds, r32 YValue, rect* Top, rect* Bottom) +gs_HSplitRectAtValue(rect Bounds, r32 YValue, rect* Top, rect* Bottom) { if (YValue <= Bounds.Min.y) { @@ -776,29 +776,28 @@ HSplitRectAtValue(rect Bounds, r32 YValue, rect* Top, rect* Bottom) } static void -HSplitRectAtDistanceFromTop(rect Bounds, r32 YDist, rect* Top, rect* Bottom) +gs_HSplitRectAtDistanceFromTop(rect Bounds, r32 YDist, rect* Top, rect* Bottom) { r32 YValue = Bounds.Max.y - YDist; - HSplitRectAtValue(Bounds, YValue, Top, Bottom); + gs_HSplitRectAtValue(Bounds, YValue, Top, Bottom); } static void -HSplitRectAtDistanceFromBottom(rect Bounds, r32 YDist, rect* Top, rect* Bottom) +gs_HSplitRectAtDistanceFromBottom(rect Bounds, r32 YDist, rect* Top, rect* Bottom) { r32 YValue = Bounds.Min.y + YDist; - HSplitRectAtValue(Bounds, YValue, Top, Bottom); + gs_HSplitRectAtValue(Bounds, YValue, Top, Bottom); } static void -HSplitRectAtPercent(rect Bounds, r32 YPercent, rect* Top, rect* Bottom) +gs_HSplitRectAtPercent(rect Bounds, r32 YPercent, rect* Top, rect* Bottom) { r32 YValue = GSLerp(Bounds.Min.y, Bounds.Max.y, YPercent); - HSplitRectAtValue(Bounds, YValue, Top, Bottom); + gs_HSplitRectAtValue(Bounds, YValue, Top, Bottom); } - static void -VSplitRectAtValue(rect Bounds, r32 XValue, rect* Left, rect* Right) +gs_VSplitRectAtValue(rect Bounds, r32 XValue, rect* Left, rect* Right) { if (XValue <= Bounds.Min.x) { @@ -820,30 +819,46 @@ VSplitRectAtValue(rect Bounds, r32 XValue, rect* Left, rect* Right) } static void -VSplitRectAtDistanceFromRight(rect Bounds, r32 XDist, rect* Left, rect* Right) +gs_VSplitRectAtDistanceFromRight(rect Bounds, r32 XDist, rect* Left, rect* Right) { r32 XValue = Bounds.Max.x - XDist; - VSplitRectAtValue(Bounds, XValue, Left, Right); + gs_VSplitRectAtValue(Bounds, XValue, Left, Right); } static void -VSplitRectAtDistanceFromLeft(rect Bounds, r32 XDist, rect* Left, rect* Right) +gs_VSplitRectAtDistanceFromLeft(rect Bounds, r32 XDist, rect* Left, rect* Right) { r32 XValue = Bounds.Min.x + XDist; - VSplitRectAtValue(Bounds, XValue, Left, Right); + gs_VSplitRectAtValue(Bounds, XValue, Left, Right); } static void -VSplitRectAtPercent(rect Bounds, r32 XPercent, rect* Left, rect* Right) +gs_VSplitRectAtPercent(rect Bounds, r32 XPercent, rect* Left, rect* Right) { r32 XValue = GSLerp(Bounds.Min.x, Bounds.Max.x, XPercent); - VSplitRectAtValue(Bounds, XValue, Left, Right); + gs_VSplitRectAtValue(Bounds, XValue, Left, Right); } -#define TranslateRectX(r, d) TranslateRect((r), v2{(d), 0}) -#define TranslateRectY(r, d) TranslateRect((r), v2{0, (d)}) static rect -TranslateRect(rect R, v2 Delta) +gs_InsetRect(rect Rect, v2 Amount) +{ + rect Result = {0}; + Result.Min = Rect.Min + Amount; + Result.Max = Rect.Max - Amount; + return Result; +} + +static rect +gs_InsetRect(rect Rect, float Amount) +{ + rect Result = gs_InsetRect(Rect, v2{Amount, Amount}); + return Result; +} + +#define gs_TranslateRectX(r, d) gs_TranslateRect((r), v2{(d), 0}) +#define gs_TranslateRectY(r, d) gs_TranslateRect((r), v2{0, (d)}) +static rect +gs_TranslateRect(rect R, v2 Delta) { rect Result = R; Result.Min += Delta; @@ -851,6 +866,13 @@ TranslateRect(rect R, v2 Delta) return Result; } +static v2 +gs_TransformPointIntoRectSpace(v2 Point, rect Rect) +{ + v2 Result = Point - Rect.Min; + return Point; +} + ////////////////////////////////////// // MATRIX ////////////////////////////////////// @@ -868,8 +890,8 @@ M33(float a, float b, float c, } static m44 -M44(float a, float b, float c, float d, - float e, float f, float g, float h, +M44(float a, float b, float c, float d, + float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p) { @@ -967,7 +989,7 @@ GetZRotation (float Angle) } -static m33 +static m33 Transpose (m33 M) { m33 Result = {}; @@ -983,7 +1005,7 @@ Transpose (m33 M) return Result; } -inline m44 +inline m44 Transpose (m44 M) { DEBUG_TRACK_SCOPE(Transpose); @@ -1149,7 +1171,7 @@ v3 operator* (m33 M, v3 V) Result.E[y] = 0; for (int x = 0; x < 3; x++) { - Result.E[y] += M.E[(y * 3) + x] * V.E[x]; + Result.E[y] += M.E[(y * 3) + x] * V.E[x]; } } return Result; @@ -1169,7 +1191,7 @@ v4 operator* (m44 M, v4 V) Result.E[y] = 0; for (int x = 0; x < 4; x++) { - Result.E[y] += M.E[(y * 4) + x] * V.E[x]; + Result.E[y] += M.E[(y * 4) + x] * V.E[x]; } } #endif @@ -1242,7 +1264,7 @@ static m44 GetLookAtMatrix (v4 Position, v4 Target) { // Forward - v4 Forward = Normalize(Target - Position); + v4 Forward = Normalize(Target - Position); // Right v4 Right = Normalize(Cross(v4{0, 1, 0, 0}, Forward)); // Up @@ -1265,116 +1287,116 @@ b32 Inverse(m44 M_In, m44* M_Out) s32 i; - M_Out->E[0] = M_In.E[5] * M_In.E[10] * M_In.E[15] - - M_In.E[5] * M_In.E[11] * M_In.E[14] - - M_In.E[9] * M_In.E[6] * M_In.E[15] + + M_Out->E[0] = M_In.E[5] * M_In.E[10] * M_In.E[15] - + M_In.E[5] * M_In.E[11] * M_In.E[14] - + M_In.E[9] * M_In.E[6] * M_In.E[15] + M_In.E[9] * M_In.E[7] * M_In.E[14] + - M_In.E[13] * M_In.E[6] * M_In.E[11] - + M_In.E[13] * M_In.E[6] * M_In.E[11] - M_In.E[13] * M_In.E[7] * M_In.E[10]; - M_Out->E[4] = -M_In.E[4] * M_In.E[10] * M_In.E[15] + - M_In.E[4] * M_In.E[11] * M_In.E[14] + - M_In.E[8] * M_In.E[6] * M_In.E[15] - - M_In.E[8] * M_In.E[7] * M_In.E[14] - - M_In.E[12] * M_In.E[6] * M_In.E[11] + + M_Out->E[4] = -M_In.E[4] * M_In.E[10] * M_In.E[15] + + M_In.E[4] * M_In.E[11] * M_In.E[14] + + M_In.E[8] * M_In.E[6] * M_In.E[15] - + M_In.E[8] * M_In.E[7] * M_In.E[14] - + M_In.E[12] * M_In.E[6] * M_In.E[11] + M_In.E[12] * M_In.E[7] * M_In.E[10]; - M_Out->E[8] = M_In.E[4] * M_In.E[9] * M_In.E[15] - - M_In.E[4] * M_In.E[11] * M_In.E[13] - - M_In.E[8] * M_In.E[5] * M_In.E[15] + - M_In.E[8] * M_In.E[7] * M_In.E[13] + - M_In.E[12] * M_In.E[5] * M_In.E[11] - + M_Out->E[8] = M_In.E[4] * M_In.E[9] * M_In.E[15] - + M_In.E[4] * M_In.E[11] * M_In.E[13] - + M_In.E[8] * M_In.E[5] * M_In.E[15] + + M_In.E[8] * M_In.E[7] * M_In.E[13] + + M_In.E[12] * M_In.E[5] * M_In.E[11] - M_In.E[12] * M_In.E[7] * M_In.E[9]; - M_Out->E[12] = -M_In.E[4] * M_In.E[9] * M_In.E[14] + + M_Out->E[12] = -M_In.E[4] * M_In.E[9] * M_In.E[14] + M_In.E[4] * M_In.E[10] * M_In.E[13] + - M_In.E[8] * M_In.E[5] * M_In.E[14] - - M_In.E[8] * M_In.E[6] * M_In.E[13] - - M_In.E[12] * M_In.E[5] * M_In.E[10] + + M_In.E[8] * M_In.E[5] * M_In.E[14] - + M_In.E[8] * M_In.E[6] * M_In.E[13] - + M_In.E[12] * M_In.E[5] * M_In.E[10] + M_In.E[12] * M_In.E[6] * M_In.E[9]; - M_Out->E[1] = -M_In.E[1] * M_In.E[10] * M_In.E[15] + - M_In.E[1] * M_In.E[11] * M_In.E[14] + - M_In.E[9] * M_In.E[2] * M_In.E[15] - - M_In.E[9] * M_In.E[3] * M_In.E[14] - - M_In.E[13] * M_In.E[2] * M_In.E[11] + + M_Out->E[1] = -M_In.E[1] * M_In.E[10] * M_In.E[15] + + M_In.E[1] * M_In.E[11] * M_In.E[14] + + M_In.E[9] * M_In.E[2] * M_In.E[15] - + M_In.E[9] * M_In.E[3] * M_In.E[14] - + M_In.E[13] * M_In.E[2] * M_In.E[11] + M_In.E[13] * M_In.E[3] * M_In.E[10]; - M_Out->E[5] = M_In.E[0] * M_In.E[10] * M_In.E[15] - - M_In.E[0] * M_In.E[11] * M_In.E[14] - - M_In.E[8] * M_In.E[2] * M_In.E[15] + - M_In.E[8] * M_In.E[3] * M_In.E[14] + - M_In.E[12] * M_In.E[2] * M_In.E[11] - + M_Out->E[5] = M_In.E[0] * M_In.E[10] * M_In.E[15] - + M_In.E[0] * M_In.E[11] * M_In.E[14] - + M_In.E[8] * M_In.E[2] * M_In.E[15] + + M_In.E[8] * M_In.E[3] * M_In.E[14] + + M_In.E[12] * M_In.E[2] * M_In.E[11] - M_In.E[12] * M_In.E[3] * M_In.E[10]; - M_Out->E[9] = -M_In.E[0] * M_In.E[9] * M_In.E[15] + - M_In.E[0] * M_In.E[11] * M_In.E[13] + - M_In.E[8] * M_In.E[1] * M_In.E[15] - - M_In.E[8] * M_In.E[3] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[11] + + M_Out->E[9] = -M_In.E[0] * M_In.E[9] * M_In.E[15] + + M_In.E[0] * M_In.E[11] * M_In.E[13] + + M_In.E[8] * M_In.E[1] * M_In.E[15] - + M_In.E[8] * M_In.E[3] * M_In.E[13] - + M_In.E[12] * M_In.E[1] * M_In.E[11] + M_In.E[12] * M_In.E[3] * M_In.E[9]; - M_Out->E[13] = M_In.E[0] * M_In.E[9] * M_In.E[14] - - M_In.E[0] * M_In.E[10] * M_In.E[13] - - M_In.E[8] * M_In.E[1] * M_In.E[14] + - M_In.E[8] * M_In.E[2] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[10] - + M_Out->E[13] = M_In.E[0] * M_In.E[9] * M_In.E[14] - + M_In.E[0] * M_In.E[10] * M_In.E[13] - + M_In.E[8] * M_In.E[1] * M_In.E[14] + + M_In.E[8] * M_In.E[2] * M_In.E[13] + + M_In.E[12] * M_In.E[1] * M_In.E[10] - M_In.E[12] * M_In.E[2] * M_In.E[9]; - M_Out->E[2] = M_In.E[1] * M_In.E[6] * M_In.E[15] - - M_In.E[1] * M_In.E[7] * M_In.E[14] - - M_In.E[5] * M_In.E[2] * M_In.E[15] + - M_In.E[5] * M_In.E[3] * M_In.E[14] + - M_In.E[13] * M_In.E[2] * M_In.E[7] - + M_Out->E[2] = M_In.E[1] * M_In.E[6] * M_In.E[15] - + M_In.E[1] * M_In.E[7] * M_In.E[14] - + M_In.E[5] * M_In.E[2] * M_In.E[15] + + M_In.E[5] * M_In.E[3] * M_In.E[14] + + M_In.E[13] * M_In.E[2] * M_In.E[7] - M_In.E[13] * M_In.E[3] * M_In.E[6]; - M_Out->E[6] = -M_In.E[0] * M_In.E[6] * M_In.E[15] + - M_In.E[0] * M_In.E[7] * M_In.E[14] + - M_In.E[4] * M_In.E[2] * M_In.E[15] - - M_In.E[4] * M_In.E[3] * M_In.E[14] - - M_In.E[12] * M_In.E[2] * M_In.E[7] + + M_Out->E[6] = -M_In.E[0] * M_In.E[6] * M_In.E[15] + + M_In.E[0] * M_In.E[7] * M_In.E[14] + + M_In.E[4] * M_In.E[2] * M_In.E[15] - + M_In.E[4] * M_In.E[3] * M_In.E[14] - + M_In.E[12] * M_In.E[2] * M_In.E[7] + M_In.E[12] * M_In.E[3] * M_In.E[6]; - M_Out->E[10] = M_In.E[0] * M_In.E[5] * M_In.E[15] - - M_In.E[0] * M_In.E[7] * M_In.E[13] - - M_In.E[4] * M_In.E[1] * M_In.E[15] + - M_In.E[4] * M_In.E[3] * M_In.E[13] + - M_In.E[12] * M_In.E[1] * M_In.E[7] - + M_Out->E[10] = M_In.E[0] * M_In.E[5] * M_In.E[15] - + M_In.E[0] * M_In.E[7] * M_In.E[13] - + M_In.E[4] * M_In.E[1] * M_In.E[15] + + M_In.E[4] * M_In.E[3] * M_In.E[13] + + M_In.E[12] * M_In.E[1] * M_In.E[7] - M_In.E[12] * M_In.E[3] * M_In.E[5]; - M_Out->E[14] = -M_In.E[0] * M_In.E[5] * M_In.E[14] + - M_In.E[0] * M_In.E[6] * M_In.E[13] + - M_In.E[4] * M_In.E[1] * M_In.E[14] - - M_In.E[4] * M_In.E[2] * M_In.E[13] - - M_In.E[12] * M_In.E[1] * M_In.E[6] + + M_Out->E[14] = -M_In.E[0] * M_In.E[5] * M_In.E[14] + + M_In.E[0] * M_In.E[6] * M_In.E[13] + + M_In.E[4] * M_In.E[1] * M_In.E[14] - + M_In.E[4] * M_In.E[2] * M_In.E[13] - + M_In.E[12] * M_In.E[1] * M_In.E[6] + M_In.E[12] * M_In.E[2] * M_In.E[5]; - M_Out->E[3] = -M_In.E[1] * M_In.E[6] * M_In.E[11] + - M_In.E[1] * M_In.E[7] * M_In.E[10] + - M_In.E[5] * M_In.E[2] * M_In.E[11] - - M_In.E[5] * M_In.E[3] * M_In.E[10] - - M_In.E[9] * M_In.E[2] * M_In.E[7] + + M_Out->E[3] = -M_In.E[1] * M_In.E[6] * M_In.E[11] + + M_In.E[1] * M_In.E[7] * M_In.E[10] + + M_In.E[5] * M_In.E[2] * M_In.E[11] - + M_In.E[5] * M_In.E[3] * M_In.E[10] - + M_In.E[9] * M_In.E[2] * M_In.E[7] + M_In.E[9] * M_In.E[3] * M_In.E[6]; - M_Out->E[7] = M_In.E[0] * M_In.E[6] * M_In.E[11] - - M_In.E[0] * M_In.E[7] * M_In.E[10] - - M_In.E[4] * M_In.E[2] * M_In.E[11] + - M_In.E[4] * M_In.E[3] * M_In.E[10] + - M_In.E[8] * M_In.E[2] * M_In.E[7] - + M_Out->E[7] = M_In.E[0] * M_In.E[6] * M_In.E[11] - + M_In.E[0] * M_In.E[7] * M_In.E[10] - + M_In.E[4] * M_In.E[2] * M_In.E[11] + + M_In.E[4] * M_In.E[3] * M_In.E[10] + + M_In.E[8] * M_In.E[2] * M_In.E[7] - M_In.E[8] * M_In.E[3] * M_In.E[6]; - M_Out->E[11] = -M_In.E[0] * M_In.E[5] * M_In.E[11] + - M_In.E[0] * M_In.E[7] * M_In.E[9] + - M_In.E[4] * M_In.E[1] * M_In.E[11] - - M_In.E[4] * M_In.E[3] * M_In.E[9] - - M_In.E[8] * M_In.E[1] * M_In.E[7] + + M_Out->E[11] = -M_In.E[0] * M_In.E[5] * M_In.E[11] + + M_In.E[0] * M_In.E[7] * M_In.E[9] + + M_In.E[4] * M_In.E[1] * M_In.E[11] - + M_In.E[4] * M_In.E[3] * M_In.E[9] - + M_In.E[8] * M_In.E[1] * M_In.E[7] + M_In.E[8] * M_In.E[3] * M_In.E[5]; - M_Out->E[15] = M_In.E[0] * M_In.E[5] * M_In.E[10] - - M_In.E[0] * M_In.E[6] * M_In.E[9] - - M_In.E[4] * M_In.E[1] * M_In.E[10] + - M_In.E[4] * M_In.E[2] * M_In.E[9] + - M_In.E[8] * M_In.E[1] * M_In.E[6] - + M_Out->E[15] = M_In.E[0] * M_In.E[5] * M_In.E[10] - + M_In.E[0] * M_In.E[6] * M_In.E[9] - + M_In.E[4] * M_In.E[1] * M_In.E[10] + + M_In.E[4] * M_In.E[2] * M_In.E[9] + + M_In.E[8] * M_In.E[1] * M_In.E[6] - M_In.E[8] * M_In.E[2] * M_In.E[5]; det = M_In.E[0] * M_Out->E[0] + M_In.E[1] * M_Out->E[4] + M_In.E[2] * M_Out->E[8] + M_In.E[3] * M_Out->E[12]; @@ -1476,13 +1498,13 @@ void TestVectorMatrixMultiplication () TestClean(((TestV2 * TestV2) == v2{TestV2.x * TestV2.x, TestV2.y * TestV2.y}), "V2 Piecewise Mult"); TestClean(((TestV3 * TestV3) == v3{ - TestV3.x * TestV3.x, - TestV3.y * TestV3.y, + TestV3.x * TestV3.x, + TestV3.y * TestV3.y, TestV3.z * TestV3.z}), "V3 Piecewise Mult"); TestClean(((TestV4 * TestV4) == v4{ - TestV4.x * TestV4.x, - TestV4.y * TestV4.y, - TestV4.z * TestV4.z, + TestV4.x * TestV4.x, + TestV4.y * TestV4.y, + TestV4.z * TestV4.z, TestV4.w * TestV4.w}), "V4 Piecewise Mult"); @@ -1492,13 +1514,13 @@ void TestVectorMatrixMultiplication () TestClean(((TestV2 / TestV2) == v2{TestV2.x / TestV2.x, TestV2.y / TestV2.y}), "V2 Piecewise Div"); TestClean(((TestV3 / TestV3) == v3{ - TestV3.x / TestV3.x, - TestV3.y / TestV3.y, + TestV3.x / TestV3.x, + TestV3.y / TestV3.y, TestV3.z / TestV3.z}), "V3 Piecewise Div"); TestClean(((TestV4 / TestV4) == v4{ - TestV4.x / TestV4.x, - TestV4.y / TestV4.y, - TestV4.z / TestV4.z, + TestV4.x / TestV4.x, + TestV4.y / TestV4.y, + TestV4.z / TestV4.z, TestV4.w / TestV4.w}), "V4 Piecewise Div"); TestClean(((MagSqr(V2Unit) == 1) && (MagSqr(TestV2) == TestV2MagSq)), "V2 Square Mag"); @@ -1519,8 +1541,8 @@ void TestVectorMatrixMultiplication () TestClean((Normalize(TestV3) == TestV3Norm), "V3 Normalize"); TestClean((Normalize(TestV4) == TestV4Norm), "V4 Normalize"); - TestClean(((Dot(V2Unit, V2Unit) == 1) && (Dot(TestV2, V2Unit) == TestV2DotR)), "V2 Dot"); - TestClean(((Dot(V3Unit, V3Unit) == 1) && (Dot(TestV3, V3Unit) == TestV3DotR)), "V3 Dot"); + TestClean(((Dot(V2Unit, V2Unit) == 1) && (Dot(TestV2, V2Unit) == TestV2DotR)), "V2 Dot"); + TestClean(((Dot(V3Unit, V3Unit) == 1) && (Dot(TestV3, V3Unit) == TestV3DotR)), "V3 Dot"); TestClean(((Dot(V4Unit, V4Unit) == 1) && (Dot(TestV4, V4Unit) == TestV4DotR)), "V4 Dot"); // Skipping Cross For Now @@ -1583,9 +1605,9 @@ void TestVectorMatrixMultiplication () m44 TestM44Squared = m44{ 56, 62, 68, 74, - 152, 174, 196, 218, - 248, 286, 324, 362, - 344, 398, 452, 506, + 152, 174, 196, 218, + 248, 286, 324, 362, + 344, 398, 452, 506, }; TestClean(((IdentityM33 == IdentityM33) && (TestM33 == EqualityM33)), "M33 Equality"); @@ -1642,8 +1664,8 @@ void TestVectorMatrixMultiplication () m44 MTest = m44{ 50, 40, 60, 50, 138, 112, 156, 130, - 109, 94, 99, 84, - 116, 94, 132, 110 + 109, 94, 99, 84, + 116, 94, 132, 110 }; TestClean(((B * C) == MTest), "M44 Mult Test 2"); diff --git a/src/assembly_parser.cpp b/src/assembly_parser.cpp index 3ec38d9..459f644 100644 --- a/src/assembly_parser.cpp +++ b/src/assembly_parser.cpp @@ -5,7 +5,6 @@ // #ifndef ASSEMBLY_PARSER_CPP - internal assembly_token ParseToken (tokenizer* Tokenizer) { @@ -129,7 +128,7 @@ ParseLEDStrip (tokenizer* Tokenizer) Result.StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token).SignedIntValue; // Strip Type - // TODO(Peter): This is unused for now, and would be a branch point for parsing + // TODO(Peter): This is unused for now, and would be a branch point for parsing // the rest of the info. Fix this. EatPastCharacter(Tokenizer, ','); EatWhitespace(Tokenizer); diff --git a/src/foldhaus_app.cpp b/src/foldhaus_app.cpp index 96c87cf..90a737a 100644 --- a/src/foldhaus_app.cpp +++ b/src/foldhaus_app.cpp @@ -12,8 +12,8 @@ internal v4 MouseToWorldRay(r32 MouseX, r32 MouseY, camera* Camera, rect WindowBounds) { DEBUG_TRACK_SCOPE(MouseToWorldRay); - r32 X = ((2.0f * MouseX) / Width(WindowBounds)) - 1; - r32 Y = ((2.0f * MouseY) / Height(WindowBounds)) - 1; + r32 X = ((2.0f * MouseX) / gs_Width(WindowBounds)) - 1; + r32 Y = ((2.0f * MouseY) / gs_Height(WindowBounds)) - 1; v4 ScreenPos = v4{X, Y, -1, 1}; @@ -82,8 +82,8 @@ INITIALIZE_APPLICATION(InitializeApplication) *State->GlobalLog = {0}; s32 CommandQueueSize = 32; - command_queue_entry* CommandQueueMemory = PushArray(&State->Permanent, - command_queue_entry, + command_queue_entry* CommandQueueMemory = PushArray(&State->Permanent, + command_queue_entry, CommandQueueSize); State->CommandQueue = InitializeCommandQueue(CommandQueueMemory, CommandQueueSize); @@ -127,9 +127,9 @@ INITIALIZE_APPLICATION(InitializeApplication) u32 CodepointW, CodepointH; Context.PlatformDrawFontCodepoint( Font->BitmapMemory, - Font->BitmapWidth, + Font->BitmapWidth, Font->BitmapHeight, - CodepointX, CodepointY, + CodepointX, CodepointY, Codepoint, FontInfo, &CodepointW, &CodepointH); @@ -138,10 +138,10 @@ INITIALIZE_APPLICATION(InitializeApplication) State->Interface.Font = Font; - Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, + Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory, Font->BitmapWidth, Font->BitmapHeight); - } - else + } + else { LogError(State->GlobalLog, "Unable to load font"); } @@ -169,7 +169,7 @@ INITIALIZE_APPLICATION(InitializeApplication) State->NetworkProtocolHeaderSize = STREAM_HEADER_SIZE; State->Camera.FieldOfView = DegreesToRadians(45.0f); - State->Camera.AspectRatio = AspectRatio(State->WindowBounds); + State->Camera.AspectRatio = gs_AspectRatio(State->WindowBounds); State->Camera.Near = 1.0f; State->Camera.Far = 100.0f; State->Camera.Position = v3{0, 0, -250}; @@ -242,20 +242,20 @@ HandleInput (app_state* State, rect WindowBounds, input_queue InputQueue, mouse_ { input_entry Event = InputQueue.Entries[EventIdx]; - // NOTE(Peter): These are in the order Down, Up, Held because we want to privalege - // Down and Up over Held. In other words, we don't want to call a Held command on the + // NOTE(Peter): These are in the order Down, Up, Held because we want to privalege + // Down and Up over Held. In other words, we don't want to call a Held command on the // frame when the button was released, even if the command is registered to both events if (KeyTransitionedDown(Event)) { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue); + FindAndPushExistingCommand(ActiveCommands, Event, Command_Began, &State->CommandQueue); } else if (KeyTransitionedUp(Event)) { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue); + FindAndPushExistingCommand(ActiveCommands, Event, Command_Ended, &State->CommandQueue); } else if (KeyHeldDown(Event)) { - FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue); + FindAndPushExistingCommand(ActiveCommands, Event, Command_Held, &State->CommandQueue); } } } @@ -292,8 +292,8 @@ CreateDMXBuffers(assembly Assembly, s32 BufferHeaderSize, memory_arena* Arena) NewBuffer->Next = 0; // Append - if (!Result) { - Result = NewBuffer; + if (!Result) { + Result = NewBuffer; Head = Result; } Head->Next = NewBuffer; @@ -325,21 +325,21 @@ UPDATE_AND_RENDER(UpdateAndRender) // NOTE(Peter): We do this at the beginning because all the render commands are stored in Transient, // and need to persist beyond the end of the UpdateAndRender call. In the release version, we won't - // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically + // zero the Transient arena when we clear it so it wouldn't be a problem, but it is technically // incorrect to clear the arena, and then access the memory later. ClearArena(&State->Transient); Context->Mouse.CursorType = CursorType_Arrow; HandleInput(State, State->WindowBounds, InputQueue, Context->Mouse); - if (State->AnimationSystem.TimelineShouldAdvance) { + if (State->AnimationSystem.TimelineShouldAdvance) { // TODO(Peter): Revisit this. This implies that the framerate of the animation system // is tied to the framerate of the simulation. That seems correct to me, but I'm not sure - State->AnimationSystem.CurrentFrame += 1; + State->AnimationSystem.CurrentFrame += 1; // Loop back to the beginning if (State->AnimationSystem.CurrentFrame > State->AnimationSystem.PlayableRange.Max) { - State->AnimationSystem.CurrentFrame = 0; + State->AnimationSystem.CurrentFrame = 0; } } @@ -386,9 +386,9 @@ UPDATE_AND_RENDER(UpdateAndRender) // TODO(Peter): Temporary switch(Block.AnimationProcHandle) { - case 1: + case 1: { - TestPatternOne(&LayerLEDBuffers[Layer], SecondsIntoBlock); + TestPatternOne(&LayerLEDBuffers[Layer], SecondsIntoBlock); }break; case 2: @@ -498,7 +498,7 @@ UPDATE_AND_RENDER(UpdateAndRender) } } - PushRenderOrthographic(RenderBuffer, 0, 0, Width(State->WindowBounds), Height(State->WindowBounds)); + PushRenderOrthographic(RenderBuffer, 0, 0, gs_Width(State->WindowBounds), gs_Height(State->WindowBounds)); PushRenderClearScreen(RenderBuffer); State->WindowBounds = Context->WindowBounds; diff --git a/src/foldhaus_interface.cpp b/src/foldhaus_interface.cpp index fbee3ca..86684f5 100644 --- a/src/foldhaus_interface.cpp +++ b/src/foldhaus_interface.cpp @@ -123,7 +123,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / Height(PanelBounds); + Panel->SplitPercent = (NewSplitY - PanelBounds.Min.y) / gs_Height(PanelBounds); } } else if (Panel->SplitDirection == PanelSplit_Vertical) @@ -139,7 +139,7 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndDragPanelBorderOperation) } else { - Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / Width(PanelBounds); + Panel->SplitPercent = (NewSplitX - PanelBounds.Min.x) / gs_Width(PanelBounds); } } } @@ -241,12 +241,12 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndSplitPanelOperation) if (XDistance > YDistance) { - r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / Width(PanelBounds); + r32 XPercent = (Mouse.Pos.x - PanelBounds.Min.x) / gs_Width(PanelBounds); SplitPanelVertically(Panel, XPercent, PanelBounds, &State->PanelSystem); } else { - r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / Height(PanelBounds); + r32 YPercent = (Mouse.Pos.y - PanelBounds.Min.y) / gs_Height(PanelBounds); SplitPanelHorizontally(Panel, YPercent, PanelBounds, &State->PanelSystem); } @@ -301,11 +301,11 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit { rect TopPanelBounds = GetTopPanelBounds(Panel, PanelBounds); rect BottomPanelBounds = GetBottomPanelBounds(Panel, PanelBounds); - if (PointIsInRect(Mouse.DownPos, BottomPanelBounds)) + if (gs_PointIsInRect(Mouse.DownPos, BottomPanelBounds)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Bottom->Panel, PanelEditMode, BottomPanelBounds, Mouse, State); } - if (PointIsInRect(Mouse.DownPos, TopPanelBounds)) + if (gs_PointIsInRect(Mouse.DownPos, TopPanelBounds)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Top->Panel, PanelEditMode, TopPanelBounds, Mouse, State); } @@ -324,11 +324,11 @@ HandleMouseDownPanelInteractionOrRecurse(panel* Panel, panel_edit_mode PanelEdit { rect LeftPanelBounds = GetLeftPanelBounds(Panel, PanelBounds); rect RightPanelBounds = GetRightPanelBounds(Panel, PanelBounds); - if (PointIsInRect(Mouse.DownPos, LeftPanelBounds)) + if (gs_PointIsInRect(Mouse.DownPos, LeftPanelBounds)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Left->Panel, PanelEditMode, LeftPanelBounds, Mouse, State); } - if (PointIsInRect(Mouse.DownPos, RightPanelBounds)) + if (gs_PointIsInRect(Mouse.DownPos, RightPanelBounds)) { HandleMouseDownPanelInteractionOrRecurse(&Panel->Right->Panel, PanelEditMode, RightPanelBounds, Mouse, State); } @@ -403,14 +403,14 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo PushRenderQuad2D(RenderBuffer, FooterBounds.Min, v2{FooterBounds.Max.x, FooterBounds.Min.y + 25}, v4{.5f, .5f, .5f, 1.f}); PushRenderQuad2D(RenderBuffer, FooterBounds.Min, FooterBounds.Min + v2{25, 25}, WhiteV4); - rect PanelSelectBtnBounds = MakeRectMinWidth(FooterBounds.Min + v2{30, 1}, v2{100, 23}); + rect PanelSelectBtnBounds = gs_MakeRectMinWidth(FooterBounds.Min + v2{30, 1}, v2{100, 23}); if (Panel->PanelSelectionMenuOpen) { - rect ButtonBounds = MakeRectMinWidth(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); + rect ButtonBounds = gs_MakeRectMinWidth(v2{ PanelSelectBtnBounds.Min.x, FooterBounds.Max.y }, v2{ 100, 25 }); v2 MenuMin = ButtonBounds.Min; - v2 MenuMax = v2{ButtonBounds.Min.x + Width(ButtonBounds), ButtonBounds.Min.y + (Height(ButtonBounds) * GlobalPanelDefsCount)}; + v2 MenuMax = v2{ButtonBounds.Min.x + gs_Width(ButtonBounds), ButtonBounds.Min.y + (gs_Height(ButtonBounds) * GlobalPanelDefsCount)}; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && !PointIsInRange(Mouse.DownPos, MenuMin, MenuMax)) { @@ -428,7 +428,7 @@ DrawPanelFooter(panel* Panel, render_command_buffer* RenderBuffer, rect FooterBo Panel->PanelSelectionMenuOpen = false; } - ButtonBounds = TranslateRectY(ButtonBounds, Height(ButtonBounds)); + ButtonBounds = gs_TranslateRectY(ButtonBounds, gs_Height(ButtonBounds)); } } diff --git a/src/interface.h b/src/interface.h index 510a28d..653138f 100644 --- a/src/interface.h +++ b/src/interface.h @@ -207,8 +207,9 @@ struct ui_layout r32 RowYAt; b32 DrawHorizontal; - u32 RowDivisions; - u32 RowElementsCount; + u32 ColumnsMax; + r32* ColumnWidths; + u32 ColumnsCount; }; struct ui_interface @@ -230,11 +231,12 @@ ui_CreateLayout(ui_interface Interface, rect Bounds) } static void -ui_StartRow(ui_layout* Layout, u32 RowDivisions) +ui_StartRow(ui_layout* Layout, u32 ColumnsMax) { Layout->DrawHorizontal = true; - Layout->RowDivisions = RowDivisions; - Layout->RowElementsCount = 0; + Layout->ColumnsMax = ColumnsMax; + Layout->ColumnWidths = 0; + Layout->ColumnsCount = 0; } static void @@ -243,10 +245,21 @@ ui_StartRow(ui_layout* Layout) ui_StartRow(Layout, 0); } +static void +ui_StartRow(ui_layout* Layout, u32 ColumnsMax, r32* ColumnWidths) +{ + Layout->DrawHorizontal = true; + Layout->ColumnsMax = ColumnsMax; + Layout->ColumnWidths = ColumnWidths; + Layout->ColumnsCount = 0; +} + static void ui_EndRow(ui_layout* Layout) { Layout->DrawHorizontal = false; + Layout->ColumnWidths = 0; + Layout->RowYAt -= Layout->RowHeight; } static b32 @@ -261,19 +274,32 @@ ui_TryReserveElementBounds(ui_layout* Layout, rect* Bounds) } else { - if (Layout->RowDivisions > 0) + if (Layout->ColumnsMax > 0) { - Assert(Layout->RowElementsCount < Layout->RowDivisions); - r32 ElementWidth = Width(Layout->Bounds) / Layout->RowDivisions; - Bounds->Min = { - Layout->Bounds.Min.x + (ElementWidth * Layout->RowElementsCount) + Layout->Margin.x, - Layout->RowYAt - }; - Bounds->Max = { - Bounds->Min.x + ElementWidth - Layout->Margin.x, - Bounds->Min.y + Layout->RowHeight - }; - Layout->RowElementsCount++; + Assert(Layout->ColumnsCount < Layout->ColumnsMax); + if (Layout->ColumnWidths != 0) + { + v2 Min = { Layout->Bounds.Min.x, Layout->RowYAt }; + for (u32 i = 0; i < Layout->ColumnsCount; i++) + { + Min.x += Layout->ColumnWidths[i]; + } + Bounds->Min = Min; + Bounds->Max = Bounds->Min + v2{ Layout->ColumnWidths[Layout->ColumnsCount], Layout->RowHeight }; + } + else + { + r32 ElementWidth = gs_Width(Layout->Bounds) / Layout->ColumnsMax; + Bounds->Min = { + Layout->Bounds.Min.x + (ElementWidth * Layout->ColumnsCount) + Layout->Margin.x, + Layout->RowYAt + }; + Bounds->Max = { + Bounds->Min.x + ElementWidth - Layout->Margin.x, + Bounds->Min.y + Layout->RowHeight + }; + } + Layout->ColumnsCount++; } else { @@ -302,6 +328,17 @@ ui_ReserveElementBounds(ui_layout* Layout) return Bounds; } +static rect +ui_LayoutRemaining(ui_layout Layout) +{ + rect Result = Layout.Bounds; + Result.Max.y = Layout.RowYAt; + if (Layout.DrawHorizontal) + { + Result.Max.y -= Layout.RowHeight; + } + return Result; +} // // Drawing Functions // @@ -309,7 +346,7 @@ ui_ReserveElementBounds(ui_layout* Layout) static void ui_FillRect(ui_interface* Interface, rect Bounds, v4 Color) { - PushRenderQuad2D(Interface->RenderBuffer, RectExpand(Bounds), Color); + PushRenderQuad2D(Interface->RenderBuffer, gs_RectExpand(Bounds), Color); } static void @@ -371,7 +408,7 @@ ui_Button(ui_interface* Interface, string Text, rect Bounds, v4 InactiveColor, v { b32 Pressed = false; v4 ButtonBG = InactiveColor; - if (PointIsInRect(Interface->Mouse.Pos, Bounds)) + if (gs_PointIsInRect(Interface->Mouse.Pos, Bounds)) { ButtonBG = HoverColor; if (MouseButtonTransitionedDown(Interface->Mouse.LeftButtonState)) diff --git a/src/panels/foldhaus_panel_animation_timeline.h b/src/panels/foldhaus_panel_animation_timeline.h index 65ab2ce..36b23fc 100644 --- a/src/panels/foldhaus_panel_animation_timeline.h +++ b/src/panels/foldhaus_panel_animation_timeline.h @@ -27,7 +27,7 @@ inline s32 GetXPositionFromFrameInAnimationPanel (u32 Frame, rect PanelBounds, frame_range VisibleRange) { r32 PercentOfTimeline = (r32)(Frame - VisibleRange.Min) / (r32)GetFrameCount(VisibleRange); - s32 XPositionAtFrame = (PercentOfTimeline * Width(PanelBounds)) + PanelBounds.Min.x; + s32 XPositionAtFrame = (PercentOfTimeline * gs_Width(PanelBounds)) + PanelBounds.Min.x; return XPositionAtFrame; } @@ -295,14 +295,14 @@ DrawFrameBar (animation_system* AnimationSystem, render_command_buffer* RenderBu s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; - r32 BarHeight = Height(BarBounds); - r32 BarWidth = Width(BarBounds); + r32 BarHeight = gs_Height(BarBounds); + r32 BarWidth = gs_Width(BarBounds); - PushRenderQuad2D(RenderBuffer, RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); // Mouse clicked inside frame nubmer bar -> change current frame on timeline if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRange(Mouse.DownPos, RectExpand(BarBounds))) + PointIsInRange(Mouse.DownPos, gs_RectExpand(BarBounds))) { StartDragTimeMarker(BarBounds, VisibleFrames, State); } @@ -344,9 +344,9 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat { frame_range Result = {0}; - r32 BarHeight = Height(BarBounds); - r32 BarWidth = Width(BarBounds); - PushRenderQuad2D(RenderBuffer, RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); + r32 BarHeight = gs_Height(BarBounds); + r32 BarWidth = gs_Width(BarBounds); + PushRenderQuad2D(RenderBuffer, gs_RectExpand(BarBounds), v4{.16f, .16f, .16f, 1.f}); r32 PlayableFrames = (r32)GetFrameCount(AnimationSystem->PlayableRange); v2 SliderBarDim = v2{25, BarHeight}; @@ -354,8 +354,8 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat // Convert Frames To Pixels r32 VisibleMinPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Min, AnimationSystem->PlayableRange); r32 VisibleMaxPercentPlayable = FrameToPercentRange(TimelineState->VisibleRange.Max, AnimationSystem->PlayableRange); - v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * Width(BarBounds)), BarBounds.Min.y}; - v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * Width(BarBounds)) - 25, BarBounds.Min.y}; + v2 RangeMinSliderMin = v2{BarBounds.Min.x + (VisibleMinPercentPlayable * gs_Width(BarBounds)), BarBounds.Min.y}; + v2 RangeMaxSliderMin = v2{BarBounds.Min.x + (VisibleMaxPercentPlayable * gs_Width(BarBounds)) - 25, BarBounds.Min.y}; if (MouseButtonHeldDown(Mouse.LeftButtonState) || MouseButtonTransitionedUp(Mouse.LeftButtonState)) @@ -398,7 +398,7 @@ DrawTimelineRangeBar (animation_system* AnimationSystem, animation_timeline_stat internal void DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_buffer* RenderBuffer, app_state* State, mouse_state Mouse) { - v2 LayerDim = { Width(PanelDim), LAYER_HEIGHT }; + v2 LayerDim = { gs_Width(PanelDim), LAYER_HEIGHT }; v2 LayerListMin = PanelDim.Min + v2{0, 24}; for (u32 LayerIndex = 0; LayerIndex < AnimationSystem->LayersCount; LayerIndex++) { @@ -408,7 +408,7 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b LayerBounds.Max = LayerBounds.Min + LayerDim; if (MouseButtonTransitionedDown(Mouse.LeftButtonState) && - PointIsInRect(Mouse.Pos, LayerBounds)) + gs_PointIsInRect(Mouse.Pos, LayerBounds)) { State->SelectedAnimationLayer = LayerIndex; } @@ -416,7 +416,7 @@ DrawLayerMenu(animation_system* AnimationSystem, rect PanelDim, render_command_b v2 LayerTextPos = { LayerBounds.Min.x + 6, LayerBounds.Max.y - 16}; if (State->SelectedAnimationLayer == LayerIndex) { - PushRenderBoundingBox2D(RenderBuffer, RectExpand(LayerBounds), 1, WhiteV4); + PushRenderBoundingBox2D(RenderBuffer, gs_RectExpand(LayerBounds), 1, WhiteV4); } DrawString(RenderBuffer, Layer->Name, State->Interface.Font, LayerTextPos, WhiteV4); } @@ -427,7 +427,7 @@ DrawAnimationBlock (animation_block AnimationBlock, v4 BlockColor, frame_range V { rect BlockBounds = {}; - r32 TimelineWidth = Width(TimelineBounds); + r32 TimelineWidth = gs_Width(TimelineBounds); u32 ClampedBlockStartFrame = ClampFrameToRange(AnimationBlock.Range.Min, VisibleFrames); r32 StartFramePercent = FrameToPercentRange(ClampedBlockStartFrame, VisibleFrames); @@ -454,12 +454,12 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta gs_list_handle Result = SelectedBlockHandle; rect LayerMenuBounds, TimelineBounds; - VSplitRectAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); + gs_VSplitRectAtDistanceFromLeft(PanelBounds, 256, &LayerMenuBounds, &TimelineBounds); // In Top To Bottom Order rect TimelineFrameBarBounds, TimelineBlockDisplayBounds, TimelineRangeBarBounds; - HSplitRectAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); - HSplitRectAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); + gs_HSplitRectAtDistanceFromTop(TimelineBounds, 32, &TimelineFrameBarBounds, &TimelineBounds); + gs_HSplitRectAtDistanceFromBottom(TimelineBounds, 24, &TimelineBlockDisplayBounds, &TimelineRangeBarBounds); // TODO(Peter): Clean Up DrawLayerMenu(AnimationSystem, LayerMenuBounds, Interface->RenderBuffer, State, Interface->Mouse); @@ -501,7 +501,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta } // TODO(Peter): Clean Up rect BlockBounds = DrawAnimationBlock(AnimationBlockAt, BlockColor, AdjustedViewRange, TimelineBounds, Interface->RenderBuffer); - if (PointIsInRect(Interface->Mouse.Pos, BlockBounds)) + if (gs_PointIsInRect(Interface->Mouse.Pos, BlockBounds)) { DragBlockHandle = CurrentBlockHandle; } @@ -531,7 +531,7 @@ DrawAnimationTimeline (animation_system* AnimationSystem, animation_timeline_sta ui_OutlineRect(Interface, TimelineFrameBarBounds, 1.f, RedV4); ui_OutlineRect(Interface, TimelineBlockDisplayBounds, 1.f, RedV4); - if (MouseDownAndNotHandled && PointIsInRect(Interface->Mouse.Pos, TimelineBounds)) + if (MouseDownAndNotHandled && gs_PointIsInRect(Interface->Mouse.Pos, TimelineBounds)) { DeselectCurrentAnimationBlock(State); } @@ -581,9 +581,9 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R animation_system* AnimationSystem = &State->AnimationSystem; rect TitleBarBounds, PanelContentsBounds; - HSplitRectAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); + gs_HSplitRectAtDistanceFromTop(PanelBounds, Interface->Style.RowHeight, &TitleBarBounds, &PanelContentsBounds); rect AnimationListBounds, TimelineBounds; - VSplitRectAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); + gs_VSplitRectAtDistanceFromLeft(PanelContentsBounds, 300, &AnimationListBounds, &TimelineBounds); ui_FillRect(Interface, TitleBarBounds, Interface->Style.PanelBGColors[0]); ui_layout TitleBarLayout = ui_CreateLayout(*Interface, TitleBarBounds); @@ -605,7 +605,7 @@ AnimationTimeline_Render(panel Panel, rect PanelBounds, render_command_buffer* R } ui_EndRow(&TitleBarLayout); - if (Height(TimelineBounds) > 0) + if (gs_Height(TimelineBounds) > 0) { SelectedBlockHandle = DrawAnimationTimeline(AnimationSystem, TimelineState, TimelineBounds, SelectedBlockHandle, Interface, State); DrawAnimationClipsList(AnimationListBounds, Interface, State->SelectedAnimationLayer, &State->AnimationSystem); diff --git a/src/panels/foldhaus_panel_file_view.h b/src/panels/foldhaus_panel_file_view.h index 060fa6c..658435b 100644 --- a/src/panels/foldhaus_panel_file_view.h +++ b/src/panels/foldhaus_panel_file_view.h @@ -44,10 +44,10 @@ FileView_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuff rect ListBounds = {0}; ListBounds.Min = PanelBounds.Min; - ListBounds.Max = BottomRight(HeaderBounds); + ListBounds.Max = gs_BottomRight(HeaderBounds); - PushRenderQuad2D(RenderBuffer, RectExpand(HeaderBounds), PinkV4); - PushRenderQuad2D(RenderBuffer, RectExpand(ListBounds), RedV4); + PushRenderQuad2D(RenderBuffer, gs_RectExpand(HeaderBounds), PinkV4); + PushRenderQuad2D(RenderBuffer, gs_RectExpand(ListBounds), RedV4); } diff --git a/src/panels/foldhaus_panel_hierarchy.h b/src/panels/foldhaus_panel_hierarchy.h index 1fc0cc9..6f1ff6f 100644 --- a/src/panels/foldhaus_panel_hierarchy.h +++ b/src/panels/foldhaus_panel_hierarchy.h @@ -35,7 +35,7 @@ HierarchyView_Render(panel Panel, rect PanelBounds, render_command_buffer* Rende string TempString = MakeString(PushArray(&State->Transient, char, 256), 0, 256); - u32 LineCount = (u32)(Height(PanelBounds) / Layout.RowHeight) + 1; + u32 LineCount = (u32)(gs_Height(PanelBounds) / Layout.RowHeight) + 1; u32 LinesDrawn = 0; u32 AssembliesToDraw = GSMin(LineCount, State->ActiveAssemblyIndecies.Used); for (; LinesDrawn < AssembliesToDraw; LinesDrawn++) diff --git a/src/panels/foldhaus_panel_node_graph.h b/src/panels/foldhaus_panel_node_graph.h index 65affe5..12ae92d 100644 --- a/src/panels/foldhaus_panel_node_graph.h +++ b/src/panels/foldhaus_panel_node_graph.h @@ -71,7 +71,7 @@ OPERATION_STATE_DEF(pan_node_graph_operation_state) { v2 InitialViewOffset; - // TODO(Peter): I DON"T LIKE THIS!!!! + // TODO(Peter): I DON"T LIKE THIS!!!! // We should have a way to access the panel that created an operation mode or something v2* ViewOffset; }; @@ -128,8 +128,8 @@ FOLDHAUS_INPUT_COMMAND_PROC(EndConnectNodesOperation) for (u32 p = 0; p < GraphState->Layout.VisualPortsCount; p++) { visual_port VisualPort = GraphState->Layout.VisualPorts[p]; - rect ViewAdjustedBounds = RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); - if (PointIsInRect(Mouse.Pos, ViewAdjustedBounds)) + rect ViewAdjustedBounds = gs_RectOffsetByVector(VisualPort.PortBounds, GraphState->ViewOffset); + if (gs_PointIsInRect(Mouse.Pos, ViewAdjustedBounds)) { visual_port UpstreamPort = (OpState->IsInput & IsInputMember) ? VisualPort : OpState->VisualPort; visual_port DownstreamPort = (OpState->IsInput & IsInputMember) ? OpState->VisualPort : VisualPort; @@ -161,7 +161,7 @@ BeginConnectNodesOperation(visual_port VisualPort, u32 VisualPortIndex, mouse_st node_graph_state* GraphState = (node_graph_state*)NodeGraphPanel.Panel->PanelStateMemory; GraphState->Layout.ConnectionIsInProgress = true; - GraphState->Layout.InProgressConnectionStart = CalculateRectCenter(VisualPort.PortBounds); + GraphState->Layout.InProgressConnectionStart = gs_CalculateRectCenter(VisualPort.PortBounds); } // @@ -177,8 +177,8 @@ GSMetaTag(panel_type_node_graph); internal void NodeGraph_Init(panel* Panel, app_state* State) { - // TODO(Peter): We aren't able to free this memory. We need a system for - // taking fixed size chunks off the Memory stack and then reusing them. THis + // TODO(Peter): We aren't able to free this memory. We need a system for + // taking fixed size chunks off the Memory stack and then reusing them. THis // should probably live outside the paneling system. // TODO: :FreePanelMemory Panel->PanelStateMemory = (u8*)PushStruct(&State->Permanent, node_graph_state); @@ -242,7 +242,7 @@ DrawNodePorts(gsm_struct_type_info NodeDataTypeInfo, b32 InputMask, v2 Position, gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i]; if (MemberIsInput(Member)) { - // TODO(Peter): Can we make this rely on the same data that we use to + // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); DrawString(RenderBuffer, MemberName, Interface.Font, LinePosition + TextOffset, WhiteV4, TextAlign); @@ -267,7 +267,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod u32 LineCount = 1 + GSMax(InputMembers, OutputMembers); v2 NodeDim = v2{ - NodeWidth, + NodeWidth, (LineHeight * LineCount) + Interface.Margin.y, }; rect NodeBounds = rect{ @@ -295,7 +295,7 @@ DrawNode (v2 Position, node_specification_ NodeSpecification, gs_list_handle Nod gsm_struct_member_type_info Member = NodeDataTypeInfo.Members[i]; string MemberName = MakeString(Member.Identifier, Member.IdentifierLength); - // TODO(Peter): Can we make this rely on the same data that we use to + // TODO(Peter): Can we make this rely on the same data that we use to // render the actual connection points? if (MemberIsInput(Member)) { @@ -364,10 +364,10 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, visual_node* VisualNode = Result.VisualNodes + n; VisualNode->Spec = Spec; - VisualNode->Position = v2{(1.5f * NodeWidth) * n, 0}; + VisualNode->Position = v2{(1.5f * NodeWidth) * n, 0}; // NOTE(Peter): These start at 2 to account for the offset past the node title - s32 InputsCount = 2; + s32 InputsCount = 2; s32 OutputsCount = 2; for (u32 p = 0; p < NodeDataTypeInfo.MembersCount; p++) { @@ -375,7 +375,7 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, rect PortBounds = {0}; v2 PortDim = v2{8, 8}; - PortBounds.Min = VisualNode->Position + v2{0, PortDim.y / 2}; + PortBounds.Min = VisualNode->Position + v2{0, PortDim.y / 2}; if (MemberIsInput(Member)) { PortBounds.Min.y -= LineHeight * InputsCount++; @@ -410,8 +410,8 @@ ArrangeNodes(pattern_node_workspace Workspace, r32 NodeWidth, r32 LayerDistance, visual_port UpstreamPort = Result.VisualPorts[VisualConnection->UpstreamVisualPortIndex]; visual_port DownstreamPort = Result.VisualPorts[VisualConnection->DownstreamVisualPortIndex]; - VisualConnection->UpstreamPosition = CalculateRectCenter(UpstreamPort.PortBounds); - VisualConnection->DownstreamPosition = CalculateRectCenter(DownstreamPort.PortBounds); + VisualConnection->UpstreamPosition = gs_CalculateRectCenter(UpstreamPort.PortBounds); + VisualConnection->DownstreamPosition = gs_CalculateRectCenter(DownstreamPort.PortBounds); } return Result; @@ -467,8 +467,8 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf if (GraphState->Layout.ConnectionIsInProgress) { - PushRenderLine2D(RenderBuffer, - GraphState->Layout.InProgressConnectionStart, + PushRenderLine2D(RenderBuffer, + GraphState->Layout.InProgressConnectionStart, GraphState->Layout.InProgressConnectionEnd, 1.5f, WhiteV4); } @@ -513,7 +513,7 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf List.TextColor = WhiteV4; List.ListBounds = NodeSelectionWindowBounds; List.ListElementDimensions = v2{ - Width(NodeSelectionWindowBounds), + gs_Width(NodeSelectionWindowBounds), (r32)(State->Interface.Font->PixelHeight + 8), }; List.ElementLabelIndent = v2{10, 4}; @@ -526,8 +526,8 @@ NodeGraph_Render(panel Panel, rect PanelBounds, render_command_buffer* RenderBuf node_specification_ Spec = NodeSpecifications[i]; rect ElementBounds = DrawListElement(Spec.Identifier, &List, Mouse, RenderBuffer, State->Interface); - if (MouseButtonTransitionedDown(Mouse.LeftButtonState) - && PointIsInRect(Mouse.DownPos, ElementBounds)) + if (MouseButtonTransitionedDown(Mouse.LeftButtonState) + && gs_PointIsInRect(Mouse.DownPos, ElementBounds)) { PushNodeOnWorkspace(i, &State->NodeWorkspace, &State->Transient); GraphState->LayoutIsDirty = true; diff --git a/src/panels/foldhaus_panel_profiler.h b/src/panels/foldhaus_panel_profiler.h index b86fdb6..d4e25aa 100644 --- a/src/panels/foldhaus_panel_profiler.h +++ b/src/panels/foldhaus_panel_profiler.h @@ -25,10 +25,7 @@ ProfilerView_Cleanup(panel* Panel, app_state* State) } internal void -RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, - interface_config Interface, mouse_state Mouse, - v2 Min, v2 Max, - debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ScopeVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) { v4 ThreadColors[] = { v4{.73f, .33f, .83f, 1}, @@ -38,7 +35,8 @@ RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, v4{.74f, .40f, .25f, 1}, }; - r32 Width = Max.x - Min.x; + rect Bounds = ui_LayoutRemaining(Layout); + r32 Width = gs_Width(Bounds); r32 DepthHeight = 64; s64 FrameStartCycles = VisibleFrame->FrameStartCycles; @@ -47,6 +45,9 @@ RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, debug_scope_record_list* ThreadScopeCalls = GetScopeListForThreadInFrame(GlobalDebugServices, VisibleFrame); + scope_record* HotRecord = 0; + scope_name* HotRecordName = 0; + MakeStringBuffer(String, 256); for (s32 i = 0; i < ThreadScopeCalls->Count; i++) { @@ -55,44 +56,50 @@ RenderProfiler_ScopeVisualization(render_command_buffer* RenderBuffer, r32 PercentStart = (r32)(Record->StartCycles - FrameStartCycles) / (r32)FrameTotalCycles; r32 PercentEnd = (r32)(Record->EndCycles - FrameStartCycles) / (r32)FrameTotalCycles; - v2 ScopeMin = v2{Min.x + (Width * PercentStart), Max.y - ((Record->CallDepth + 1) * DepthHeight)}; - v2 ScopeMax = v2{Min.x + (Width * PercentEnd), ScopeMin.y + (DepthHeight - 4)}; - - if ((ScopeMax.x - ScopeMin.x) >= 1) + r32 PixelStart = Bounds.Min.x + (Width * PercentStart); + r32 PixelEnd = Bounds.Min.x + (Width * PercentEnd); + r32 MinY = Bounds.Max.y - ((Record->CallDepth + 1) * DepthHeight); + rect ScopeBounds = { + v2{ PixelStart, MinY }, + v2{ PixelEnd, MinY + (DepthHeight - 4) } + }; + if (gs_Width(ScopeBounds) >= 1) { v4 Color = ThreadColors[0]; - if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax)) + if (gs_PointIsInRect(Interface->Mouse.Pos, ScopeBounds)) { Color = GreenV4; + HotRecord = Record; + HotRecordName = Name; } - PushRenderQuad2D(RenderBuffer, ScopeMin, ScopeMax, Color); - PushRenderBoundingBox2D(RenderBuffer, ScopeMin, ScopeMax, 1, BlackV4); - - if (PointIsInRange(Mouse.Pos, ScopeMin, ScopeMax)) - { - PushRenderQuad2D(RenderBuffer, Mouse.Pos, Mouse.Pos + v2{256, 32}, BlackV4); - PrintF(&String, "%.*s : %d - %d", Name->Name.Length, Name->Name.Memory, Record->StartCycles, Record->EndCycles); - DrawString(RenderBuffer, String, Interface.Font, Mouse.Pos, WhiteV4); - } + ui_FillRect(Interface, ScopeBounds, Color); + ui_OutlineRect(Interface, ScopeBounds, 1, BlackV4); } } + + if (HotRecord != 0) + { + PrintF(&String, "%S : %d - %d", HotRecordName->Name, HotRecord->StartCycles, HotRecord->EndCycles); + ui_TextBox(Interface, gs_MakeRectMinWidth(Interface->Mouse.Pos, v2{256, 32}), String, BlackV4, WhiteV4); + } } internal void -RenderProfiler_ListVisualization(render_command_buffer* RenderBuffer, - interface_config Interface, mouse_state Mouse, - v2 Min, v2 Max, - debug_frame* VisibleFrame, memory_arena* Memory) +RenderProfiler_ListVisualization(ui_interface* Interface, ui_layout Layout, debug_frame* VisibleFrame, memory_arena* Memory) { MakeStringBuffer(String, 256); - r32 YAt = Max.y - Interface.Font->PixelHeight; - r32 Column0X = Min.x; - r32 Column1X = Column0X + 256; - r32 Column2X = Column1X + 128; - r32 Column3X = Column2X + 128; - r32 Column4X = Column3X + 100; + r32 ColumnWidths[] = {256, 128, 128, 128, 128}; + ui_StartRow(&Layout, 5, &ColumnWidths[0]); + { + ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Procedure"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("% Frame"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Seconds"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Cycles"), Interface->Style.TextColor); + ui_LayoutDrawString(Interface, &Layout, MakeStringLiteral("Calls"), Interface->Style.TextColor); + } + ui_EndRow(&Layout); for (s32 n = 0; n < VisibleFrame->ScopeNamesMax; n++) { @@ -101,24 +108,24 @@ RenderProfiler_ListVisualization(render_command_buffer* RenderBuffer, { collated_scope_record* CollatedRecord = VisibleFrame->CollatedScopes + n; - PrintF(&String, "%.*s", NameEntry.Name.Length, NameEntry.Name.Memory); - DrawString(RenderBuffer, String, Interface.Font, v2{Column0X, YAt}, WhiteV4); - - PrintF(&String, "%f", CollatedRecord->PercentFrameTime); - DrawString(RenderBuffer, String, Interface.Font, v2{Column1X, YAt}, WhiteV4); - - PrintF(&String, "%fs", CollatedRecord->TotalSeconds); - DrawString(RenderBuffer, String, Interface.Font, v2{Column2X, YAt}, WhiteV4); - - PrintF(&String, "%dcy", CollatedRecord->TotalCycles); - DrawString(RenderBuffer, String, Interface.Font, v2{Column3X, YAt}, WhiteV4); - - PrintF(&String, "%d calls", CollatedRecord->CallCount); - DrawString(RenderBuffer, String, Interface.Font, v2{Column4X, YAt}, WhiteV4); - - YAt -= Interface.Font->PixelHeight + 4; - - if (YAt < Min.y) { break; } + ui_StartRow(&Layout, 5, &ColumnWidths[0]); + { + PrintF(&String, "%S", NameEntry.Name); + ui_LayoutDrawString(Interface, &Layout, String, Interface->Style.TextColor); + + PrintF(&String, "%f%%", CollatedRecord->PercentFrameTime); + ui_LayoutDrawString(Interface, &Layout, String, Interface->Style.TextColor); + + PrintF(&String, "%fs", CollatedRecord->TotalSeconds); + ui_LayoutDrawString(Interface, &Layout, String, Interface->Style.TextColor); + + PrintF(&String, "%dcy", CollatedRecord->TotalCycles); + ui_LayoutDrawString(Interface, &Layout, String, Interface->Style.TextColor); + + PrintF(&String, "%d", CollatedRecord->CallCount); + ui_LayoutDrawString(Interface, &Layout, String, Interface->Style.TextColor); + } + ui_EndRow(&Layout); } } } @@ -134,23 +141,18 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render v4 FrameColors[] = { GreenV4, YellowV4, RedV4, WhiteV4 }; r32 FrameListHeight = 64; - v2 FrameListMin = v2{PanelBounds.Min.x + 16, PanelBounds.Max.y - (16 + FrameListHeight)}; - v2 FrameListMax = v2{PanelBounds.Max.x - 16, PanelBounds.Max.y - 16}; + rect FrameListBounds, ProcListBounds; + gs_HSplitRectAtDistanceFromTop(PanelBounds, FrameListHeight, &FrameListBounds, &ProcListBounds); + rect FrameListInner = gs_InsetRect(FrameListBounds, 4); - r32 FrameListPadding = 4; - r32 FrameListInnerWidth = (FrameListMax.x - FrameListMin.x) - (FrameListPadding * 2); - - r32 SingleFrameStep = FrameListInnerWidth / DEBUG_FRAME_COUNT; + r32 SingleFrameStep = gs_Width(FrameListInner) / DEBUG_FRAME_COUNT; r32 SingleFrameWidth = (r32)((s32)SingleFrameStep - 2); - PushRenderBoundingBox2D(RenderBuffer, FrameListMin, FrameListMax, 2, WhiteV4); - - if (PointIsInRange(Mouse.Pos, FrameListMin, FrameListMax) && - MouseButtonHeldDown(Mouse.LeftButtonState)) + ui_OutlineRect(&State->Interface_, FrameListBounds, 2, WhiteV4); + if (gs_PointIsInRect(Mouse.Pos, FrameListBounds) && MouseButtonHeldDown(Mouse.LeftButtonState)) { - r32 LocalMouseX = (Mouse.Pos.x - FrameListMin.x) + FrameListPadding; - s32 ClosestFrameIndex = (LocalMouseX / SingleFrameStep); - + v2 LocalMouse = gs_TransformPointIntoRectSpace(Mouse.Pos, FrameListBounds); + s32 ClosestFrameIndex = (LocalMouse.x / SingleFrameStep); if (ClosestFrameIndex >= 0 && ClosestFrameIndex < DEBUG_FRAME_COUNT) { GlobalDebugServices->RecordFrames = false; @@ -158,60 +160,61 @@ ProfilerView_Render(panel Panel, rect PanelBounds, render_command_buffer* Render } } + rect FrameBounds = gs_MakeRectMinWidth(FrameListInner.Min, v2{SingleFrameWidth, gs_Height(FrameListInner)}); for (s32 F = 0; F < DEBUG_FRAME_COUNT; F++) { - v2 Min = v2{FrameListMin.x + FrameListPadding + (F * SingleFrameStep), FrameListMin.y + 4}; - v2 Max = v2{Min.x + SingleFrameWidth, FrameListMax.y - 4}; - + rect PositionedFrameBounds = gs_TranslateRectX(FrameBounds, F * SingleFrameStep); s32 FramesAgo = (GlobalDebugServices->CurrentDebugFrame - F); if (FramesAgo < 0) { FramesAgo += DEBUG_FRAME_COUNT; } v4 Color = FrameColors[GSClamp(0, FramesAgo, 3)]; - PushRenderQuad2D(RenderBuffer, Min, Max, Color); + ui_FillRect(&State->Interface_, PositionedFrameBounds, Color); } debug_frame* VisibleFrame = GetLastDebugFrame(GlobalDebugServices); - s64 FrameStartCycles = VisibleFrame->FrameStartCycles; - s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; - PrintF(&String, "Frame %d - Total Cycles: %lld", - GlobalDebugServices->CurrentDebugFrame - 1, - FrameTotalCycles); - DrawString(RenderBuffer, String, State->Interface.Font, FrameListMin - v2{0, 32}, WhiteV4); - - rect ResumeRecordingBtnBounds = MakeRectMinWidth(v2{ FrameListMax.x - 128, FrameListMin.y - 32 }, v2{ 128, 28 }); - if (ui_Button(&State->Interface_, MakeString("Resume Recording"), ResumeRecordingBtnBounds)) + ui_layout Layout = ui_CreateLayout(State->Interface_, ProcListBounds); + ui_StartRow(&Layout, 4); { - GlobalDebugServices->RecordFrames = true; + s64 FrameStartCycles = VisibleFrame->FrameStartCycles; + s64 FrameTotalCycles = VisibleFrame->FrameEndCycles - VisibleFrame->FrameStartCycles; + u32 CurrentDebugFrame = GlobalDebugServices->CurrentDebugFrame - 1; + PrintF(&String, "Frame %d", CurrentDebugFrame); + ui_LayoutDrawString(&State->Interface_, &Layout, String, WhiteV4); + + PrintF(&String, "Total Cycles: %lld", FrameTotalCycles); + ui_LayoutDrawString(&State->Interface_, &Layout, String, WhiteV4); + + // NOTE(NAME): Skipping a space for aesthetic reasons, not functional, and could + // be removed, or used for something else + ui_ReserveElementBounds(&Layout); + + if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("Resume Recording"))) + { + GlobalDebugServices->RecordFrames = true; + } } + ui_EndRow(&Layout); - rect ScopeViewBtnBounds = { - v2{ FrameListMin.x, FrameListMin.y - 60 }, - v2{ FrameListMin.x + 128, FrameListMin.y - 42 } - }; - if (ui_Button(&State->Interface_, MakeString("Scope View"), ScopeViewBtnBounds)) + ui_StartRow(&Layout, 8); { - GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; + if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("Scope View"))) + { + GlobalDebugServices->Interface.FrameView = FRAME_VIEW_PROFILER; + } + if (ui_LayoutButton(&State->Interface_, &Layout, MakeString("List View"))) + { + GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; + } } + ui_EndRow(&Layout); - rect ListViewBtnBounds = TranslateRectX(ScopeViewBtnBounds, 152); - if (ui_Button(&State->Interface_, MakeString("List View"), ListViewBtnBounds)) - { - GlobalDebugServices->Interface.FrameView = FRAME_VIEW_SCOPE_LIST; - } - - rect ViewModeBounds = { - v2{ FrameListMin.x, PanelBounds.Min.y }, - v2{ FrameListMax.x, FrameListMin.y - 96 } - }; if (GlobalDebugServices->Interface.FrameView == FRAME_VIEW_PROFILER) { - RenderProfiler_ScopeVisualization(RenderBuffer, State->Interface, Mouse, RectExpand(ViewModeBounds), - VisibleFrame, Memory); + RenderProfiler_ScopeVisualization(&State->Interface_, Layout, VisibleFrame, Memory); } else { - RenderProfiler_ListVisualization(RenderBuffer, State->Interface, Mouse, RectExpand(ViewModeBounds), - VisibleFrame, Memory); + RenderProfiler_ListVisualization(&State->Interface_, Layout, VisibleFrame, Memory); } } diff --git a/todo.txt b/todo.txt index aecaccf..a9edcb9 100644 --- a/todo.txt +++ b/todo.txt @@ -1,33 +1,22 @@ TODO FOLDHAUS +STREAM #0: Metaprogramming - Metaprogramming - fix memory layout (remeber to profile before and after) +- Make everything truly platform agnostic + - Application DLL + - math.h: present for trig functions (though this is part of the c-std lib, so it should be everywhere) + - windows.h: only thing left is InterlockedIncrement and InterlockedAdd + - Meta Layer + - ??? -- Make the DLL truly platform agnostic - - math.h: present for trig functions (though this is part of the c-std lib, so it should be everywhere) - - windows.h: only thing left is InterlockedIncrement and InterlockedAdd - -- Win32 Platform Layer - - Enumerate Directory Contents (you started this in win32_foldhaus_fileio.h) - -- Internal Log File - NOTE: This should not be a part of the debug system - - Save output log to a file continuously - - Have a window where we can view the log within the app - - Create a bar that displays the most recent error message - - :ErrorLogging - -- Make sure it works without building in Debug Mode - -- Buckets & Lists - - On second thought, I just really don't like these. Lets get rid of them, and put custom structures in place - +STREAM #1: 3D Overhaul - Rendering (Working on this elsewhere) - OpenGL 3 - Vertex Buffers + - Clipping in shaders - Layers - Lighting - - Clipping (with error checking) - Camera - pan @@ -43,28 +32,22 @@ TODO FOLDHAUS - led groups & subgroups - defined in file - motion -- Network - - Handle Error Cases - - Handle connecting a sculpture after launch - - Artnet - - Universe offsets (per sculpture) - -- Interface - - Layout functionality - - styling - - text input - - lister with icon options - - panel system: destroy panel by extending it beyond its max, not just its min - -- Asset Loading - - Need to figure out which textures are currently in graphics memory and which need to be resubmitted - - images - - icon system - integrate with interface - - Sculpture View - mouse spatial interaction - handles, and hover for info - debug capabilities (toggle strip/led/universe colors) +STREAM #2: Memory +- Buckets & Lists + - On second thought, I just really don't like these. Lets get rid of them, and put custom structures in place + +- Internal Log File + NOTE: This should not be a part of the debug system + - Save output log to a file continuously + - Have a window where we can view the log within the app + - Create a bar that displays the most recent error message + - :ErrorLogging + +STREAM #3: Nodes - Animation System - blending between animation - layers @@ -91,11 +74,32 @@ TODO FOLDHAUS - saving animation timelines - saving projects -- Settings +STRAM #4: Completeness +- Win32 Platform Layer + - Enumerate Directory Contents (you started this in win32_foldhaus_fileio.h) - Platform Layer - Mac Platform Layer +- Make sure it works without building in Debug Mode + +- Network + - Handle Error Cases + - Handle connecting a sculpture after launch + - Artnet + - Universe offsets (per sculpture) + +- Interface + - text input + - lister with icon options + +- Asset Loading + - Need to figure out which textures are currently in graphics memory and which need to be resubmitted + - images + - icon system - integrate with interface + +- Settings + Assembly -> SACN interface - need to create a data structure in CreateDMXBuffers that prevents duplication of DMXBuffers. - - thinking about a dictionary. Key is Universe, length is 256, create parallel arrays as necessary @@ -120,7 +124,7 @@ Switch To Nodes - - create separate files: foldhaus_node_engine, foldhaus_node_gui - - store interface_nodes in binary tree - - allow panning and zooming around the node canvas -- - Investigate why we're giving nodes bounds :NodesDontNeedToKnowTheirBounds +- - Investigate why we're giving nodes bounds :NodesDontNeedToKnowTheirBounds - selector node (has a list of connections that it can switch between) - evaluation step (one node at a time)