generate metadata in code

This commit is contained in:
Asuro
2025-04-04 20:30:55 +02:00
parent 12c546b6dc
commit 34876ff652
10 changed files with 440 additions and 278 deletions

View File

@@ -32,7 +32,7 @@ namespace Gen
constexpr char StructHeader2[] = constexpr char StructHeader2[] =
R"END( struct %s R"END( struct %s
{ {
static constexpr uint32_t Hash = %u; static constexpr uint16_t TypeIdx = %u;
)END"; )END";
constexpr char StructField4[] = constexpr char StructField4[] =
@@ -46,8 +46,8 @@ namespace Gen
constexpr char EnumHeader4[] = constexpr char EnumHeader4[] =
R"END( struct %s R"END( struct %s
{ {
static constexpr uint16_t EnumIdx = %u;
static constexpr int32_t EntryCount = %u; static constexpr int32_t EntryCount = %u;
static constexpr uint32_t Hash = %u;
enum Enum : %s enum Enum : %s
{ {
)END"; )END";
@@ -112,6 +112,44 @@ namespace Gen
return isOk; return isOk;
} }
)END"; )END";
constexpr char MetadataStart1[] = R"END(
namespace Meta {
struct TypeDef
{
uint32_t Size = 0;
uint32_t Hash = 0;
const char Name[64]{"Dummy"};
uint16_t ChildCount = 0;
uint16_t ChildIndices[64]{0};
};
struct EnumDef
{
uint32_t Size = 0;
uint32_t Hash = 0;
};
struct MetadataTable
{
TypeDef TypeDefinitions[%u]
{
)END";
constexpr char MetadataTypeEntry5[] = R"END( TypeDef{sizeof(%s), %u, "%s", %u, {%s}},
)END";
constexpr char MetadataEnumStart1[] = R"END( };
EnumDef EnumDefinitions[%u]
{
)END";
constexpr char MetadataEnumEntry2[] = R"END( EnumDef{sizeof(%s::Enum), %u},
)END";
constexpr char MetadataEnd[] = R"END( };
};
constexpr MetadataTable Metadata;
}
)END";
} // namespace WriteTemplates } // namespace WriteTemplates
void CppFileWriter::InitBuffer(WriteBuffer& buf) void CppFileWriter::InitBuffer(WriteBuffer& buf)
@@ -164,26 +202,25 @@ void CppFileWriter::WriteInternal(WriteBuffer& buf, const char* templateStr, va_
buf.WrittenBytes += bx::vsnprintf(&buf.Data[buf.WrittenBytes], BufferRequestSize, templateStr, args); buf.WrittenBytes += bx::vsnprintf(&buf.Data[buf.WrittenBytes], BufferRequestSize, templateStr, args);
} }
void CppFileWriter::PrintTypeName(char* buf, void CppFileWriter::PrintTypeName(char* buf, int32_t bufSize, Def::TypeRef type, const Def::DefinitionFile& definitions)
int32_t bufSize,
const Def::FieldType& type,
const Def::DefinitionFile& definitions)
{ {
if (type.FieldKind == Def::EFieldType::Native) if (buf == nullptr || bufSize == 0 || !IsValid(type))
{ {
if (int32_t(type.Native) < Gen::KnownType::EntryCount) LOG_ERROR(0, "Invalid PrintTypeName call!");
return;
}
if (type.FieldKind == Def::EFieldType::DefinedClass)
{
auto& t = definitions.Types[type.TypeIdx];
if ((uint32_t)t.TypeFlags & (uint32_t)Def::ETypeFlags::IsNative)
{ {
bx::strCopy(buf, bufSize, Gen::KnownType::CName[size_t(type.Native)]); bx::strCopy(buf, bufSize, t.NativeCName);
} }
else else
{ {
LOG_ERROR(0, "Unknown native type index: %u", type.Native); bx::strCopy(buf, bufSize, t.Name);
} }
} }
else if (type.FieldKind == Def::EFieldType::DefinedClass)
{
bx::strCopy(buf, bufSize, definitions.Types[type.TypeIdx].Name);
}
else if (type.FieldKind == Def::EFieldType::DefinedEnum) else if (type.FieldKind == Def::EFieldType::DefinedEnum)
{ {
bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name); bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name);
@@ -197,11 +234,15 @@ void CppFileWriter::WriteEnums(const Def::DefinitionFile& definitions)
{ {
const Def::Enum& e = definitions.Enums[enumIdx]; const Def::Enum& e = definitions.Enums[enumIdx];
Write(WriteTemplates::EnumHeader4, if (!IsValid(e.EnumType))
e.Name, {
e.EntryCount, LOG_ERROR(0, "Invalid enum type (enum %i)", enumIdx);
e.Hash, continue;
Gen::KnownType::CName[(int32_t)e.EnumType.Native]); }
char Buf[Def::MaxNameLength]{0};
PrintTypeName(Buf, sizeof(Buf), e.EnumType, definitions);
Write(WriteTemplates::EnumHeader4, e.Name, enumIdx, e.EntryCount, Buf);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx) for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{ {
Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]); Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]);
@@ -230,15 +271,16 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx) for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)
{ {
const Def::Type& t = definitions.Types[typeIdx]; const Def::Type& t = definitions.Types[typeIdx];
if ((uint32_t)t.TypeFlags & (uint32_t)Def::ETypeFlags::IsNative) continue;
Write(WriteTemplates::StructHeader2, t.Name, t.Hash); Write(WriteTemplates::StructHeader2, t.Name, typeIdx);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx) for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{ {
char Type[64]{0}; char Type[64]{0};
PrintTypeName(Type, sizeof(Type), t.FieldTypes[fieldIdx], definitions); PrintTypeName(Type, sizeof(Type), t.FieldTypes[fieldIdx], definitions);
char Array[32]{0}; char Array[32]{0};
uint32_t ArraySize = t.FieldArraySizes[fieldIdx]; uint32_t ArraySize = t.FieldArraySizes[fieldIdx];
if (ArraySize > 0) if (ArraySize > 0 && ArraySize != UINT32_MAX)
{ {
bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize); bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize);
} }
@@ -254,6 +296,11 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
for (int32_t enumIdx = 0; enumIdx < definitions.EnumCount; ++enumIdx) for (int32_t enumIdx = 0; enumIdx < definitions.EnumCount; ++enumIdx)
{ {
const Def::Enum& e = definitions.Enums[enumIdx]; const Def::Enum& e = definitions.Enums[enumIdx];
if (!IsValid(e.EnumType))
{
LOG_ERROR(0, "Invalid enum!");
continue;
}
bx::snprintf(nameBuf, sizeof(nameBuf), "%s::Enum", e.Name); bx::snprintf(nameBuf, sizeof(nameBuf), "%s::Enum", e.Name);
PrintTypeName(fieldBuf, sizeof(fieldBuf), e.EnumType, definitions); PrintTypeName(fieldBuf, sizeof(fieldBuf), e.EnumType, definitions);
@@ -268,13 +315,16 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
WriteCpp(WriteTemplates::LoadFuncBodyEnum2, fieldBuf, fieldBuf); WriteCpp(WriteTemplates::LoadFuncBodyEnum2, fieldBuf, fieldBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnd); WriteCpp(WriteTemplates::LoadFuncBodyEnd);
} }
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx) for (uint16_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)
{ {
const Def::Type& t = definitions.Types[typeIdx]; const Def::Type& t = definitions.Types[typeIdx];
Write(WriteTemplates::SaveFuncHeader1, t.Name); char typeName[Def::MaxNameLength]{0};
Write(WriteTemplates::LoadFuncHeader1, t.Name); PrintTypeName(typeName, sizeof(typeName), {typeIdx, Def::EFieldType::DefinedClass}, definitions);
WriteCpp(WriteTemplates::SaveFuncBodyStart1, t.Name); Write(WriteTemplates::SaveFuncHeader1, typeName);
Write(WriteTemplates::LoadFuncHeader1, typeName);
WriteCpp(WriteTemplates::SaveFuncBodyStart1, typeName);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx) for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{ {
WriteCpp(WriteTemplates::SaveFuncBodyType3, WriteCpp(WriteTemplates::SaveFuncBodyType3,
@@ -284,7 +334,7 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
} }
WriteCpp(WriteTemplates::SaveFuncBodyEnd); WriteCpp(WriteTemplates::SaveFuncBodyEnd);
WriteCpp(WriteTemplates::LoadFuncBodyStart1, t.Name); WriteCpp(WriteTemplates::LoadFuncBodyStart1, typeName);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx) for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{ {
WriteCpp(WriteTemplates::LoadFuncBodyType3, WriteCpp(WriteTemplates::LoadFuncBodyType3,
@@ -295,6 +345,33 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
WriteCpp(WriteTemplates::LoadFuncBodyEnd); WriteCpp(WriteTemplates::LoadFuncBodyEnd);
} }
} }
void CppFileWriter::WriteMetadata(const Def::DefinitionFile& definitions)
{
Write(WriteTemplates::MetadataStart1, definitions.TypeCount);
for (uint16_t i = 0; i < definitions.TypeCount; ++i)
{
auto& type = definitions.Types[i];
char fieldStr[256]{0};
for (int32_t j = 0; j < type.FieldCount; ++j)
{
if (j != 0) bx::strCat(fieldStr, sizeof(fieldStr), ", ");
char numBuf[8]{0};
bx::snprintf(numBuf, sizeof(numBuf), "%u", type.FieldTypes[j].TypeIdx);
bx::strCat(fieldStr, sizeof(fieldStr), numBuf);
}
char typeStr[Def::MaxNameLength]{0};
PrintTypeName(typeStr, sizeof(typeStr), {i, Def::EFieldType::DefinedClass}, definitions);
Write(WriteTemplates::MetadataTypeEntry5, typeStr, type.Hash, type.Name, type.FieldCount, fieldStr);
}
Write(WriteTemplates::MetadataEnumStart1, definitions.EnumCount);
for (int32_t i = 0; i < definitions.EnumCount; ++i)
{
Write(WriteTemplates::MetadataEnumEntry2, definitions.Enums[i].Name, definitions.Enums[i].Hash);
}
Write(WriteTemplates::MetadataEnd);
}
void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions) void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions)
{ {
LOG(0, "Generating output files..."); LOG(0, "Generating output files...");
@@ -307,6 +384,7 @@ void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::Definitio
WriteEnums(definitions); WriteEnums(definitions);
WriteTypes(definitions); WriteTypes(definitions);
WriteSaveLoadMethods(definitions); WriteSaveLoadMethods(definitions);
WriteMetadata(definitions);
Write(WriteTemplates::FileEnd); Write(WriteTemplates::FileEnd);
WriteCpp(WriteTemplates::FileEnd); WriteCpp(WriteTemplates::FileEnd);
@@ -334,36 +412,3 @@ void CppFileWriter::WriteCpp(const char* templateStr, ...)
WriteInternal(CppWrite, templateStr, args); WriteInternal(CppWrite, templateStr, args);
va_end(args); va_end(args);
} }
void CppFileWriter::WriteTypeDataFile(const bx::FilePath& outDir, const Def::DefinitionFile& definitions)
{
constexpr const char _4cc[] = "TDAT";
constexpr uint32_t version = 1;
bx::FilePath typeDataFilePath = outDir;
typeDataFilePath.join("TypeData.bin");
bx::Error err;
bx::FileWriter writer;
if (!writer.open(typeDataFilePath, false, &err))
{
LOG_ERROR(0, "Failed to open type data file to write: %s", err.getMessage().getCPtr());
return;
}
uint32_t size = sizeof(definitions);
writer.write(_4cc, 4, &err);
if (!err.isOk())
{
LOG_ERROR(0, "Failed to write type data: %s", err.getMessage().getCPtr());
writer.close();
return;
}
writer.write(&version, sizeof(version), &err);
writer.write(&size, sizeof(size), &err);
writer.write(&definitions, sizeof(definitions), &err);
if (!err.isOk())
{
LOG_ERROR(0, "Failed to write type data: %s", err.getMessage().getCPtr());
}
writer.close();
return;
}

