384 lines
8.7 KiB
C
384 lines
8.7 KiB
C
|
//
|
||
|
// File: foldhaus_serializer.h
|
||
|
// Author: Peter Slattery
|
||
|
// Creation Date: 2020-10-09
|
||
|
//
|
||
|
#ifndef FOLDHAUS_SERIALIZER_H
|
||
|
|
||
|
struct serializer
|
||
|
{
|
||
|
gs_string String;
|
||
|
u32 Indent;
|
||
|
gs_const_string* Identifiers;
|
||
|
u32 IdentifiersCount;
|
||
|
};
|
||
|
|
||
|
internal gs_const_string
|
||
|
Serializer_GetIdent(serializer* Serializer, u32 Index)
|
||
|
{
|
||
|
gs_const_string Result = Serializer->Identifiers[Index];
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
// Serializing
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteIndent(serializer* Serializer)
|
||
|
{
|
||
|
for (u32 i = 0; i < Serializer->Indent; i++)
|
||
|
{
|
||
|
AppendPrintF(&Serializer->String, " ");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteF(serializer* Serializer, char* Format, ...)
|
||
|
{
|
||
|
Serializer_WriteIndent(Serializer);
|
||
|
|
||
|
va_list Args;
|
||
|
va_start(Args, Format);
|
||
|
PrintFArgsList(&Serializer->String, Format, Args);
|
||
|
va_end(Args);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_OpenStruct(serializer* Serializer, gs_const_string StructName)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S:{\n", StructName);
|
||
|
Serializer->Indent++;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_OpenStruct(serializer* Serializer, u32 StructIdentifier)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, StructIdentifier);
|
||
|
Serializer_WriteF(Serializer, "%S:{\n", Ident);
|
||
|
Serializer->Indent++;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_CloseStruct(serializer* Serializer)
|
||
|
{
|
||
|
Serializer->Indent--;
|
||
|
Serializer_WriteF(Serializer, "};\n");
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S: %S;\n", Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||
|
Serializer_WriteValue(Serializer, Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, u32 Value)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S: %d;\n", Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, u32 Value)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||
|
Serializer_WriteValue(Serializer, Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, gs_const_string Ident, r32 Value)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S: %f;\n", Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteValue(serializer* Serializer, u32 IdentIndex, r32 Value)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||
|
Serializer_WriteValue(Serializer, Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteStringValue(serializer* Serializer, gs_const_string Ident, gs_const_string Value)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S: \"%S\";\n", Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteStringValue(serializer* Serializer, u32 IdentIndex, gs_const_string Value)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||
|
Serializer_WriteStringValue(Serializer, Ident, Value);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteV3Value(serializer* Serializer, gs_const_string Ident, v3 Value)
|
||
|
{
|
||
|
Serializer_WriteF(Serializer, "%S: (%f, %f, %f);\n", Ident, Value.x, Value.y, Value.z);
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value)
|
||
|
{
|
||
|
gs_const_string Ident = Serializer_GetIdent(Serializer, IdentIndex);
|
||
|
Serializer_WriteV3Value(Serializer, Ident, Value);
|
||
|
}
|
||
|
|
||
|
// Parsing
|
||
|
|
||
|
struct parser
|
||
|
{
|
||
|
gs_string String;
|
||
|
|
||
|
gs_const_string* Identifiers;
|
||
|
u32 IdentifiersCount;
|
||
|
|
||
|
u32 Line;
|
||
|
|
||
|
char* LineStart;
|
||
|
char* At;
|
||
|
|
||
|
gs_memory_arena* Arena;
|
||
|
};
|
||
|
|
||
|
internal gs_const_string
|
||
|
Parser_GetIdent(parser Parser, u32 Index)
|
||
|
{
|
||
|
gs_const_string Result = Parser.Identifiers[Index];
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_AtValidPosition(parser Parser)
|
||
|
{
|
||
|
u64 Offset = Parser.At - Parser.String.Str;
|
||
|
bool Result = (Offset < Parser.String.Length);
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Parser_AdvanceChar(parser* P)
|
||
|
{
|
||
|
if (IsNewline(P->At[0]))
|
||
|
{
|
||
|
P->Line += 1;
|
||
|
P->LineStart = P->At + 1;
|
||
|
}
|
||
|
P->At++;
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Parser_EatWhitespace(parser* P)
|
||
|
{
|
||
|
while(Parser_AtValidPosition(*P) && IsNewlineOrWhitespace(P->At[0]))
|
||
|
{
|
||
|
Parser_AdvanceChar(P);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void
|
||
|
Parser_EatToNewLine(parser* P)
|
||
|
{
|
||
|
while(Parser_AtValidPosition(*P) && !IsNewline(P->At[0]))
|
||
|
{
|
||
|
Parser_AdvanceChar(P);
|
||
|
}
|
||
|
Parser_EatWhitespace(P);
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_AdvanceIfTokenEquals(parser* P, gs_const_string Value)
|
||
|
{
|
||
|
bool Result = true;
|
||
|
|
||
|
char* PAt = P->At;
|
||
|
char* VAt = Value.Str;
|
||
|
while (*VAt != 0)
|
||
|
{
|
||
|
if (*PAt != *VAt)
|
||
|
{
|
||
|
Result = false;
|
||
|
break;
|
||
|
}
|
||
|
PAt += 1;
|
||
|
VAt += 1;
|
||
|
}
|
||
|
|
||
|
// TODO(Peter): What if the token is a subset of Value? ie. this would return true for
|
||
|
// T->At = hello_world and Value = hello_
|
||
|
// But the next token we read would fail
|
||
|
|
||
|
if (Result)
|
||
|
{
|
||
|
P->At = PAt;
|
||
|
Parser_EatWhitespace(P);
|
||
|
}
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_AdvanceIfLineEnd(parser* P)
|
||
|
{
|
||
|
bool Result = Parser_AdvanceIfTokenEquals(P, ConstString(";"));
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_ReadString(parser* P, gs_const_string String)
|
||
|
{
|
||
|
// string;
|
||
|
bool Result = Parser_AdvanceIfTokenEquals(P, String);
|
||
|
Result &= Parser_AdvanceIfLineEnd(P);
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_ReadString(parser* P, u32 IdentIndex)
|
||
|
{
|
||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||
|
return Parser_ReadString(P, Ident);
|
||
|
}
|
||
|
|
||
|
internal gs_string
|
||
|
Parser_ReadStringValue(parser* P, gs_const_string Ident)
|
||
|
{
|
||
|
// ident: "value";
|
||
|
gs_string Result = {};
|
||
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
||
|
Parser_AdvanceIfTokenEquals(P, ConstString("\"")))
|
||
|
{
|
||
|
gs_const_string FileString = {0};
|
||
|
FileString.Str = P->At;
|
||
|
|
||
|
while (Parser_AtValidPosition(*P) && P->At[0] != '"')
|
||
|
{
|
||
|
Parser_AdvanceChar(P);
|
||
|
}
|
||
|
|
||
|
FileString.Length = P->At - FileString.Str;
|
||
|
if (Parser_AdvanceIfTokenEquals(P, ConstString("\"")) &&
|
||
|
Parser_AdvanceIfLineEnd(P))
|
||
|
{
|
||
|
Result = PushStringF(P->Arena, FileString.Length, "%S", FileString);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO(pjs): Error
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal gs_string
|
||
|
Parser_ReadStringValue(parser* P, u32 IdentIndex)
|
||
|
{
|
||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||
|
return Parser_ReadStringValue(P, Ident);
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_ReadOpenStruct(parser* P, gs_const_string Ident)
|
||
|
{
|
||
|
// ident: {
|
||
|
bool Result = Parser_AdvanceIfTokenEquals(P, Ident);
|
||
|
Result &= Parser_AdvanceIfTokenEquals(P, ConstString(":"));
|
||
|
Result &= Parser_AdvanceIfTokenEquals(P, ConstString("{"));
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_ReadOpenStruct(parser* P, u32 IdentIndex)
|
||
|
{
|
||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||
|
return Parser_ReadOpenStruct(P, Ident);
|
||
|
}
|
||
|
|
||
|
internal bool
|
||
|
Parser_ReadCloseStruct(parser* P)
|
||
|
{
|
||
|
// }
|
||
|
bool Result = Parser_AdvanceIfTokenEquals(P, ConstString("}"));
|
||
|
Result &= Parser_AdvanceIfLineEnd(P);
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal gs_const_string
|
||
|
Parser_ReadNumberString(parser* P)
|
||
|
{
|
||
|
gs_const_string Result = {};
|
||
|
Result.Str = P->At;
|
||
|
while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0]))
|
||
|
{
|
||
|
Parser_AdvanceChar(P);
|
||
|
}
|
||
|
Result.Length = P->At - Result.Str;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal u32
|
||
|
Parser_ReadU32Value(parser* P, gs_const_string Ident)
|
||
|
{
|
||
|
// ident: value;
|
||
|
u32 Result = 0;
|
||
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||
|
{
|
||
|
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||
|
if (Parser_AdvanceIfLineEnd(P))
|
||
|
{
|
||
|
Result = (u32)ParseInt(NumStr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO(pjs): Error
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal u32
|
||
|
Parser_ReadU32Value(parser* P, u32 IdentIndex)
|
||
|
{
|
||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||
|
return Parser_ReadU32Value(P, Ident);
|
||
|
}
|
||
|
|
||
|
internal r32
|
||
|
Parser_ReadR32Value(parser* P, gs_const_string Ident)
|
||
|
{
|
||
|
// ident: value;
|
||
|
r32 Result = 0;
|
||
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||
|
{
|
||
|
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||
|
if (Parser_AdvanceIfLineEnd(P))
|
||
|
{
|
||
|
Result = (r32)ParseFloat(NumStr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// TODO(pjs): Error
|
||
|
}
|
||
|
}
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
internal u32
|
||
|
Parser_ReadR32Value(parser* P, u32 IdentIndex)
|
||
|
{
|
||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||
|
return Parser_ReadR32Value(P, Ident);
|
||
|
}
|
||
|
|
||
|
|
||
|
#define FOLDHAUS_SERIALIZER_H
|
||
|
#endif // FOLDHAUS_SERIALIZER_H
|