[examples] more type metadata commentary; write some usage code for the generated type info

This commit is contained in:
Allen Webster
2021-10-08 22:13:45 -07:00
parent 367b527229
commit a5436aec0e
7 changed files with 205 additions and 22 deletions
@@ -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);
}
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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
View File
@@ -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";