View File

@@ -21,13 +21,13 @@ struct CppFileWriter
void WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args); void WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args);
public: public:
void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, const Def::DefinitionFile& definitions); void PrintTypeName(char* buf, int32_t bufSize, Def::TypeRef type, const Def::DefinitionFile& definitions);
void WriteEnums(const Def::DefinitionFile& definitions); void WriteEnums(const Def::DefinitionFile& definitions);
void WriteTypes(const Def::DefinitionFile& definitions); void WriteTypes(const Def::DefinitionFile& definitions);
void WriteSaveLoadMethods(const Def::DefinitionFile& definitions); void WriteSaveLoadMethods(const Def::DefinitionFile& definitions);
void WriteMetadata(const Def::DefinitionFile& definitions);
void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions); void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions);
void Write(const char* templateStr, ...); void Write(const char* templateStr, ...);
void WriteCpp(const char* templateStr, ...); void WriteCpp(const char* templateStr, ...);
void WriteTypeDataFile(const bx::FilePath& outDir, const Def::DefinitionFile& definitions);
}; };

View File

@@ -1,41 +0,0 @@
#include "Def.h"
#define INST(T) \
template bool Save<T>(const T* obj, uint32_t count, Serializer& serializer); \
template bool Load<T>(T * obj, uint32_t count, Deserializer & serializer);
namespace Gen
{
template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk;
}
return isOk;
}
template <typename T> bool Load(T* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk;
}
return isOk;
}
INST(uint8_t)
INST(uint16_t)
INST(uint32_t)
INST(uint64_t)
INST(int8_t)
INST(int16_t)
INST(int32_t)
INST(int64_t)
INST(float)
INST(double)
INST(bool)
INST(char)
} // namespace Gen

