base layer defined type info tables experiment - can ideally be used as a more whole solution for the ctrl meta eval info stuff

This commit is contained in:
Ryan Fleury
2024-09-17 17:52:23 -07:00
parent 85a07be1ac
commit 9ae3b2eb92
9 changed files with 551 additions and 21 deletions
+1
View File
@@ -15,5 +15,6 @@
#include "base_thread_context.c"
#include "base_command_line.c"
#include "base_markup.c"
#include "base_meta.c"
#include "base_log.c"
#include "base_entry_point.c"
+1
View File
@@ -17,6 +17,7 @@
#include "base_thread_context.h"
#include "base_command_line.h"
#include "base_markup.h"
#include "base_meta.h"
#include "base_log.h"
#include "base_entry_point.h"
+188
View File
@@ -0,0 +1,188 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Type Info Lookups
internal Member *
member_from_name(Type *type, String8 name)
{
Member *member = &member_nil;
if(type->members != 0)
{
for(U64 idx = 0; idx < type->count; idx += 1)
{
if(str8_match(type->members[idx].name, name, 0))
{
member = &type->members[idx];
break;
}
}
}
return member;
}
////////////////////////////////
//~ rjf: Type Info * Instance Operations
internal String8
serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializeParams *params)
{
Temp scratch = scratch_begin(&arena, 1);
String8List strings = {0};
str8_serial_begin(scratch.arena, &strings);
{
typedef struct Task Task;
struct Task
{
Task *next;
Type *type;
void *ptr;
U64 count;
Type *containing_type;
void *containing_ptr;
};
Task start_task = {0, type, ptr, 1};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
{
switch(t->type->kind)
{
//- rjf: leaf serialiation -> just write the data directly
default:
if(TypeKind_FirstLeaf <= t->type->kind && t->type->kind <= TypeKind_LastLeaf)
{
str8_serial_push_string(scratch.arena, &strings, str8((U8 *)t->ptr, type_leaves[t->type->kind].size*t->count));
}break;
//- rjf: pointers -> try to interpret/understand pointer & write, otherwise skip
case TypeKind_Ptr:
{
// rjf: gather info about pointer references of this type
TypeSerializePtrRefInfo *ptr_ref_info = 0;
for(U64 idx = 0; idx < params->ptr_ref_infos_count; idx += 1)
{
if(params->ptr_ref_infos[idx].type == t->type->direct)
{
ptr_ref_info = &params->ptr_ref_infos[idx];
break;
}
}
// rjf: read ptr value
void *ptr_value = 0;
MemoryCopy(&ptr_value, t->ptr, sizeof(ptr_value));
// rjf: indexification -> subtract base, divide direct size, write index
if(ptr_ref_info != 0 && ptr_ref_info->indexify_base != 0)
{
U64 ptr_offsetified = (U8 *)ptr_value - (U8 *)ptr_ref_info->indexify_base;
U64 ptr_indexified = ptr_offsetified / t->type->direct->size;
str8_serial_push_struct(scratch.arena, &strings, &ptr_indexified);
}
// rjf: explicit identification -> descend to ID member at destination, write that
else if(ptr_ref_info != 0 && ptr_ref_info->id_member.size != 0)
{
Member *member = member_from_name(t->type->direct, ptr_ref_info->id_member);
if(member != &member_nil)
{
Task *task = push_array(scratch.arena, Task, 1);
task->type = member->type;
task->ptr = ((U8 *)ptr_value) + member->value;
task->count = 1;
task->containing_type = t->type->direct;
task->containing_ptr = ptr_value;
SLLQueuePush(first_task, last_task, task);
}
}
// rjf: count-delimited pointers -> read count from member in containing type,
// descend & write destination that way
else if(t->type->count_delimiter_name.size != 0 && t->containing_type != 0)
{
Member *count_member = member_from_name(t->containing_type, t->type->count_delimiter_name);
if(count_member != &member_nil)
{
U64 count = 0;
MemoryCopy(&count, (U8 *)t->containing_ptr + count_member->value, count_member->type->size);
Task *task = push_array(scratch.arena, Task, 1);
task->type = t->type->direct;
task->ptr = ptr_value;
task->count = count;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}
}
// rjf: any other nonzero pointer -> descend to pointer destination. trust usage code
else if(ptr_value != 0)
{
Task *task = push_array(scratch.arena, Task, 1);
task->type = t->type->direct;
task->ptr = ptr_value;
task->count = 1;
SLLQueuePush(first_task, last_task, task);
}
}break;
//- rjf: arrays -> descend to underlying type, + count
case TypeKind_Array:
{
Task *task = push_array(scratch.arena, Task, 1);
task->type = t->type->direct;
task->ptr = t->ptr;
task->count = t->type->count;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
//- rjf: struct -> descend to members
case TypeKind_Struct:
{
for(U64 idx = 0; idx < t->count; idx += 1)
{
for(U64 member_idx = 0; member_idx < t->type->count; member_idx += 1)
{
if(t->type->members[member_idx].flags & MemberFlag_DoNotSerialize)
{
continue;
}
Task *task = push_array(scratch.arena, Task, 1);
task->type = t->type->members[member_idx].type;
task->ptr = (U8 *)t->ptr + t->type->size*idx + t->type->members[member_idx].value;
task->count = 1;
task->containing_type = t->type;
task->containing_ptr = t->ptr;
SLLQueuePush(first_task, last_task, task);
}
}
}break;
//- rjf: enum -> descend to basic type interpretation
case TypeKind_Enum:
{
Task *task = push_array(scratch.arena, Task, 1);
task->type = t->type->direct;
task->ptr = t->ptr;
task->count = t->count;
task->containing_type = t->containing_type;
task->containing_ptr = t->containing_ptr;
SLLQueuePush(first_task, last_task, task);
}break;
}
}
}
String8 result = str8_serial_end(scratch.arena, &strings);
scratch_end(scratch);
return result;
}
internal void *
data_from_typed_serialized(Arena *arena, Type *type, String8 string, TypeSerializeParams *params)
{
}
+191
View File
@@ -0,0 +1,191 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_META_H
#define BASE_META_H
////////////////////////////////
//~ rjf: Meta Markup Features
#define EmbedFile(name, path)
#define TweakB32(name, default) (TWEAK_##name)
#define TweakF32(name, default, min, max) (TWEAK_##name)
////////////////////////////////
//~ rjf: Tweak Info Tables
typedef struct TweakB32Info TweakB32Info;
struct TweakB32Info
{
String8 name;
B32 default_value;
B32 *value_ptr;
};
typedef struct TweakF32Info TweakF32Info;
struct TweakF32Info
{
String8 name;
F32 default_value;
Rng1F32 value_range;
F32 *value_ptr;
};
typedef struct TweakB32InfoTable TweakB32InfoTable;
struct TweakB32InfoTable
{
TweakB32Info *v;
U64 count;
};
typedef struct TweakF32InfoTable TweakF32InfoTable;
struct TweakF32InfoTable
{
TweakF32Info *v;
U64 count;
};
typedef struct EmbedInfo EmbedInfo;
struct EmbedInfo
{
String8 name;
String8 *data;
U128 *hash;
};
typedef struct EmbedInfoTable EmbedInfoTable;
struct EmbedInfoTable
{
EmbedInfo *v;
U64 count;
};
////////////////////////////////
//~ rjf: Type Info Types
typedef U32 TypeFlags;
enum
{
TypeFlag_Indexified = (1<<0),
};
typedef enum TypeKind
{
TypeKind_Null,
// rjf: leaves
TypeKind_Void, TypeKind_FirstLeaf = TypeKind_Void,
TypeKind_U8,
TypeKind_U16,
TypeKind_U32,
TypeKind_U64,
TypeKind_S8,
TypeKind_S16,
TypeKind_S32,
TypeKind_S64,
TypeKind_B8,
TypeKind_B16,
TypeKind_B32,
TypeKind_B64,
TypeKind_F32,
TypeKind_F64, TypeKind_LastLeaf = TypeKind_F64,
// rjf: operators
TypeKind_Ptr,
TypeKind_Array,
// rjf: user-defined-types
TypeKind_Struct,
TypeKind_Union,
TypeKind_Enum,
TypeKind_COUNT
}
TypeKind;
typedef U32 MemberFlags;
enum
{
MemberFlag_DoNotSerialize = (1<<0),
};
typedef struct Type Type;
typedef struct Member Member;
struct Member
{
String8 name;
Type *type;
U64 value;
MemberFlags flags;
};
typedef struct Type Type;
struct Type
{
TypeKind kind;
TypeFlags flags;
U64 size;
Type *direct;
String8 name;
String8 count_delimiter_name; // gathered from surrounding members, turns *->[1] into *->[N]
U64 count;
Member *members;
};
////////////////////////////////
//~ rjf: Type Serialization Parameters
typedef struct TypeSerializePtrRefInfo TypeSerializePtrRefInfo;
struct TypeSerializePtrRefInfo
{
Type *type; // pointers to this
void *indexify_base; // can be indexified using this
String8 id_member; // or ID'd via this member of the pointed-to-instance
};
typedef struct TypeSerializeParams TypeSerializeParams;
struct TypeSerializeParams
{
TypeSerializePtrRefInfo *ptr_ref_infos;
U64 ptr_ref_infos_count;
};
////////////////////////////////
//~ rjf: Globals
read_only global Type type_leaves[] =
{
{TypeKind_Null, 0, 0, &type_leaves[0], str8_lit_comp("null")},
{TypeKind_Void, 0, 0, &type_leaves[0], str8_lit_comp("void")},
{TypeKind_U8, 0, sizeof(U8), &type_leaves[0], str8_lit_comp("U8")},
{TypeKind_U16, 0, sizeof(U16), &type_leaves[0], str8_lit_comp("U16")},
{TypeKind_U32, 0, sizeof(U32), &type_leaves[0], str8_lit_comp("U32")},
{TypeKind_U64, 0, sizeof(U64), &type_leaves[0], str8_lit_comp("U64")},
{TypeKind_S8, 0, sizeof(S8), &type_leaves[0], str8_lit_comp("S8")},
{TypeKind_S16, 0, sizeof(S16), &type_leaves[0], str8_lit_comp("S16")},
{TypeKind_S32, 0, sizeof(S32), &type_leaves[0], str8_lit_comp("S32")},
{TypeKind_S64, 0, sizeof(S64), &type_leaves[0], str8_lit_comp("S64")},
{TypeKind_B8, 0, sizeof(B8), &type_leaves[0], str8_lit_comp("B8")},
{TypeKind_B16, 0, sizeof(B16), &type_leaves[0], str8_lit_comp("B16")},
{TypeKind_B32, 0, sizeof(B32), &type_leaves[0], str8_lit_comp("B32")},
{TypeKind_B64, 0, sizeof(B64), &type_leaves[0], str8_lit_comp("B64")},
{TypeKind_F32, 0, sizeof(F32), &type_leaves[0], str8_lit_comp("F32")},
{TypeKind_F64, 0, sizeof(F64), &type_leaves[0], str8_lit_comp("F64")},
};
read_only global Member member_nil = {{0}, &type_leaves[0]};
////////////////////////////////
//~ rjf: Type Info Lookups
#define type(T) &(T##__type)
internal Member *member_from_name(Type *type, String8 name);
////////////////////////////////
//~ rjf: Type Info * Instance Operations
internal String8 serialized_from_typed_data(Arena *arena, Type *type, void *ptr, TypeSerializeParams *params);
internal void *data_from_typed_serialized(Arena *arena, Type *type, String8 string, TypeSerializeParams *params);
#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), (ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__})
#define struct_from_serialized(arena, T, string, ...) (T *)data_from_typed_serialized((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__})
#endif // BASE_META_H