|
|
|
@@ -0,0 +1,204 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
using Cpp2Beef;
|
|
|
|
|
using LibClang;
|
|
|
|
|
|
|
|
|
|
namespace TinyglTF.Setup;
|
|
|
|
|
|
|
|
|
|
class TinyglTFGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
|
|
|
|
|
{
|
|
|
|
|
protected override Span<char8*> Args => args;
|
|
|
|
|
protected override Flags Flags => .None;
|
|
|
|
|
|
|
|
|
|
// You can have your binding in one file or in multiple, file management is up to you
|
|
|
|
|
StreamWriter writer = new .()..Create("../src/TinyglTF_v3.bf")..Write("""
|
|
|
|
|
// This file was generated by Cpp2Beef
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Interop;
|
|
|
|
|
|
|
|
|
|
namespace TinyglTF;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""") ~ delete _;
|
|
|
|
|
|
|
|
|
|
protected override StreamWriter GetWriterForHeader(StringView header)
|
|
|
|
|
{
|
|
|
|
|
if (header.EndsWith("tiny_gltf_v3.h"))
|
|
|
|
|
return writer;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override Block GetCursorBlock(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
if (cursor.kind == .FunctionDecl)
|
|
|
|
|
return .CustomBlock("TinyglTF");
|
|
|
|
|
if (cursor.kind == .MacroDefinition && GetMacroEnum(GetCursorSpelling!(cursor)) != -1)
|
|
|
|
|
return .NoBlock;
|
|
|
|
|
return base.GetCursorBlock(cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void Record(CXCursor cursor, bool attributes = true)
|
|
|
|
|
{
|
|
|
|
|
base.Record(cursor, attributes);
|
|
|
|
|
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
bool isStr = spelling == "tg3_str";
|
|
|
|
|
if (isStr || spelling.StartsWith("tg3_span_"))
|
|
|
|
|
{
|
|
|
|
|
str.Append("\n", cursorIndent, "public static operator ");
|
|
|
|
|
if (isStr)
|
|
|
|
|
str.Append("StringView");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
str.Append("Span<");
|
|
|
|
|
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
|
|
|
|
|
{
|
|
|
|
|
Self self = (.)Internal.UnsafeCastToObject(client_data);
|
|
|
|
|
self.Type(Clang.GetPointeeType(Clang.GetCursorType(cursor)));
|
|
|
|
|
return .Break;
|
|
|
|
|
}, Internal.UnsafeCastToPtr(this));
|
|
|
|
|
str.Append('>');
|
|
|
|
|
}
|
|
|
|
|
str.Append("(Self self) => .(self.data, (.)self.", isStr ? "len" : "count", ");");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const String[?] macroEnumNames = .("tg3_PrimitiveMode", "tg3_ComponentType", "tg3_AccessorType", "tg3_TextureFilter", "tg3_TextureWrapMode",
|
|
|
|
|
"tg3_ImageFormat", "tg3_TextureFormat", "tg3_BufferTarget", "tg3_SectionCheckFlags");
|
|
|
|
|
const String[?] macroEnumPrefixes = .("mode", "component_type", "type", "texture_filter", "texture_wrap", "image_format", "texture_format", "target", "required_sections");
|
|
|
|
|
StringView currentMacroEnum = null;
|
|
|
|
|
|
|
|
|
|
static int GetMacroEnum(StringView spelling)
|
|
|
|
|
{
|
|
|
|
|
if (!spelling.StartsWith("TG3_"))
|
|
|
|
|
return -1;
|
|
|
|
|
if (spelling == "TG3_NO_REQUIRE" || spelling.StartsWith("TG3_REQUIRE_"))
|
|
|
|
|
return macroEnumPrefixes.Count-1;
|
|
|
|
|
var spelling;
|
|
|
|
|
spelling.RemoveFromStart(4);
|
|
|
|
|
for (let prefix in macroEnumPrefixes)
|
|
|
|
|
if (spelling.StartsWith(prefix, .OrdinalIgnoreCase) && spelling[prefix.Length] == '_')
|
|
|
|
|
return @prefix;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void MacroDefinition(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
int idx = GetMacroEnum(spelling);
|
|
|
|
|
if (idx == -1)
|
|
|
|
|
{
|
|
|
|
|
if (!currentMacroEnum.IsNull)
|
|
|
|
|
{
|
|
|
|
|
str.Insert(0, "\n}");
|
|
|
|
|
currentMacroEnum = null;
|
|
|
|
|
}
|
|
|
|
|
base.MacroDefinition(cursor);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentMacroEnum != macroEnumNames[idx])
|
|
|
|
|
{
|
|
|
|
|
if (!currentMacroEnum.IsNull) str.Insert(0, "\n}");
|
|
|
|
|
str.Append("[CRepr] enum ", macroEnumNames[idx], "\n{\n");
|
|
|
|
|
currentMacroEnum = macroEnumNames[idx];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int prefixLen = macroEnumPrefixes[idx].Length + 5;
|
|
|
|
|
if (idx == macroEnumPrefixes.Count-1)
|
|
|
|
|
prefixLen = 4;
|
|
|
|
|
|
|
|
|
|
str.Append('\t');
|
|
|
|
|
UpperSnakeCase2PascalCase(spelling[prefixLen...], str);
|
|
|
|
|
str.Append(" = ");
|
|
|
|
|
WriteTokens(ScopeTokenize!(cursor, unit)[1...], Clang.GetNullLocation(), .Punctuation);
|
|
|
|
|
str.Append(',');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void Type(CXType type, TypeParamMode paramMode = .None)
|
|
|
|
|
{
|
|
|
|
|
if (currentCursor.kind == .FieldDecl && GetTypeSpelling!(type) == "int32_t")
|
|
|
|
|
{
|
|
|
|
|
let spelling = GetCursorSpelling!(currentCursor);
|
|
|
|
|
if (spelling.StartsWith("wrap_"))
|
|
|
|
|
{
|
|
|
|
|
str.Append("tg3_TextureWrapMode");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for (let prefix in macroEnumPrefixes)
|
|
|
|
|
if (prefix == spelling)
|
|
|
|
|
{
|
|
|
|
|
str.Append(macroEnumNames[@prefix]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
base.Type(type, paramMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void Enum(CXCursor cursor)
|
|
|
|
|
{
|
|
|
|
|
if (!currentMacroEnum.IsNull)
|
|
|
|
|
{
|
|
|
|
|
str.Insert(0, "\n}");
|
|
|
|
|
currentMacroEnum = null;
|
|
|
|
|
}
|
|
|
|
|
base.Enum(cursor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void GetNameInBindings(CXCursor cursor, String outString)
|
|
|
|
|
{
|
|
|
|
|
switch (cursor.kind)
|
|
|
|
|
{
|
|
|
|
|
case .EnumConstantDecl:
|
|
|
|
|
StringView parent = GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor));
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
int index = parent[4...].IndexOf('_');
|
|
|
|
|
if (index >= 0) parent = parent[...(index + 4)];
|
|
|
|
|
if (spelling.StartsWith(parent, .OrdinalIgnoreCase))
|
|
|
|
|
spelling.RemoveFromStart(parent.Length);
|
|
|
|
|
else if (spelling.StartsWith("TG3_"))
|
|
|
|
|
spelling.RemoveFromStart(4);
|
|
|
|
|
if (spelling.StartsWith('_'))
|
|
|
|
|
spelling.RemoveFromStart(1);
|
|
|
|
|
UpperSnakeCase2PascalCase(spelling, outString);
|
|
|
|
|
return;
|
|
|
|
|
case .EnumDecl, .StructDecl, .UnionDecl, .TypedefDecl:
|
|
|
|
|
if (!GetCursorSpelling!(cursor).StartsWith("tg3_"))
|
|
|
|
|
break;
|
|
|
|
|
outString.Append("tg3_");
|
|
|
|
|
fallthrough;
|
|
|
|
|
case .FunctionDecl:
|
|
|
|
|
StringView spelling = GetCursorSpelling!(cursor);
|
|
|
|
|
Runtime.Assert(spelling.StartsWith("tg3_"));
|
|
|
|
|
spelling.RemoveFromStart(4);
|
|
|
|
|
UpperSnakeCase2PascalCase(spelling, outString);
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
}
|
|
|
|
|
base.GetNameInBindings(cursor, outString);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Program
|
|
|
|
|
{
|
|
|
|
|
[CLink] static extern int32 system(char8*);
|
|
|
|
|
|
|
|
|
|
public static int Main(String[] args)
|
|
|
|
|
{
|
|
|
|
|
void Download(String file)
|
|
|
|
|
{
|
|
|
|
|
if (system(scope $"wget -O ../src/{file} https://raw.githubusercontent.com/syoyo/tinygltf/refs/heads/release/{file}") != 0)
|
|
|
|
|
Runtime.FatalError(scope $"Failed to download {file}");
|
|
|
|
|
}
|
|
|
|
|
Download("tiny_gltf_v3.h");
|
|
|
|
|
Download("tiny_gltf_v3.c");
|
|
|
|
|
Download("tinygltf_json_c.h");
|
|
|
|
|
|
|
|
|
|
scope TinyglTFGenerator(char8*[?]("--language=c")).Generate("../src/tiny_gltf_v3.h");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|