mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-12 23:51:37 -07:00
[examples] more type metadata commentary; write some usage code for the generated type info
This commit is contained in:
@@ -30,12 +30,20 @@ $build_path/type_metadata.exe $examps_path/type_metadata/types.mdesk
|
||||
echo
|
||||
|
||||
if [ -f $examps_path/type_metadata/generated/meta_types.h ]; then
|
||||
echo ~~~ Building Program ~~~
|
||||
$bin_path/bld_core.sh unit type_info $examps/type_metadata/type_info_final_program.c
|
||||
else
|
||||
echo !!! Skipping Program !!!
|
||||
fi
|
||||
echo ~~~ Building Final Program ~~~
|
||||
$bin_path/bld_core.sh unit type_info_final $examps/type_metadata/type_info_final_program.c
|
||||
echo
|
||||
|
||||
echo ~~~ Running Final Program ~~~
|
||||
$build_path/type_info_final
|
||||
echo
|
||||
|
||||
else
|
||||
|
||||
echo !!! Skipping Final Program !!!
|
||||
echo
|
||||
|
||||
fi
|
||||
|
||||
###### Restore Path ###########################################################
|
||||
cd $og_path
|
||||
@@ -1,4 +1,4 @@
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:837
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:874
|
||||
TypeInfoMember Circle_members[2] = {
|
||||
{"r", 1, -1, &F32_type_info},
|
||||
{"pos", 3, -1, &V2F32_type_info},
|
||||
@@ -14,14 +14,14 @@ TypeInfoMember RoundedPolygon_members[3] = {
|
||||
{"p", 1, 1, &V2F32_type_info},
|
||||
};
|
||||
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:876
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:913
|
||||
TypeInfoEnumerant Shape_members[3] = {
|
||||
{"Circle", 6, 1},
|
||||
{"Segment", 7, 2},
|
||||
{"Polygon", 7, 3},
|
||||
};
|
||||
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:912
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:949
|
||||
TypeInfo U32_type_info = {TypeKind_Basic, "U32", 3, 4, 0, 0};
|
||||
TypeInfo F32_type_info = {TypeKind_Basic, "F32", 3, 4, 0, 0};
|
||||
TypeInfo V2F32_type_info = {TypeKind_Basic, "V2F32", 5, 8, 0, 0};
|
||||
@@ -30,7 +30,7 @@ TypeInfo RoundedSegment_type_info = {TypeKind_Struct, "RoundedSegment", 14, 3, R
|
||||
TypeInfo RoundedPolygon_type_info = {TypeKind_Struct, "RoundedPolygon", 14, 3, RoundedPolygon_members, 0};
|
||||
TypeInfo Shape_type_info = {TypeKind_Enum, "Shape", 5, 3, Shape_members, &U32_type_info};
|
||||
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:972
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:1009
|
||||
TypeInfo*
|
||||
type_info_from_shape(Shape v)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#if !defined(META_TYPES_H)
|
||||
#define META_TYPES_H
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:714
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:751
|
||||
typedef struct Circle Circle;
|
||||
struct Circle
|
||||
{
|
||||
@@ -29,11 +29,11 @@ Shape_Segment = 2,
|
||||
Shape_Polygon = 3,
|
||||
};
|
||||
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:798
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:835
|
||||
TypeInfo* type_info_from_shape(Shape v);
|
||||
U32 max_slot_from_shape(Shape v);
|
||||
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:821
|
||||
// generated by W:/metadesk/examples/type_metadata/type_metadata.c:858
|
||||
extern TypeInfo U32_type_info;
|
||||
extern TypeInfo F32_type_info;
|
||||
extern TypeInfo V2F32_type_info;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
/*
|
||||
** Example: type metadata
|
||||
**
|
||||
** This file shows including the generated type information into a final
|
||||
** program and using that type info to unpack a buffer of data.
|
||||
** This file shows including the generated types and metadata in the a final
|
||||
** program and using it to unpack a buffer of data.
|
||||
**
|
||||
*/
|
||||
|
||||
//~ setup base types //////////////////////////////////////////////////////////
|
||||
#include <stdint.h>
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef float F32;
|
||||
typedef struct V2F32 V2F32;
|
||||
@@ -26,12 +28,184 @@ struct V2F32
|
||||
|
||||
//~ main //////////////////////////////////////////////////////////////////////
|
||||
|
||||
U8 raw_buffer[] = {
|
||||
0x03,0x00,0x00,0x00,0x00,0x00,0x90,0x40,0x06,0x00,0x00,0x00,
|
||||
0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,
|
||||
0x2D,0xB2,0x5D,0x3F,0x00,0x00,0x00,0xBF,0x2D,0xB2,0x5D,0x3F,
|
||||
0x00,0x00,0x80,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBF,
|
||||
0x2D,0xB2,0x5D,0xBF,0x00,0x00,0x00,0x3F,0x2D,0xB2,0x5D,0xBF,
|
||||
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,
|
||||
0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0xC0,
|
||||
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,
|
||||
0x00,0x00,0x00,0xC0,0x00,0x00,0x80,0x40,0x00,0x00,0x00,0x00,
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
int
|
||||
print_data_from_type_info(U8 **ptr_inout, U8 *opl, TypeInfo *type_info, int indent){
|
||||
static char spaces[] =
|
||||
" ";
|
||||
|
||||
int result = 1;
|
||||
|
||||
switch (type_info->kind){
|
||||
case TypeKind_Basic:
|
||||
{
|
||||
// special case each basic type
|
||||
|
||||
if (type_info == &U32_type_info)
|
||||
{
|
||||
if (*ptr_inout + sizeof(U32) > opl)
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
U32 x = *(U32*)*ptr_inout;
|
||||
*ptr_inout += sizeof(x);
|
||||
fprintf(stdout, "%u\n", x);
|
||||
}
|
||||
|
||||
if (type_info == &F32_type_info)
|
||||
{
|
||||
if (*ptr_inout + sizeof(F32) > opl)
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
F32 x = *(F32*)*ptr_inout;
|
||||
*ptr_inout += sizeof(x);
|
||||
fprintf(stdout, "%f\n", x);
|
||||
}
|
||||
|
||||
if (type_info == &V2F32_type_info)
|
||||
{
|
||||
if (*ptr_inout + sizeof(V2F32) > opl)
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
V2F32 x = *(V2F32*)*ptr_inout;
|
||||
*ptr_inout += sizeof(x);
|
||||
fprintf(stdout, "(%f,%f)\n", x.x, x.y);
|
||||
}
|
||||
}break;
|
||||
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
U32 member_value_memory[20] = {0};
|
||||
|
||||
// iterate members
|
||||
TypeInfoMember *first_member = (TypeInfoMember*)type_info->children;
|
||||
TypeInfoMember *member = first_member;
|
||||
int child_count = type_info->child_count;
|
||||
for (int i = 0; i < child_count; i += 1, member += 1)
|
||||
{
|
||||
assert(i < 20);
|
||||
TypeInfo *member_type_info = member->type;
|
||||
|
||||
// decode single members
|
||||
if (member->array_count_member_index == -1)
|
||||
{
|
||||
// save the offset of this member for later
|
||||
U8 *ptr_og = *ptr_inout;
|
||||
// decode this member
|
||||
fprintf(stdout, "%.*s%.*s: ", indent, spaces, member->name_length, member->name);
|
||||
if (!print_data_from_type_info(ptr_inout, opl, member_type_info, indent + 1))
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
// if we see a U32 we want to remember it in case it's an array count
|
||||
if (member_type_info == &U32_type_info)
|
||||
{
|
||||
member_value_memory[i] = *(U32*)ptr_og;
|
||||
}
|
||||
}
|
||||
|
||||
// decode arrays
|
||||
else
|
||||
{
|
||||
assert(member->array_count_member_index < i);
|
||||
U32 count = member_value_memory[member->array_count_member_index];
|
||||
fprintf(stdout, "%.*s%.*s:\n", indent, spaces, member->name_length, member->name);
|
||||
indent += 1;
|
||||
for (U32 j = 0; j < count; j += 1)
|
||||
{
|
||||
fprintf(stdout, "%.*s[%d]: ", indent, spaces, j);
|
||||
if (!print_data_from_type_info(ptr_inout, opl, member_type_info, indent + 1))
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
indent -= 1;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case TypeKind_Enum:
|
||||
{
|
||||
// rely on the underlying type (default to U32) to print enums
|
||||
TypeInfo *underlying_type = type_info->underlying_type;
|
||||
if (underlying_type == 0)
|
||||
{
|
||||
underlying_type = &U32_type_info;
|
||||
}
|
||||
fprintf(stdout, "(%.*s)", type_info->name_length, type_info->name);
|
||||
if (!print_data_from_type_info(ptr_inout, opl, underlying_type, indent))
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = 0;
|
||||
goto finish;
|
||||
}break;
|
||||
}
|
||||
|
||||
finish:;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
// TODO(allen): write example final program
|
||||
// decode the raw buffer
|
||||
U8 *ptr = raw_buffer;
|
||||
U8 *opl = ptr + sizeof(raw_buffer);
|
||||
for (;ptr < opl;)
|
||||
{
|
||||
// decode a shape discriminator
|
||||
if (ptr + sizeof(Shape) > opl){
|
||||
fprintf(stdout, "Could not decode shape discriminator\n");
|
||||
break;
|
||||
}
|
||||
Shape shape = *(Shape*)ptr;
|
||||
ptr += sizeof(shape);
|
||||
|
||||
// get type info
|
||||
TypeInfo *type_info = type_info_from_shape(shape);
|
||||
if (type_info == 0){
|
||||
fprintf(stdout, "Unrecognized shape discriminator\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// print type name
|
||||
fprintf(stdout, "%.*s:\n", type_info->name_length, type_info->name);
|
||||
|
||||
// print contents
|
||||
if (!print_data_from_type_info(&ptr, opl, type_info, 1))
|
||||
{
|
||||
fprintf(stdout, "Decoding error\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
** type_info_final_program.c - In addition to the metaprogram this example
|
||||
** includes a "final program", i.e. one that depends on
|
||||
** generated code. There is more commentary there.
|
||||
** generated/* - This is the output folder where the generated files
|
||||
** generated/ * - This is the output folder where the generated files
|
||||
** should be saved by the metaprogram.
|
||||
** types.mdesk - Sample input for this metaprogram. The code generated
|
||||
** from this metadesk file will be necessary to make
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
** Example: type metadata
|
||||
**
|
||||
** TODO full commentary
|
||||
** The header file for the metaprogram's main file. There isn't much commentary
|
||||
** here, this file is just to help us keep the example organized.
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
+5
-5
@@ -94,16 +94,16 @@ command_list =
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "type_info_example",
|
||||
.name = "type_metadata_example",
|
||||
.out = "*run*",
|
||||
.footer_panel = false,
|
||||
.save_dirty_files = true,
|
||||
.cursor_at_end = false,
|
||||
.cmd =
|
||||
{
|
||||
{ "git_bash bin\\type_info_example.sh", .os = "win" },
|
||||
{ "bin/type_info_example.sh", .os = "linux" },
|
||||
{ "bin/type_info_example.sh", .os = "mac" },
|
||||
{ "git_bash bin\\type_metadata_example.sh", .os = "win" },
|
||||
{ "bin/type_metadata_example.sh", .os = "linux" },
|
||||
{ "bin/type_metadata_example.sh", .os = "mac" },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -112,4 +112,4 @@ fkey_command[1] = "build_tests";
|
||||
fkey_command[2] = "run_tests";
|
||||
fkey_command[3] = "build_examples";
|
||||
fkey_command[4] = "run_examples";
|
||||
fkey_command[5] = "type_info_example";
|
||||
fkey_command[5] = "type_metadata_example";
|
||||
|
||||
Reference in New Issue
Block a user