Reimplemented PrintF
This commit is contained in:
parent
7a10f4066f
commit
e69aa8d21a
|
@ -62,15 +62,15 @@ ParseAssemblyVector (char* String)
|
|||
Tokenizer.At = String;
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.x = ParseFloatUnsafe(Tokenizer.At);
|
||||
Result.x = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.y = ParseFloatUnsafe(Tokenizer.At);
|
||||
Result.y = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
EatWhitespace(&Tokenizer);
|
||||
Result.z = ParseFloatUnsafe(Tokenizer.At);
|
||||
Result.z = ParseFloatUnsafe(Tokenizer.At).FloatValue;
|
||||
EatPastCharacter(&Tokenizer, ',');
|
||||
|
||||
return Result;
|
||||
|
@ -86,7 +86,7 @@ ParseAssemblyFileHeader (tokenizer* Tokenizer, assembly_definition* Definition)
|
|||
assembly_token CountToken = ParseToken(Tokenizer);
|
||||
if (CountToken.Type == AssemblyToken_Number)
|
||||
{
|
||||
Definition->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token);
|
||||
Definition->LEDStripSize = ParseSignedIntUnsafe(CountToken.Token).SignedIntValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -112,21 +112,21 @@ ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly)
|
|||
while (*Tokenizer->At && !IsNumericExtended(*Tokenizer->At)) { Tokenizer->At++; }
|
||||
assembly_token BoxIDToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
LEDStripDef->ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token);
|
||||
LEDStripDef->ControlBoxID = ParseSignedIntUnsafe(BoxIDToken.Token).SignedIntValue;
|
||||
|
||||
// Start Universe
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token StartUniverseToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
LEDStripDef->StartUniverse = ParseSignedIntUnsafe(StartUniverseToken.Token);
|
||||
LEDStripDef->StartUniverse = ParseSignedIntUnsafe(StartUniverseToken.Token).SignedIntValue;
|
||||
|
||||
// Start Channel
|
||||
EatPastCharacter(Tokenizer, ',');
|
||||
EatWhitespace(Tokenizer);
|
||||
assembly_token StartChannelToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
LEDStripDef->StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token);
|
||||
LEDStripDef->StartChannel = ParseSignedIntUnsafe(StartChannelToken.Token).SignedIntValue;
|
||||
|
||||
// Strip Type
|
||||
// TODO(Peter): This is unused for now, and would be a branch point for parsing
|
||||
|
@ -156,7 +156,7 @@ ParseLEDStrip (tokenizer* Tokenizer, assembly_definition* Assembly)
|
|||
EatWhitespace(Tokenizer);
|
||||
assembly_token LEDsPerStripToken = ParseToken(Tokenizer);
|
||||
Assert(BoxIDToken.Type == AssemblyToken_Number);
|
||||
LEDStripDef->LEDsPerStrip = ParseSignedIntUnsafe(LEDsPerStripToken.Token);
|
||||
LEDStripDef->LEDsPerStrip = ParseSignedIntUnsafe(LEDsPerStripToken.Token).SignedIntValue;
|
||||
}
|
||||
|
||||
EatPastCharacter(Tokenizer, '}');
|
||||
|
|
|
@ -423,7 +423,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel;
|
||||
GSMemSet(Font->BitmapMemory, 0, Font->BitmapStride * Font->BitmapHeight);
|
||||
|
||||
platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14);
|
||||
platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", FontSize);
|
||||
Font->PixelHeight = FontInfo.PixelHeight;
|
||||
Font->Ascent = FontInfo.Ascent;
|
||||
Font->Descent = FontInfo.Descent;
|
||||
|
@ -435,12 +435,10 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize);
|
||||
Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize);
|
||||
|
||||
char CodepointValues[] = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+{}[];':\",./<>?`~";
|
||||
for (s32 CodepointIdx = 0; //FontInfo.CodepointStart;
|
||||
CodepointIdx < sizeof(CodepointValues) / sizeof(CodepointValues[0]); //FontInfo.CodepointOnePastLast;
|
||||
CodepointIdx++)
|
||||
for (s32 Codepoint = FontInfo.CodepointStart;
|
||||
Codepoint < FontInfo.CodepointOnePastLast;
|
||||
Codepoint++)
|
||||
{
|
||||
char Codepoint = CodepointValues[CodepointIdx];
|
||||
|
||||
u32 CodepointX, CodepointY;
|
||||
GetNextCodepointOffset(Font, &CodepointX, &CodepointY);
|
||||
|
@ -909,18 +907,6 @@ UPDATE_AND_RENDER(UpdateAndRender)
|
|||
Context.DeltaTime, State->Camera, Input, State->Transient);
|
||||
}
|
||||
|
||||
render_texture FontTexture = {};
|
||||
FontTexture.Memory = State->Font->BitmapMemory;
|
||||
FontTexture.Handle = State->Font->BitmapTextureHandle;
|
||||
FontTexture.Width = State->Font->BitmapWidth;
|
||||
FontTexture.Height = State->Font->BitmapHeight;
|
||||
FontTexture.BytesPerPixel = State->Font->BitmapBytesPerPixel;
|
||||
FontTexture.Stride = State->Font->BitmapStride;
|
||||
|
||||
PushRenderTexture2D(RenderBuffer, v2{200, 200},
|
||||
v2{200 + (r32)FontTexture.Width, 200 + (r32)FontTexture.Height},
|
||||
v4{1, 1, 1, 1}, v2{0, 0}, v2{1, 1}, &FontTexture);
|
||||
|
||||
ClearArena(State->Transient);
|
||||
EndDebugFrame(GlobalDebugServices);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ GetIndexForCodepoint (bitmap_font Font, char Codepoint)
|
|||
inline s32
|
||||
NewLineYOffset (bitmap_font Font)
|
||||
{
|
||||
s32 Result = Font.Ascent - Font.Descent;
|
||||
s32 Result = Font.Ascent + Font.Descent;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
592
gs_string.h
592
gs_string.h
|
@ -214,6 +214,7 @@ static void SetStringToCharArray (string* Dest, char* Source);
|
|||
|
||||
static void ConcatString (string* Dest, string Source);
|
||||
static void ConcatString (string* Dest, string Source, s32 Length);
|
||||
static void ConcatCharToString(string* Dest, char C);
|
||||
static void ConcatCharArrayToString (string* Dest, char* Source);
|
||||
static void ConcatCharArrayToString (string* Dest, char* Source, s32 SourceLength);
|
||||
|
||||
|
@ -235,16 +236,41 @@ static void NullTerminate (string* String);
|
|||
|
||||
|
||||
// Parsing
|
||||
static u32 ParseUnsignedInt (char* String, s32 Length);
|
||||
static s32 UIntToString (u32 Int, char* String, s32 Length);
|
||||
static s32 ParseSignedInt (char* String, s32 Length);
|
||||
static s32 IntToString (s32 Int, char* String, s32 Length);
|
||||
static s32 IntToString (s32 Int, char* String, s32 Length, s32 Offset);
|
||||
static float ParseFloat (char* String, s32 Length);
|
||||
static s32 FloatToString(float Float, char *String, s32 Length, s32 AfterPoint);
|
||||
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 (char* String, s32 Length);
|
||||
static parse_result ParseSignedInt (char* String, s32 Length);
|
||||
static parse_result ParseFloat (char* String, s32 Length);
|
||||
|
||||
// PrintF
|
||||
static s32 PrintF(string* String, char* Format, ...);
|
||||
static void PrintFArgList(char* Dest, s32 DestMax, char* Format, va_list Args);
|
||||
static void PrintF(string* String, char* Format, ...);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// String Memory Function Declarations
|
||||
|
@ -880,6 +906,16 @@ ConcatString (string* Dest, string Source, s32 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 (string* Dest, char* Source)
|
||||
{
|
||||
|
@ -1082,52 +1118,44 @@ InsertStringAt (string* Dest, string Source, s32 At)
|
|||
// String Parsing
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static u32
|
||||
static parse_result
|
||||
ParseUnsignedInt (char* String, s32 Length)
|
||||
{
|
||||
Assert(IsNumeric(*String));
|
||||
parse_result Result = {};
|
||||
Result.Type = ParseType_UnsignedInt;
|
||||
|
||||
char* Iter = String;
|
||||
u32 Result = 0;
|
||||
u32 ResultValue = 0;
|
||||
for (s32 i = 0; i < Length; i++)
|
||||
{
|
||||
Result = CharToUInt(*Iter++) + (Result * 10);
|
||||
ResultValue = CharToUInt(*Iter++) + (ResultValue * 10);
|
||||
}
|
||||
|
||||
Result.UnsignedIntValue = ResultValue;
|
||||
Result.OnePastLast = Iter;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static u32
|
||||
ParseUnisgnedIntUnsafe (char* String)
|
||||
static parse_result
|
||||
ParseUnsignedIntUnsafe (char* String)
|
||||
{
|
||||
char* Start = String;
|
||||
char* End = EatNumber(String + 1);
|
||||
return ParseUnsignedInt(String, End - Start);
|
||||
}
|
||||
|
||||
static s32
|
||||
UIntToString (u32 Int, char* String, s32 Length)
|
||||
{
|
||||
s32 Remaining = Int;
|
||||
s32 CharsCopied = 0;
|
||||
char* Iter = String;
|
||||
while (Remaining > 0 && CharsCopied < Length)
|
||||
{
|
||||
*Iter++ = '0' + (Remaining % 10);
|
||||
Remaining /= 10;
|
||||
CharsCopied++;
|
||||
}
|
||||
ReverseCharArray(String, CharsCopied);
|
||||
return CharsCopied;
|
||||
}
|
||||
|
||||
static s32
|
||||
static parse_result
|
||||
ParseSignedInt (char* String, s32 Length)
|
||||
{
|
||||
Assert(Length > 0);
|
||||
parse_result Result = {};
|
||||
Result.Type = ParseType_SignedInt;
|
||||
|
||||
s32 Negative = 1;
|
||||
s32 LengthRemaining = Length;
|
||||
s32 Result = 0;
|
||||
s32 ResultValue = 0;
|
||||
char* Iter = String;
|
||||
|
||||
if (*Iter == '-') {
|
||||
|
@ -1138,15 +1166,18 @@ ParseSignedInt (char* String, s32 Length)
|
|||
|
||||
for (s32 i = 0; i < LengthRemaining; i++)
|
||||
{
|
||||
Result = CharToUInt(*Iter++) + (Result * 10);
|
||||
ResultValue = CharToUInt(*Iter++) + (ResultValue * 10);
|
||||
}
|
||||
|
||||
Result *= Negative;
|
||||
ResultValue *= Negative;
|
||||
|
||||
Result.SignedIntValue = ResultValue;
|
||||
Result.OnePastLast = Iter;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static s32
|
||||
static parse_result
|
||||
ParseSignedIntUnsafe (char* String)
|
||||
{
|
||||
char* Start = String;
|
||||
|
@ -1154,47 +1185,15 @@ ParseSignedIntUnsafe (char* String)
|
|||
return ParseSignedInt(String, End - Start);
|
||||
}
|
||||
|
||||
static s32
|
||||
IntToString (s32 Int, char* String, s32 Length)
|
||||
{
|
||||
s32 Remaining = Int;
|
||||
s32 CharsCopied = 0;
|
||||
char* Iter = String;
|
||||
|
||||
bool Negative = Remaining < 0;
|
||||
Remaining = GSAbs(Remaining);
|
||||
|
||||
while (Remaining > 0 && CharsCopied < Length)
|
||||
{
|
||||
*Iter++ = '0' + (Remaining % 10);
|
||||
Remaining /= 10;
|
||||
CharsCopied++;
|
||||
}
|
||||
|
||||
if (Negative)
|
||||
{
|
||||
*Iter++ = '-';
|
||||
CharsCopied++;
|
||||
}
|
||||
|
||||
ReverseCharArray(String, CharsCopied);
|
||||
return CharsCopied;
|
||||
}
|
||||
|
||||
static s32
|
||||
IntToString (s32 Int, char* String, s32 Length, s32 Offset)
|
||||
{
|
||||
char* StringStart = String + Offset;
|
||||
s32 LengthWritten = IntToString(Int, StringStart, Length - Offset);
|
||||
return LengthWritten;
|
||||
}
|
||||
|
||||
static float
|
||||
static parse_result
|
||||
ParseFloat (char* String, s32 Length)
|
||||
{
|
||||
parse_result Result = {};
|
||||
Result.Type = ParseType_Float;
|
||||
|
||||
s32 Negative = 1;
|
||||
s32 LengthRemaining = Length;
|
||||
float Result = 0;
|
||||
float ResultValue = 0;
|
||||
char* Iter = String;
|
||||
|
||||
if (*Iter == '-') {
|
||||
|
@ -1207,7 +1206,7 @@ ParseFloat (char* String, s32 Length)
|
|||
{
|
||||
if (IsNumeric(*Iter))
|
||||
{
|
||||
Result = (float)CharToUInt(*Iter++) + (Result * 10);
|
||||
ResultValue = (float)CharToUInt(*Iter++) + (ResultValue * 10);
|
||||
}
|
||||
else if (*Iter == '.' || *Iter == 0)
|
||||
{
|
||||
|
@ -1236,15 +1235,18 @@ ParseFloat (char* String, s32 Length)
|
|||
}
|
||||
|
||||
AfterPoint = AfterPoint / GSPow(10, PlacesAfterPoint);
|
||||
Result += AfterPoint;
|
||||
ResultValue += AfterPoint;
|
||||
}
|
||||
|
||||
Result *= Negative;
|
||||
ResultValue *= Negative;
|
||||
|
||||
Result.FloatValue = ResultValue;
|
||||
Result.OnePastLast = Iter;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static float
|
||||
static parse_result
|
||||
ParseFloatUnsafe (char* String)
|
||||
{
|
||||
char* Start = String;
|
||||
|
@ -1253,19 +1255,77 @@ ParseFloatUnsafe (char* String)
|
|||
}
|
||||
|
||||
static s32
|
||||
FloatToString(float Float, char *String, s32 Length, s32 AfterPoint)
|
||||
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, Length);
|
||||
s32 i = IntToString(IPart, String, MaxLength);
|
||||
|
||||
if (AfterPoint > 1)
|
||||
{
|
||||
String[i++] = '.';
|
||||
|
||||
s32 FPartInt = FPart * GSPow(10, AfterPoint);
|
||||
i += IntToString(FPartInt, String, Length, i);
|
||||
i += IntToString(FPartInt, String, MaxLength, i, 0, 0);
|
||||
}
|
||||
|
||||
return i;
|
||||
|
@ -1275,69 +1335,333 @@ FloatToString(float Float, char *String, s32 Length, s32 AfterPoint)
|
|||
// 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, '-');
|
||||
}
|
||||
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] == '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;
|
||||
}
|
||||
|
||||
internal void
|
||||
PrintF (string* String, char* Format, ...)
|
||||
{
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
|
||||
#if 0
|
||||
s32 LengthPrinted = 0;
|
||||
char* DestChar = Destination;
|
||||
|
||||
char* C = Format;
|
||||
while(*C)
|
||||
{
|
||||
if (*C == '%')
|
||||
{
|
||||
C++;
|
||||
if (*C == 's') // string
|
||||
{
|
||||
C++;
|
||||
char* InsertString = va_arg(Args, char*);
|
||||
s32 LengthCopied = CopyCharArray(InsertString, DestChar, DestLength - LengthPrinted);
|
||||
DestChar += LengthCopied;
|
||||
LengthPrinted += LengthCopied;
|
||||
}
|
||||
else if(*C == 'd') // integer
|
||||
{
|
||||
C++;
|
||||
s32 Integer = va_arg(Args, s32);
|
||||
|
||||
s32 IntLength = IntToString(Integer, DestChar, DestLength - LengthPrinted);
|
||||
DestChar += IntLength;
|
||||
LengthPrinted += IntLength;
|
||||
}
|
||||
else if (*C == 'f')
|
||||
{
|
||||
C++;
|
||||
r32 Float = va_arg(Args, r32);
|
||||
s32 FloatLength = FloatToString(Float, DestChar, DestLength - LengthPrinted, 5);
|
||||
DestChar += FloatLength;
|
||||
LengthPrinted += FloatLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
*DestChar++ = *C++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*DestChar++ = *C++;
|
||||
}
|
||||
}
|
||||
|
||||
if (LengthPrinted >= DestLength)
|
||||
{
|
||||
LengthPrinted = DestLength - 1;
|
||||
}
|
||||
*(Destination + LengthPrinted) = 0;
|
||||
|
||||
#endif
|
||||
|
||||
String->Length = PrintFArgsList(String->Memory, String->Max, Format, Args);
|
||||
va_end(Args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue