minidef refactor

This commit is contained in:
Asuro
2025-03-10 15:16:48 +01:00
parent e2b94b826d
commit ff00119e5b
7 changed files with 306 additions and 255 deletions

View File

@@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 3.10)
project(MiniDefProj)
add_executable(minidef "${CMAKE_CURRENT_SOURCE_DIR}/src/MiniDef.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/Logging.cpp")
file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
file(GLOB sources "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
add_executable(minidef ${headers} ${sources})
target_include_directories(minidef PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../bgfx.cmake/bx/include/"
"${CMAKE_CURRENT_SOURCE_DIR}/../bgfx.cmake/bx/include/compat/msvc/"

View File

@@ -0,0 +1,206 @@
#include "CppGen.h"
#include "Logging.h"
#include "TypeDef.h"
#include <bx/file.h>
#include <memoryapi.h>
#include <winnt.h>
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
namespace WriteTemplates
{
constexpr char FileHeader[] =
R"END(#pragma once
#include "Def.h"
namespace Generated
{
)END";
constexpr char StructHeader1[] =
R"END( struct %s
{
)END";
constexpr char StructField4[] =
R"END( %s %s%s = %s;
)END";
constexpr char StructEnd[] =
R"END( };
)END";
constexpr char EnumHeader3[] =
R"END( struct %s
{
static constexpr int32_t EntryCount = %u;
enum class Enum : %s
{
)END";
constexpr char EnumField1[] =
R"END( %s,
)END";
constexpr char EnumNamesStart2[] =
R"END( };
static constexpr char %s[EntryCount][%u]
{
)END";
constexpr char EnumNamesEntry1[] =
R"END( "%s",
)END";
constexpr char EnumNamesEnd[] =
R"END( };
};
)END";
constexpr char FileEnd[] =
R"END(}
)END";
} // namespace WriteTemplates
void CppFileWriter::PrintTypeName(char* buf,
int32_t bufSize,
const Def::FieldType& type,
const Def::DefinitionFile& definitions)
{
if (type.FieldKind == Def::EFieldType::Native)
{
if (int32_t(type.Native) < Generated::KnownType::EntryCount)
{
bx::strCopy(buf, bufSize, Generated::KnownType::CName[size_t(type.Native)]);
}
else
{
LOG_ERROR(0, "Unknown native type index: %u", type.Native);
}
}
else if (type.FieldKind == Def::EFieldType::DefinedClass)
{
bx::strCopy(buf, bufSize, definitions.Types[type.TypeIdx].Name);
}
else if (type.FieldKind == Def::EFieldType::DefinedEnum)
{
bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name);
}
}
void CppFileWriter::WriteEnums(const Def::DefinitionFile& definitions)
{
for (int32_t enumIdx = 0; enumIdx < definitions.EnumCount; ++enumIdx)
{
const Def::Enum& e = definitions.Enums[enumIdx];
Write(
WriteTemplates::EnumHeader3, e.Name, e.EntryCount, Generated::KnownType::CName[(int32_t)e.EnumType.Native]);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]);
}
Write(WriteTemplates::EnumNamesStart2, "EntryNames", Def::MaxNameLength);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Write(WriteTemplates::EnumNamesEntry1, e.EntryNames[entryIdx]);
}
for (int32_t extraIdx = 0; extraIdx < e.ExtraStringFieldCount; ++extraIdx)
{
Write(WriteTemplates::EnumNamesStart2, e.ExtraStringFieldNames[extraIdx], Def::MaxNameLength);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Write(WriteTemplates::EnumNamesEntry1, e.ExtraStringFields[entryIdx][extraIdx]);
}
}
Write(WriteTemplates::EnumNamesEnd);
}
}
void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
{
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)
{
const Def::Type& t = definitions.Types[typeIdx];
Write(WriteTemplates::StructHeader1, t.Name);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{
char Type[64]{0};
PrintTypeName(Type, sizeof(Type), t.FieldTypes[fieldIdx], definitions);
char Array[32]{0};
uint32_t ArraySize = t.FieldArraySizes[fieldIdx];
if (ArraySize > 0)
{
bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize);
}
Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldVaules[fieldIdx]);
}
Write(WriteTemplates::StructEnd);
}
}
void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions)
{
LOG(0, "Generating...");
// Allocate write buffer
if (FileWriteBuffer != nullptr)
{
LOG_ERROR(0, "Multiple writes not supported yet!");
return;
}
FileWriteBuffer =
reinterpret_cast<char*>(VirtualAlloc(nullptr, BufferRequestSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
if (FileWriteBuffer == nullptr)
{
LOG_ERROR(0, "Failed to allocate write memory!");
return;
}
FileWriterWritten = 0;
// Write text to buffer
Write(WriteTemplates::FileHeader);
WriteEnums(definitions);
WriteTypes(definitions);
Write(WriteTemplates::FileEnd);
// Write buffer to disk
bx::Error error;
bx::FileWriter writer;
bx::FilePath writePath = outDir;
// std::filesystem::create_directory(outDir.getCPtr());
writePath.join("Generated.h");
LOG(0, "Writing to %s", writePath.getCPtr());
if (!writer.open(writePath, false, &error))
{
LOG_ERROR(0, "Failed to open output file: %s", error.getMessage().getCPtr());
return;
}
writer.write(FileWriteBuffer, FileWriterWritten, &error);
if (!error.isOk())
{
LOG_ERROR(0, "Failed to write to output file: %s", error.getMessage().getCPtr());
}
writer.close();
LOG(0, "Finished writing!");
}
void CppFileWriter::Write(const char* Template, ...)
{
if (FileWriteBuffer == nullptr)
{
LOG_ERROR(0, "Wrote too early!");
return;
}
va_list ArgList;
va_start(ArgList, Template);
FileWriterWritten += bx::vsnprintf(&FileWriteBuffer[FileWriterWritten], BufferRequestSize, Template, ArgList);
va_end(ArgList);
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include "TypeDef.h"
#include "bx/filepath.h"
struct CppFileWriter
{
private:
static constexpr size_t BufferRequestSize = 1024 * 1024 * 1024;
char* FileWriteBuffer = nullptr;
uint64_t FileWriterWritten = 0;
public:
void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, const Def::DefinitionFile& definitions);
void WriteEnums(const Def::DefinitionFile& definitions);
void WriteTypes(const Def::DefinitionFile& definitions);
void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions);
void Write(const char* Template, ...);
};

View File

@@ -3,17 +3,6 @@
namespace Generated
{
struct Test
{
uint32_t Number = {};
};
struct Texture
{
uint32_t Width = {};
uint32_t Height = {};
char StrTest[3] = {};
Test T = {};
};
struct KnownType
{
static constexpr int32_t EntryCount = 12;
@@ -63,4 +52,15 @@ namespace Generated
"char",
};
};
struct Test
{
uint32_t Number = {};
};
struct Texture
{
uint32_t Width = {};
uint32_t Height = {};
char StrTest[3] = {};
Test T = {};
};
}

View File

@@ -1,3 +1,4 @@
#include "CppGen.h"
#include "Gen/Generated.h"
#include "Logging.h"
#include "MiniDef.h"
@@ -5,159 +6,6 @@
#include "bx/string.h"
#include <bx/filepath.h>
#include <ctype.h>
#include <filesystem>
namespace WriteTemplates
{
constexpr char FileHeader[] =
R"END(#pragma once
#include "Def.h"
namespace Generated
{
)END";
constexpr char StructHeader1[] =
R"END( struct %s
{
)END";
constexpr char StructField4[] =
R"END( %s %s%s = %s;
)END";
constexpr char StructEnd[] =
R"END( };
)END";
constexpr char EnumHeader3[] =
R"END( struct %s
{
static constexpr int32_t EntryCount = %u;
enum class Enum : %s
{
)END";
constexpr char EnumField1[] =
R"END( %s,
)END";
constexpr char EnumNamesStart2[] =
R"END( };
static constexpr char %s[EntryCount][%u]
{
)END";
constexpr char EnumNamesEntry1[] =
R"END( "%s",
)END";
constexpr char EnumNamesEnd[] =
R"END( };
};
)END";
constexpr char FileEnd[] =
R"END(}
)END";
} // namespace WriteTemplates
void DefinitionFile::PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type)
{
if (type.FieldKind == Def::EFieldType::Native)
{
if (int32_t(type.Native) < Generated::KnownType::EntryCount)
{
bx::strCopy(buf, bufSize, Generated::KnownType::CName[size_t(type.Native)]);
}
else
{
LOG_ERROR(0, "Unknown native type index: %u", type.Native);
}
}
else if (type.FieldKind == Def::EFieldType::DefinedClass)
{
bx::strCopy(buf, bufSize, Types[type.TypeIdx].Name);
}
else if (type.FieldKind == Def::EFieldType::DefinedEnum)
{
bx::strCopy(buf, bufSize, Enums[type.TypeIdx].Name);
}
}
void DefinitionFile::WriteEnums(TemplateWriter& Template)
{
for (int32_t enumIdx = 0; enumIdx < EnumCount; ++enumIdx)
{
Def::Enum& e = Enums[enumIdx];
Template.Write(
WriteTemplates::EnumHeader3, e.Name, e.EntryCount, Generated::KnownType::CName[(int32_t)e.EnumType.Native]);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Template.Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]);
}
Template.Write(WriteTemplates::EnumNamesStart2, "EntryNames", Def::MaxNameLength);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Template.Write(WriteTemplates::EnumNamesEntry1, e.EntryNames[entryIdx]);
}
for (int32_t extraIdx = 0; extraIdx < e.ExtraStringFieldCount; ++extraIdx)
{
Template.Write(WriteTemplates::EnumNamesStart2, e.ExtraStringFieldNames[extraIdx], Def::MaxNameLength);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Template.Write(WriteTemplates::EnumNamesEntry1, e.ExtraStringFields[entryIdx][extraIdx]);
}
}
Template.Write(WriteTemplates::EnumNamesEnd);
}
}
void DefinitionFile::WriteTypes(TemplateWriter& Template)
{
for (int32_t typeIdx = 0; typeIdx < TypeCount; ++typeIdx)
{
Def::Type& t = Types[typeIdx];
Template.Write(WriteTemplates::StructHeader1, t.Name);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{
char Type[64]{0};
PrintTypeName(Type, sizeof(Type), t.FieldTypes[fieldIdx]);
char Array[32]{0};
uint32_t ArraySize = t.FieldArraySizes[fieldIdx];
if (ArraySize > 0)
{
bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize);
}
Template.Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldVaules[fieldIdx]);
}
Template.Write(WriteTemplates::StructEnd);
}
}
void DefinitionFile::GenerateCpp(const bx::FilePath& outDir)
{
LOG(0, "Generating...");
bx::Error error;
bx::FileWriter writer;
bx::FilePath writePath = outDir;
std::filesystem::create_directory(outDir.getCPtr());
writePath.join("Generated.h");
writer.open(writePath, false, &error);
TemplateWriter Template{writer, error};
Template.Write(WriteTemplates::FileHeader);
WriteEnums(Template);
WriteTypes(Template);
Template.Write(WriteTemplates::FileEnd);
writer.close();
}
bool Parser::CmpAdvance(bx::StringView expect, Result& Res, bool RequireGap)
{
@@ -308,7 +156,7 @@ Parser::Result Parser::HandleType()
if (!Stack.Push(TokenType::TypeKeyword)) return Error;
CHECK(SkipWhitespace());
if (Definitions.TypeCount >= DefinitionFile::MaxTypes)
if (Definitions.TypeCount >= Def::DefinitionFile::MaxTypes)
{
LOG_ERROR(Line, "Too many types!");
ErrorLine();
@@ -386,7 +234,7 @@ Parser::Result Parser::HandleEnum()
if (!Stack.Push(TokenType::EnumKeyword)) return Error;
CHECK(SkipWhitespace());
if (Definitions.EnumCount >= DefinitionFile::MaxTypes)
if (Definitions.EnumCount >= Def::DefinitionFile::MaxTypes)
{
LOG_ERROR(Line, "Too many enums!");
ErrorLine();
@@ -578,21 +426,10 @@ int32_t Parser::GetRemaining()
return &Buffer[BufferSize] - ReadPtr;
}
char WriteBuffer[1024 * 1024]{0};
void TemplateWriter::Write(const char* Template, ...)
{
va_list ArgList;
va_start(ArgList, Template);
int32_t Count = bx::vsnprintf(WriteBuffer, sizeof(WriteBuffer), Template, ArgList);
va_end(ArgList);
bx::write(&Writer, WriteBuffer, Count, &Error);
}
Parser TestParser;
Parser FileParser;
CppFileWriter Writer;
int main(int argc, const char** argv)
{
LOG(0, "Hello");
if (argc != 3)
{
LOG(0, "invalid number of arguments!");
@@ -609,8 +446,9 @@ int main(int argc, const char** argv)
return 1;
}
TestParser.BufferSize = bx::read(&reader, TestParser.Buffer, Parser::MaxBufferSize, &error);
Parser::Result Res = TestParser.Parse();
LOG(0, "Reading from %s", defPath.getCPtr());
FileParser.BufferSize = bx::read(&reader, FileParser.Buffer, Parser::MaxBufferSize, &error);
Parser::Result Res = FileParser.Parse();
if (Res == Parser::OK)
{
@@ -622,7 +460,7 @@ int main(int argc, const char** argv)
return 1;
}
LOG(0, "Finished parsing!");
TestParser.Definitions.GenerateCpp(outPath);
Writer.GenerateCpp(outPath, FileParser.Definitions);
return 0;
}

View File

@@ -1,12 +1,11 @@
#pragma once
#include "bx/string.h"
#include <bx/file.h>
#include <cctype>
#include <cstdint>
#include <string>
#include "Gen/Generated.h"
#include "Logging.h"
#include "bx/string.h"
#include "TypeDef.h"
enum class TokenType : uint8_t
{
@@ -50,74 +49,6 @@ struct ParseStack
}
};
class TemplateWriter
{
private:
bx::WriterI& Writer;
bx::Error& Error;
public:
TemplateWriter(bx::WriterI& W, bx::Error& E) : Writer(W), Error(E)
{
}
void Write(const char* Template, ...);
};
namespace Def
{
constexpr int32_t MaxNameLength = 64;
constexpr int32_t MaxFields = 64;
constexpr int32_t MaxExtraEnumFields = 1;
enum class EFieldType
{
Native,
DefinedClass,
DefinedEnum
};
struct FieldType
{
EFieldType FieldKind = EFieldType::Native;
Generated::KnownType::Enum Native = Generated::KnownType::Enum::i32;
uint16_t TypeIdx = UINT16_MAX;
};
struct Type
{
int32_t FieldCount = 0;
FieldType FieldTypes[MaxFields];
char FieldNames[MaxFields][MaxNameLength];
uint32_t FieldArraySizes[MaxFields]{0};
char FieldVaules[MaxFields][128]{0};
char Name[MaxNameLength]{0};
};
struct Enum
{
FieldType EnumType;
int32_t EntryCount = 0;
char EntryNames[MaxFields][MaxNameLength];
int32_t ExtraStringFieldCount = 0;
char ExtraStringFieldNames[MaxExtraEnumFields][MaxNameLength];
char ExtraStringFields[MaxFields][MaxExtraEnumFields][MaxNameLength];
char Name[MaxNameLength]{0};
};
} // namespace Def
struct DefinitionFile
{
static constexpr int32_t MaxTypes = 256;
void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type);
void WriteEnums(TemplateWriter& Template);
void WriteTypes(TemplateWriter& Template);
void GenerateCpp(const bx::FilePath& outDir);
Def::Type Types[MaxTypes];
uint16_t TypeCount = 0;
Def::Enum Enums[MaxTypes];
int32_t EnumCount = 0;
};
class Parser
{
public:
@@ -140,7 +71,7 @@ class Parser
char* ReadPtr = &Buffer[0];
uint32_t Line = 0;
DefinitionFile Definitions;
Def::DefinitionFile Definitions;
ParseStack Stack;
public:

View File

@@ -0,0 +1,52 @@
#pragma once
#include "Gen/Generated.h"
#include <cstdint>
namespace Def
{
constexpr int32_t MaxNameLength = 64;
constexpr int32_t MaxFields = 64;
constexpr int32_t MaxExtraEnumFields = 1;
enum class EFieldType
{
Native,
DefinedClass,
DefinedEnum
};
struct FieldType
{
EFieldType FieldKind = EFieldType::Native;
Generated::KnownType::Enum Native = Generated::KnownType::Enum::i32;
uint16_t TypeIdx = UINT16_MAX;
};
struct Type
{
int32_t FieldCount = 0;
FieldType FieldTypes[MaxFields];
char FieldNames[MaxFields][MaxNameLength];
uint32_t FieldArraySizes[MaxFields]{0};
char FieldVaules[MaxFields][128]{0};
char Name[MaxNameLength]{0};
};
struct Enum
{
FieldType EnumType;
int32_t EntryCount = 0;
char EntryNames[MaxFields][MaxNameLength];
int32_t ExtraStringFieldCount = 0;
char ExtraStringFieldNames[MaxExtraEnumFields][MaxNameLength];
char ExtraStringFields[MaxFields][MaxExtraEnumFields][MaxNameLength];
char Name[MaxNameLength]{0};
};
struct DefinitionFile
{
static constexpr int32_t MaxTypes = 256;
Def::Type Types[MaxTypes];
uint16_t TypeCount = 0;
Def::Enum Enums[MaxTypes];
int32_t EnumCount = 0;
};
} // namespace Def