View File

@@ -1,125 +0,0 @@
#pragma once
#include "../TypeDef.h"
// #include "../game/Log.h"
#include "bx/string.h"
#include <bx/file.h>
#include <cstdint>
#ifndef LOG_ERROR
#define LOG_ERROR(...)
#endif
namespace Gen
{
struct EmbeddedTypeDef
{
uint32_t Size = sizeof(Def::DefinitionFile);
Def::DefinitionFile Data;
};
struct Serializer
{
bx::Error Err;
bx::FilePath Path;
bx::FileWriter Writer;
bool Init(const bx::FilePath& path)
{
Path = path;
Writer.open(path, false, &Err);
return Err.isOk();
}
template <typename T> bool WriteT(const char* _4cc, const T& data)
{
if (!Write(_4cc, 4)) return false;
uint32_t hash = data.Hash;
if (!Write(&hash, sizeof(hash))) return false;
uint32_t size = sizeof(T);
if (!Write(&size, sizeof(size))) return false;
return Save(&data, 1, *this);
}
bool Write(const void* data, uint32_t size)
{
Writer.write(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Write error: %s", Err.getMessage().getCPtr());
return Err.isOk();
}
void Finish()
{
Writer.close();
}
};
struct Deserializer
{
bx::Error Err;
bx::FilePath Path;
bx::FileReader Reader;
bool Init(const bx::FilePath& path)
{
Path = path;
Reader.open(path, &Err);
return Err.isOk();
}
bool Read(void* data, uint32_t size)
{
Reader.read(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Read error: %s", Err.getMessage().getCPtr());
return Err.isOk();
}
template <typename T> bool ReadT(const char* _4cc, T& data)
{
char magic[5]{0};
if (!Read(magic, 4)) return false;
bx::StringView given{_4cc, 4};
bx::StringView loaded{magic, 4};
if (bx::strCmp(given, loaded) != 0)
{
LOG_ERROR("Magic mismatch! %s != %s", _4cc, magic);
return false;
}
uint32_t hash = 0;
if (!Read(&hash, sizeof(hash))) return false;
if (data.Hash != hash)
{
LOG_ERROR("Hash mismatch! %u != %u", data.Hash, hash);
return false;
}
uint32_t size = 0;
if (!Read(&size, sizeof(size))) return false;
if (sizeof(T) != size)
{
LOG_ERROR("Size mismatch! %u != %u", sizeof(T), size);
return false;
}
if (!Load(&data, 1, *this))
{
LOG_ERROR("Failed to load: %s", Err.getMessage().getCPtr());
return false;
}
return true;
}
void Finish()
{
Reader.close();
}
};
template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer);
template <typename T> bool Load(T* obj, uint32_t count, Deserializer& serializer);
} // namespace Gen

View File

@@ -8,7 +8,7 @@ namespace Gen
bool isOk = true; bool isOk = true;
for (uint32_t i = 0; i < count; ++i) for (uint32_t i = 0; i < count; ++i)
{ {
auto val = (int32_t)obj[i]; auto val = (uint8_t)obj[i];
isOk = Save(&val, 1, serializer) && isOk; isOk = Save(&val, 1, serializer) && isOk;
} }
return isOk; return isOk;
@@ -18,11 +18,203 @@ namespace Gen
bool isOk = true; bool isOk = true;
for (uint32_t i = 0; i < count; ++i) for (uint32_t i = 0; i < count; ++i)
{ {
int32_t& val = (int32_t&)obj[i]; uint8_t& val = (uint8_t&)obj[i];
isOk = Load(&val, 1, serializer) && isOk; isOk = Load(&val, 1, serializer) && isOk;
} }
return isOk; return isOk;
} }
bool Save(const int8_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(int8_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const int16_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(int16_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const int32_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(int32_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const int64_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(int64_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const uint8_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(uint8_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const uint16_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(uint16_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const uint32_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(uint32_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const uint64_t* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(uint64_t* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const bool* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(bool* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const float* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(float* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const double* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(double* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const char* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Load(char* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
}
return isOk;
}
bool Save(const Test* obj, uint32_t count, Serializer& serializer) bool Save(const Test* obj, uint32_t count, Serializer& serializer)
{ {
bool isOk = true; bool isOk = true;

View File

@@ -7,9 +7,9 @@ namespace Gen
struct Deserializer; struct Deserializer;
struct KnownType struct KnownType
{ {
static constexpr uint16_t EnumIdx = 0;
static constexpr int32_t EntryCount = 12; static constexpr int32_t EntryCount = 12;
static constexpr uint32_t Hash = 2024002654; enum Enum : uint8_t
enum Enum : int32_t
{ {
i8, i8,
i16, i16,
@@ -57,12 +57,12 @@ namespace Gen
}; };
struct Test struct Test
{ {
static constexpr uint32_t Hash = 273256278; static constexpr uint16_t TypeIdx = 12;
uint32_t Number = {}; uint32_t Number = {};
}; };
struct Texture struct Texture
{ {
static constexpr uint32_t Hash = 992460010; static constexpr uint16_t TypeIdx = 13;
uint32_t Width = {}; uint32_t Width = {};
uint32_t Height = {}; uint32_t Height = {};
char StrTest[3] = {}; char StrTest[3] = {};
@@ -70,8 +70,76 @@ namespace Gen
}; };
bool Save(const KnownType::Enum* obj, uint32_t count, Serializer& serializer); bool Save(const KnownType::Enum* obj, uint32_t count, Serializer& serializer);
bool Load(KnownType::Enum* obj, uint32_t count, Deserializer& serializer); bool Load(KnownType::Enum* obj, uint32_t count, Deserializer& serializer);
bool Save(const int8_t* obj, uint32_t count, Serializer& serializer);
bool Load(int8_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const int16_t* obj, uint32_t count, Serializer& serializer);
bool Load(int16_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const int32_t* obj, uint32_t count, Serializer& serializer);
bool Load(int32_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const int64_t* obj, uint32_t count, Serializer& serializer);
bool Load(int64_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const uint8_t* obj, uint32_t count, Serializer& serializer);
bool Load(uint8_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const uint16_t* obj, uint32_t count, Serializer& serializer);
bool Load(uint16_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const uint32_t* obj, uint32_t count, Serializer& serializer);
bool Load(uint32_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const uint64_t* obj, uint32_t count, Serializer& serializer);
bool Load(uint64_t* obj, uint32_t count, Deserializer& serializer);
bool Save(const bool* obj, uint32_t count, Serializer& serializer);
bool Load(bool* obj, uint32_t count, Deserializer& serializer);
bool Save(const float* obj, uint32_t count, Serializer& serializer);
bool Load(float* obj, uint32_t count, Deserializer& serializer);
bool Save(const double* obj, uint32_t count, Serializer& serializer);
bool Load(double* obj, uint32_t count, Deserializer& serializer);
bool Save(const char* obj, uint32_t count, Serializer& serializer);
bool Load(char* obj, uint32_t count, Deserializer& serializer);
bool Save(const Test* obj, uint32_t count, Serializer& serializer); bool Save(const Test* obj, uint32_t count, Serializer& serializer);
bool Load(Test* obj, uint32_t count, Deserializer& serializer); bool Load(Test* obj, uint32_t count, Deserializer& serializer);
bool Save(const Texture* obj, uint32_t count, Serializer& serializer); bool Save(const Texture* obj, uint32_t count, Serializer& serializer);
bool Load(Texture* obj, uint32_t count, Deserializer& serializer); bool Load(Texture* obj, uint32_t count, Deserializer& serializer);
namespace Meta {
struct TypeDef
{
uint32_t Size = 0;
uint32_t Hash = 0;
const char Name[64]{"Dummy"};
uint16_t ChildCount = 0;
uint16_t ChildIndices[64]{0};
};
struct EnumDef
{
uint32_t Size = 0;
uint32_t Hash = 0;
};
struct MetadataTable
{
TypeDef TypeDefinitions[14]
{
TypeDef{sizeof(int8_t), 0, "i8", 0, {}},
TypeDef{sizeof(int16_t), 1, "i16", 0, {}},
TypeDef{sizeof(int32_t), 2, "i32", 0, {}},
TypeDef{sizeof(int64_t), 3, "i64", 0, {}},
TypeDef{sizeof(uint8_t), 4, "u8", 0, {}},
TypeDef{sizeof(uint16_t), 5, "u16", 0, {}},
TypeDef{sizeof(uint32_t), 6, "u32", 0, {}},
TypeDef{sizeof(uint64_t), 7, "u64", 0, {}},
TypeDef{sizeof(bool), 8, "b", 0, {}},
TypeDef{sizeof(float), 9, "f32", 0, {}},
TypeDef{sizeof(double), 10, "f64", 0, {}},
TypeDef{sizeof(char), 11, "str", 0, {}},
TypeDef{sizeof(Test), 273256278, "Test", 1, {6}},
TypeDef{sizeof(Texture), 992460010, "Texture", 4, {6, 6, 11, 12}},
};
EnumDef EnumDefinitions[1]
{
EnumDef{sizeof(KnownType::Enum), 2983807453},
};
};
constexpr MetadataTable Metadata;
}
} }

View File

@@ -2,8 +2,8 @@
#include "Gen/Generated.h" #include "Gen/Generated.h"
#include "Logging.h" #include "Logging.h"
#include "MiniDef.h" #include "MiniDef.h"
#include "TypeDef.h" #include "TypeDef.h"
#include "bx/hash.h" #include "bx/hash.h"
#include "bx/string.h" #include "bx/string.h"
#include <bx/filepath.h> #include <bx/filepath.h>
@@ -114,6 +114,8 @@ Parser::Result Parser::Parse()
{ {
ReadPtr = &Buffer[0]; ReadPtr = &Buffer[0];
Parser::Result Res = Parser::OK; Parser::Result Res = Parser::OK;
CHECK(LoadNativeTypes());
while (Res == Parser::OK) while (Res == Parser::OK)
{ {
Res = SkipWhitespace(); Res = SkipWhitespace();
@@ -136,6 +138,7 @@ Parser::Result Parser::Parse()
Parser::Result Parser::HandleFileStart() Parser::Result Parser::HandleFileStart()
{ {
Result Res = OK; Result Res = OK;
if (CmpAdvance("type", Res, true) && Res == OK) if (CmpAdvance("type", Res, true) && Res == OK)
{ {
return HandleType(); return HandleType();
@@ -152,6 +155,20 @@ Parser::Result Parser::HandleFileStart()
return Error; return Error;
} }
Parser::Result Parser::LoadNativeTypes()
{
for (int32_t i = 0; i < Gen::KnownType::EntryCount; ++i)
{
auto& t = Definitions.Types[i];
t.Hash = i; // TODO!
bx::strCopy(t.Name, sizeof(t.Name), Gen::KnownType::EntryNames[i]);
bx::strCopy(t.NativeCName, sizeof(t.NativeCName), Gen::KnownType::CName[i]);
t.TypeFlags = Def::ETypeFlags::IsNative;
++Definitions.TypeCount;
}
return OK;
}
Parser::Result Parser::HandleType() Parser::Result Parser::HandleType()
{ {
Result Res = OK; Result Res = OK;
@@ -200,6 +217,13 @@ Parser::Result Parser::HandleType()
CHECK(ReadUint(t.FieldArraySizes[t.FieldCount])); CHECK(ReadUint(t.FieldArraySizes[t.FieldCount]));
CHECK(ExpectChar(")")); CHECK(ExpectChar(")"));
} }
else if (CmpAdvance("ArrDynamic", Res, true) && Res == Result::OK)
{
CHECK(ExpectChar("("));
CHECK(ReadUint(t.FieldArraySizes[t.FieldCount]));
t.FieldFlags[t.FieldCount] = Def::ETypeFieldFlags::DynamicArray;
CHECK(ExpectChar(")"));
}
else if (CmpAdvance("Default", Res, true) && Res == OK) else if (CmpAdvance("Default", Res, true) && Res == OK)
{ {
CHECK(ExpectChar("(")); CHECK(ExpectChar("("));
@@ -249,12 +273,15 @@ Parser::Result Parser::HandleEnum()
if (CmpAdvance("(", Res) && Res == OK) if (CmpAdvance("(", Res) && Res == OK)
{ {
CHECK(SkipWhitespace()); CHECK(SkipWhitespace());
Def::FieldType field; CHECK(ReadDefinedFieldType(e.EnumType));
CHECK(ReadNativeFieldType(field));
CHECK(SkipWhitespace()); CHECK(SkipWhitespace());
CHECK(ExpectChar(")")); CHECK(ExpectChar(")"));
CHECK(SkipWhitespace()); CHECK(SkipWhitespace());
} }
else
{
e.EnumType = {(uint16_t)Gen::KnownType::i32, Def::EFieldType::DefinedClass};
}
CHECK(ExpectChar("{")); CHECK(ExpectChar("{"));
CHECK(SkipWhitespace()); CHECK(SkipWhitespace());
@@ -338,29 +365,13 @@ Parser::Result Parser::ReadTypeToken()
{ {
Result Res = OK; Result Res = OK;
Def::Type& t = Definitions.Types[Definitions.TypeCount]; Def::Type& t = Definitions.Types[Definitions.TypeCount];
if (ReadNativeFieldType(t.FieldTypes[t.FieldCount]) == OK) return OK;
if (ReadDefinedFieldType(t.FieldTypes[t.FieldCount]) == OK) return OK; if (ReadDefinedFieldType(t.FieldTypes[t.FieldCount]) == OK) return OK;
LOG_ERROR(Line, "Unknown type token!"); LOG_ERROR(Line, "Unknown type token!");
ErrorLine(); ErrorLine();
return Error; return Error;
} }
Parser::Result Parser::ReadNativeFieldType(Def::FieldType& FieldT) Parser::Result Parser::ReadDefinedFieldType(Def::TypeRef& FieldT)
{
Result Res = OK;
for (int32_t i = 0; i < Gen::KnownType::EntryCount; ++i)
{
if (CmpAdvance(Gen::KnownType::EntryNames[i], Res, true) && Res == OK)
{
FieldT.FieldKind = Def::EFieldType::Native;
FieldT.Native = Gen::KnownType::Enum(i);
return OK;
}
}
return Error;
}
Parser::Result Parser::ReadDefinedFieldType(Def::FieldType& FieldT)
{ {
Result Res = OK; Result Res = OK;
for (uint16_t i = 0; i < Definitions.TypeCount; ++i) for (uint16_t i = 0; i < Definitions.TypeCount; ++i)
@@ -437,11 +448,7 @@ uint32_t Parser::CalculateTypeHash(const Def::Type& t)
hash.add(t.FieldArraySizes[i]); hash.add(t.FieldArraySizes[i]);
Def::EFieldType fieldType = t.FieldTypes[i].FieldKind; Def::EFieldType fieldType = t.FieldTypes[i].FieldKind;
if (fieldType == Def::EFieldType::Native) if (fieldType == Def::EFieldType::DefinedClass)
{
hash.add(t.FieldTypes[i].Native);
}
else if (fieldType == Def::EFieldType::DefinedClass)
{ {
Def::Type& dependType = Definitions.Types[t.FieldTypes[i].TypeIdx]; Def::Type& dependType = Definitions.Types[t.FieldTypes[i].TypeIdx];
if (dependType.Hash == 0) if (dependType.Hash == 0)
@@ -456,7 +463,7 @@ uint32_t Parser::CalculateTypeHash(const Def::Type& t)
} }
else else
{ {
LOG_ERROR(0, "TODO!"); LOG_ERROR(Line, "TODO!");
} }
} }
return hash.end(); return hash.end();
@@ -466,9 +473,14 @@ void Parser::CalculateHashes()
for (int32_t i = 0; i < Definitions.EnumCount; ++i) for (int32_t i = 0; i < Definitions.EnumCount; ++i)
{ {
Def::Enum& e = Definitions.Enums[i]; Def::Enum& e = Definitions.Enums[i];
if (!IsValid(e.EnumType))
{
LOG_ERROR(0, "Invalid enum type at idx %i", i);
continue;
}
bx::HashMurmur2A hash; bx::HashMurmur2A hash;
hash.begin(); hash.begin();
hash.add(e.EnumType.Native); hash.add(Definitions.Types[e.EnumType.TypeIdx].Hash); // TODO: add enum entries?
e.Hash = hash.end(); e.Hash = hash.end();
} }
for (int32_t i = 0; i < Definitions.TypeCount; ++i) for (int32_t i = 0; i < Definitions.TypeCount; ++i)
@@ -519,9 +531,5 @@ int main(int argc, const char** argv)
FileParser.CalculateHashes(); FileParser.CalculateHashes();
Writer.GenerateCpp(outPath, FileParser.Definitions); Writer.GenerateCpp(outPath, FileParser.Definitions);
LOG(0, "Writing type data file");
Writer.WriteTypeDataFile(outPath, FileParser.Definitions);
LOG(0, "Finished writing type data file!");
return 0; return 0;
} }

View File

@@ -86,12 +86,12 @@ class Parser
Result ExpectChar(bx::StringView expect); Result ExpectChar(bx::StringView expect);
Result Advance(int32_t Amount); Result Advance(int32_t Amount);
Result HandleFileStart(); Result HandleFileStart();
Result LoadNativeTypes();
Result HandleType(); Result HandleType();
Result HandleEnum(); Result HandleEnum();
Result ReadName(char* Target); Result ReadName(char* Target);
Result ReadUint(uint32_t& Out); Result ReadUint(uint32_t& Out);
Result ReadNativeFieldType(Def::FieldType& FieldT); Result ReadDefinedFieldType(Def::TypeRef& FieldT);
Result ReadDefinedFieldType(Def::FieldType& FieldT);
Result ReadTypeToken(); Result ReadTypeToken();
Result ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx); Result ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx);

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "Gen/Generated.h"
#include <cstdint> #include <cstdint>
namespace Def namespace Def
@@ -7,33 +6,52 @@ namespace Def
constexpr int32_t MaxNameLength = 64; constexpr int32_t MaxNameLength = 64;
constexpr int32_t MaxFields = 64; constexpr int32_t MaxFields = 64;
constexpr int32_t MaxExtraEnumFields = 2; constexpr int32_t MaxExtraEnumFields = 2;
enum class EFieldType
enum class EFieldType : uint8_t
{ {
Native,
DefinedClass, DefinedClass,
DefinedEnum DefinedEnum
}; };
struct FieldType
enum class ETypeFlags : uint32_t
{ {
EFieldType FieldKind = EFieldType::Native; None = 0,
Gen::KnownType::Enum Native = Gen::KnownType::Enum::i32; IsNative = 1 << 0,
uint16_t TypeIdx = UINT16_MAX;
}; };
enum class ETypeFieldFlags : uint32_t
{
None = 0,
DynamicArray = 1 << 0,
};
struct TypeRef
{
uint16_t TypeIdx = UINT16_MAX;
EFieldType FieldKind = EFieldType::DefinedClass;
};
inline bool IsValid(TypeRef ref)
{
return ref.TypeIdx != UINT16_MAX;
}
struct Type struct Type
{ {
int32_t FieldCount = 0; int32_t FieldCount = 0;
FieldType FieldTypes[MaxFields]; TypeRef FieldTypes[MaxFields];
char FieldNames[MaxFields][MaxNameLength]; char FieldNames[MaxFields][MaxNameLength];
uint32_t FieldArraySizes[MaxFields]{0}; uint32_t FieldArraySizes[MaxFields]{0};
char FieldValues[MaxFields][128]{0}; char FieldValues[MaxFields][128]{0};
ETypeFlags TypeFlags = ETypeFlags::None;
ETypeFieldFlags FieldFlags[MaxFields]{ETypeFieldFlags::None};
char Name[MaxNameLength]{0}; char Name[MaxNameLength]{0};
char NativeCName[MaxNameLength]{0};
uint32_t Hash = 0; uint32_t Hash = 0;
}; };
struct Enum struct Enum
{ {
FieldType EnumType; TypeRef EnumType;
int32_t EntryCount = 0; int32_t EntryCount = 0;
char EntryNames[MaxFields][MaxNameLength]; char EntryNames[MaxFields][MaxNameLength];
int32_t ExtraStringFieldCount = 0; int32_t ExtraStringFieldCount = 0;