#pragma once #include #include "allocator.h" #include "vector.h" #include "color.h" // config parsers and serializers go here struct CFG_NODE; struct CFG_SECTION; struct CFG_PARSER; struct CFG_SERIALIZER; enum CfgNodeType_t { CFGT_SECTION, CFGT_BYTES, CFGT_STR, CFGT_FLOAT, CFGT_INT, CFGT_VEC2, CFGT_VEC3, CFGT_CLR }; // ===================================== [ definitions ] =========================================== using CFG_PARSEFN = std::function; using CFG_SERIALIZEFN = std::function; struct CFG_TYPE { U8 type; const char* def; CFG_PARSEFN parser; CFG_SERIALIZEFN serializer; }; struct CFG_NODE { char name[64]; CFG_NODE* parent; U8 type; }; struct CFG_SECTION : CFG_NODE { LIST children; }; struct CFG_BYTES : CFG_NODE { U8* bytes; U32 size; }; struct CFG_STR : CFG_NODE { char* str; U32 len; }; struct CFG_INT : CFG_NODE { I32 value; }; struct CFG_FLOAT : CFG_NODE { F32 value; }; struct CFG_VEC2 : CFG_NODE { VEC2 value; }; struct CFG_VEC3 : CFG_NODE { VEC3 value; }; struct CFG_CLR : CFG_NODE { CLR value; }; // ======================================= [ parsers ] ============================================= extern STAT cfg_parser_bytes( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_str( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_int( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_float( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_vec2( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_vec3( CFG_PARSER* parser, CFG_SECTION* section, char* name ); extern STAT cfg_parser_clr( CFG_PARSER* parser, CFG_SECTION* section, char* name ); // ====================================== [ serializers ] ========================================== extern void cfg_serialize_section( CFG_SERIALIZER* serializer, CFG_NODE* section, char* buf ); extern void cfg_serialize_bytes( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_str( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_float( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_int( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_vec2( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_vec3( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); extern void cfg_serialize_clr( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf ); // ========================================= [ config ] ============================================ static const CFG_TYPE cfg_types[] = { { CFGT_SECTION, "DEF" , 0, &cfg_serialize_section }, // section { CFGT_BYTES , "U8" , &cfg_parser_bytes, &cfg_serialize_bytes }, { CFGT_STR , "STR" , &cfg_parser_str , &cfg_serialize_str }, { CFGT_FLOAT , "F32" , &cfg_parser_float, &cfg_serialize_float }, { CFGT_INT , "I32" , &cfg_parser_int , &cfg_serialize_int }, { CFGT_VEC2 , "VEC2", &cfg_parser_vec2 , &cfg_serialize_vec2 }, { CFGT_VEC3 , "VEC3", &cfg_parser_vec3 , &cfg_serialize_vec3 }, { CFGT_CLR , "CLR" , &cfg_parser_clr , &cfg_serialize_clr }, }; // ========================================= [ io ] ================================================ extern CFG_SECTION* cfg_load( const char* path ); extern STAT cfg_save( CFG_SECTION* root, const char* path ); static void cfg_free( CFG_NODE* n ); // =================================== [ getters/setters ] ========================================= // cfg_section_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_SECTION* cfg_section( CFG_SECTION* parent, const char* name ); // cfg_str_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_STR* cfg_str( CFG_SECTION* section, const char* name ); // cfg_bytes_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_BYTES* cfg_bytes( CFG_SECTION* section, const char* name ); // cfg_float_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_FLOAT* cfg_float( CFG_SECTION* section, const char* name ); // cfg_int_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_INT* cfg_int( CFG_SECTION* section, const char* name ); // cfg_vec2_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_VEC2* cfg_vec2( CFG_SECTION* section, const char* name ); // cfg_vec3_get( CFG_SECTION*, const char* ) -- retrieve function extern CFG_VEC3* cfg_vec3( CFG_SECTION* section, const char* name ); // cfg_clr_get( CFG_SECTION*, const char* ) -- retrieve function for extern CFG_CLR* cfg_clr( CFG_SECTION* section, const char* name ); // cfg_section_new( const char*, CFG_NODE*, I32 ) -- create function extern CFG_SECTION* cfg_section_new( const char* name, CFG_NODE* parent ); // cfg_str_new( const char*, CFG_NODE*, const char*, U32 ) -- create function extern CFG_STR* cfg_str( const char* name, CFG_NODE* section, const char* value, U32 len ); // cfg_bytes_new( const char*, CFG_NODE*, U8*, U32 ) -- create function extern CFG_BYTES* cfg_bytes( const char* name, CFG_NODE* section, U8* value, U32 size ); // cfg_float_new( const char*, CFG_NODE*, F32 ) -- create function extern CFG_FLOAT* cfg_float( const char* name, CFG_NODE* section, F32 value ); // cfg_int_new( const char*, CFG_NODE*, I32 ) -- create function extern CFG_INT* cfg_int( const char* name, CFG_NODE* section, I32 value ); // cfg_vec2_new( const char*, CFG_NODE*, VEC2 ) -- create function extern CFG_VEC2* cfg_vec2( const char* name, CFG_NODE* section, VEC2 value ); // cfg_vec3_new( const char*, CFG_NODE*, VEC3 ) -- create function extern CFG_VEC3* cfg_vec3( const char* name, CFG_NODE* section, VEC3 value ); // cfg_clr_new( const char*, CFG_NODE*, CLR ) -- create function extern CFG_CLR* cfg_clr( const char* name, CFG_NODE* section, CLR value ); // ================================================================================================= struct CFG_PARSER { FILE* file; CFG_SECTION* root; char err[256]; U32 linen; U8 iserr; }; struct CFG_SERIALIZER { FILE* f; U8 iserr; char err[256]; U32 tabc; }; static void cfg_free( CFG_NODE* n ) { if( n->type == CFGT_STR ) { CFG_STR* str = (CFG_STR*)n; free( str->str ); } else if( n->type == CFGT_BYTES ) { CFG_BYTES* bytes = (CFG_BYTES*)n; free( bytes->bytes ); } else if( n->type == CFGT_SECTION ) { CFG_SECTION* s = (CFG_SECTION*)n; s->children.each( fn( CFG_NODE** child ) { cfg_free( *child ); } ); } delete n; } extern void cfg_seterr( CFG_PARSER* p, const char* fmt, ... );