Fix for sanity test...

This commit is contained in:
Edward R. Gonzalez 2023-07-17 23:40:28 -04:00
parent 9a784fe92f
commit e501941c5c
5 changed files with 1641 additions and 155 deletions

View File

@ -699,7 +699,8 @@ This project came about for a few reasons:
* Not a fan of pure C, maybe I'll succumb to the drawbacks. * Not a fan of pure C, maybe I'll succumb to the drawbacks.
* All alternatives to C/C++ are too opionionated instead of providing a lax frontend, or a proper compiler backend with a frontend api to quickly roll your own forntend. * All alternatives to C/C++ are too opionionated instead of providing a lax frontend, or a proper compiler backend with a frontend api to quickly roll your own forntend.
* One of the core issues I've always had with programming is there has always been a need for metaprogramming, but every single tool has horrible error deduction for the user (backend blackbox from codebase size or closed-source, error log nightmare). * One of the core issues I've always had with programming is there has always been a need for metaprogramming, but every single tool has horrible error deduction for the user (backend blackbox from codebase size or closed-source, error log nightmare).
* I spend an obnoxious amount of time trying to express code that cannot be expressed well in templates or macros and still have an adequate editor experience, even with full blown IDEs. * I spend an obnoxious amount of time trying to express code that cannot be expressed well in templates or macros. The experience is inadequate; even with full blown IDEs.
* I wanted to be able to easily refactor interated with projects with some form of curation, and still have the ability to not maintain a separate fork (IF the scanner gets implemetned, that is possible). * I wanted to be able to easily refactor libraries interated in projects with some form of curation. While still having the ability to not maintain a separate fork (IF the scanner gets implemetned, that is possible).
* I did not use Metadesk as it was an esoteric library for me to use as a dependency when I didn't fully grasp the vision for how this library would end up. (Not much practice doing metaprogramming or code gen/transform development) * I did not use Metadesk as it was an esoteric library for me to use as a dependency when I didn't fully grasp the vision for how this library would end up. (Not much practice doing metaprogramming or code gen/transform development)
* I have no issue rewritting the library to use it as a backend if its worth while but its most likely better to just make an extension for it. * I have no issue rewritting the library to use it as a backend if its worth while but its most likely better to just make an extension for it.
* This project showed me rewwriting code isn't as expensive as people make it out to be (vs using a bloated toolchain)

File diff suppressed because it is too large Load Diff

View File

@ -223,17 +223,12 @@ namespace gen
} \ } \
while(0); while(0);
#define clamp( x, lower, upper ) min( max( ( x ), ( lower ) ), ( upper ) )
#define count_of( x ) ( ( size_of( x ) / size_of( 0 [ x ] ) ) / ( ( sw )( ! ( size_of( x ) % size_of( 0 [ x ] ) ) ) ) ) #define count_of( x ) ( ( size_of( x ) / size_of( 0 [ x ] ) ) / ( ( sw )( ! ( size_of( x ) % size_of( 0 [ x ] ) ) ) ) )
#define is_between( x, lower, upper ) ( ( ( lower ) <= ( x ) ) && ( ( x ) <= ( upper ) ) ) #define is_between( x, lower, upper ) ( ( ( lower ) <= ( x ) ) && ( ( x ) <= ( upper ) ) )
#define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
#define min( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) ) #define min( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
#define size_of( x ) ( sw )( sizeof( x ) ) #define size_of( x ) ( sw )( sizeof( x ) )
// #define swap( Type, a, b ) \
// do \
// { \
// Type tmp = ( a ); \
// ( a ) = ( b ); \
// ( b ) = tmp; \
// } while ( 0 )
template< class Type > template< class Type >
void swap( Type a, Type b ) void swap( Type a, Type b )
@ -420,6 +415,12 @@ namespace gen
//! Moves pointer forward by bytes. //! Moves pointer forward by bytes.
GEN_DEF_INLINE void* pointer_add( void* ptr, sw bytes ); GEN_DEF_INLINE void* pointer_add( void* ptr, sw bytes );
//! Moves pointer forward by bytes.
GEN_DEF_INLINE void const* pointer_add_const( void const* ptr, sw bytes );
//! Calculates difference between two addresses.
GEN_DEF_INLINE sw pointer_diff( void const* begin, void const* end );
//! Copy non-overlapping memory from source to destination. //! Copy non-overlapping memory from source to destination.
void* mem_copy( void* dest, void const* source, sw size ); void* mem_copy( void* dest, void const* source, sw size );
@ -550,6 +551,16 @@ namespace gen
return zpl_cast( void* )( zpl_cast( u8* ) ptr + bytes ); return zpl_cast( void* )( zpl_cast( u8* ) ptr + bytes );
} }
GEN_IMPL_INLINE void const* pointer_add_const( void const* ptr, sw bytes )
{
return zpl_cast( void const* )( zpl_cast( u8 const* ) ptr + bytes );
}
GEN_IMPL_INLINE sw pointer_diff( void const* begin, void const* end )
{
return zpl_cast( sw )( zpl_cast( u8 const* ) end - zpl_cast( u8 const* ) begin );
}
GEN_IMPL_INLINE void* mem_move( void* dest, void const* source, sw n ) GEN_IMPL_INLINE void* mem_move( void* dest, void const* source, sw n )
{ {
if ( dest == NULL ) if ( dest == NULL )
@ -869,6 +880,7 @@ namespace gen
#pragma region String Ops #pragma region String Ops
GEN_DEF_INLINE const char* char_first_occurence( const char* str, char c ); GEN_DEF_INLINE const char* char_first_occurence( const char* str, char c );
constexpr auto str_find = &char_first_occurence;
GEN_DEF_INLINE b32 char_is_alpha( char c ); GEN_DEF_INLINE b32 char_is_alpha( char c );
GEN_DEF_INLINE b32 char_is_alphanumeric( char c ); GEN_DEF_INLINE b32 char_is_alphanumeric( char c );
@ -888,14 +900,17 @@ namespace gen
GEN_DEF_INLINE sw str_len( const char* str ); GEN_DEF_INLINE sw str_len( const char* str );
GEN_DEF_INLINE sw str_len( const char* str, sw max_len ); GEN_DEF_INLINE sw str_len( const char* str, sw max_len );
GEN_DEF_INLINE char* str_reverse( char* str ); // NOTE: ASCII only GEN_DEF_INLINE char* str_reverse( char* str ); // NOTE: ASCII only
GEN_DEF_INLINE char const* str_skip( char const* str, char c );
GEN_DEF_INLINE char const* str_skip_any( char const* str, char const* char_list );
// NOTE: ASCII only // NOTE: ASCII only
GEN_DEF_INLINE void str_to_lower( char* str ); GEN_DEF_INLINE void str_to_lower( char* str );
GEN_DEF_INLINE void str_to_upper( char* str ); GEN_DEF_INLINE void str_to_upper( char* str );
s64 str_to_i64( const char* str, char** end_ptr, s32 base ); // TODO : Support more than just decimal and hexadecimal s64 str_to_i64( const char* str, char** end_ptr, s32 base );
void i64_to_str( s64 value, char* string, s32 base ); void i64_to_str( s64 value, char* string, s32 base );
void u64_to_str( u64 value, char* string, s32 base ); void u64_to_str( u64 value, char* string, s32 base );
f64 str_to_f64( const char* str, char** end_ptr );
GEN_IMPL_INLINE const char* char_first_occurence( const char* s, char c ) GEN_IMPL_INLINE const char* char_first_occurence( const char* s, char c )
{ {
@ -1070,6 +1085,27 @@ namespace gen
return str; return str;
} }
GEN_IMPL_INLINE char const* str_skip( char const* str, char c )
{
while ( *str && *str != c )
{
++str;
}
return str;
}
GEN_IMPL_INLINE char const* str_skip_any( char const* str, char const* char_list )
{
char const* closest_ptr = zpl_cast( char const* ) pointer_add( ( void* )str, str_len( str ) );
sw char_list_count = str_len( char_list );
for ( sw i = 0; i < char_list_count; i++ )
{
char const* p = str_skip( str, char_list[ i ] );
closest_ptr = min( closest_ptr, p );
}
return closest_ptr;
}
GEN_IMPL_INLINE void str_to_lower( char* str ) GEN_IMPL_INLINE void str_to_lower( char* str )
{ {
if ( ! str ) if ( ! str )
@ -1104,10 +1140,11 @@ namespace gen
char* str_fmt_buf ( char const* fmt, ... ); char* str_fmt_buf ( char const* fmt, ... );
char* str_fmt_buf_va ( char const* fmt, va_list va ); char* str_fmt_buf_va ( char const* fmt, va_list va );
sw str_fmt_va ( char* str, sw n, char const* fmt, va_list va ); sw str_fmt_va ( char* str, sw n, char const* fmt, va_list va );
sw str_fmt_file ( FileInfo* f, char const* fmt, ... );
sw str_fmt_file_va ( FileInfo* f, char const* fmt, va_list va );
sw str_fmt_out_va ( char const* fmt, va_list va ); sw str_fmt_out_va ( char const* fmt, va_list va );
sw str_fmt_out_err ( char const* fmt, ... ); sw str_fmt_out_err ( char const* fmt, ... );
sw str_fmt_out_err_va( char const* fmt, va_list va ); sw str_fmt_out_err_va( char const* fmt, va_list va );
sw str_fmt_file_va( FileInfo* f, char const* fmt, va_list va );
constexpr constexpr
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED"; char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
@ -1207,6 +1244,77 @@ namespace gen
return true; return true;
} }
bool append( Type* items, uw item_num )
{
Header* header = get_header();
if ( header->Num + item_num > header->Capacity )
{
if ( ! grow( header->Capacity + item_num ))
return false;
header = get_header();
}
mem_copy( Data + header->Num, items, item_num * sizeof(Type) );
header->Num += item_num;
return true;
}
bool append_at( Type item, sw idx )
{
Header* header = get_header();
if ( idx >= header->Num )
idx = header->Num - 1;
if ( idx < 0 )
idx = 0;
if ( header->Capacity < header->Num + 1 )
{
if ( ! grow( header->Capacity + 1 ))
return false;
header = get_header();
}
Type* target = Data + idx;
mem_move( target + 1, target, (header->Num - idx) * sizeof(Type) );
return true;
}
bool append_at( Type* items, uw item_num, sw idx )
{
Header* header = get_header();
if ( idx >= header->Num )
{
return append( items, item_num );
}
if ( item_num > header->Capacity )
{
if ( ! grow( header->Capacity + item_num ) )
return false;
header = get_header();
}
Type* target = Data + idx + item_num;
Type* src = Data + idx;
mem_move( target, src, (header->Num - idx) * sizeof(Type) );
mem_copy( src, items, item_num * sizeof(Type) );
header->Num += item_num;
return true;
}
Type& back( void ) Type& back( void )
{ {
Header& header = * get_header(); Header& header = * get_header();
@ -1238,6 +1346,7 @@ namespace gen
{ {
Header& header = * get_header(); Header& header = * get_header();
gen::free( header.Allocator, &header ); gen::free( header.Allocator, &header );
Data = nullptr;
} }
Header* get_header( void ) Header* get_header( void )
@ -2074,30 +2183,30 @@ namespace gen
struct DirEntry struct DirEntry
{ {
char const* FileName; char const* filename;
DirInfo* Info; struct DirInfo* dir_info;
u8 Type; u8 type;
}; };
struct DirInfo struct DirInfo
{ {
char const* FullPath; char const* fullpath;
DirEntry* Entries; // zpl_array DirEntry* entries; // zpl_array
// Internals // Internals
char** Filenames; // zpl_array char** filenames; // zpl_array
char* Buffer; // zpl_string String buf;
}; };
struct FileInfo struct FileInfo
{ {
FileOperations Ops; FileOperations ops;
FileDescriptor FD; FileDescriptor fd;
b32 IsTemp; b32 is_temp;
char const* Filename; char const* filename;
FileTime LastWriteTime; FileTime last_write_time;
DirEntry* Dir; DirEntry* dir;
}; };
enum FileStandardType enum FileStandardType
@ -2129,7 +2238,7 @@ namespace gen
inline inline
char const* file_name( FileInfo* file ) char const* file_name( FileInfo* file )
{ {
return file->Filename ? file->Filename : ""; return file->filename ? file->filename : "";
} }
/** /**
@ -2227,10 +2336,10 @@ namespace gen
{ {
s64 new_offset = 0; s64 new_offset = 0;
if ( ! f->Ops.read_at ) if ( ! f->ops.read_at )
f->Ops = default_file_operations; f->ops = default_file_operations;
f->Ops.seek( f->FD, offset, ESeekWhence_BEGIN, &new_offset ); f->ops.seek( f->fd, offset, ESeekWhence_BEGIN, &new_offset );
return new_offset; return new_offset;
} }
@ -2239,10 +2348,10 @@ namespace gen
{ {
s64 new_offset = 0; s64 new_offset = 0;
if ( ! f->Ops.read_at ) if ( ! f->ops.read_at )
f->Ops = default_file_operations; f->ops = default_file_operations;
f->Ops.seek( f->FD, 0, ESeekWhence_END, &new_offset ); f->ops.seek( f->fd, 0, ESeekWhence_END, &new_offset );
return new_offset; return new_offset;
} }
@ -2251,10 +2360,10 @@ namespace gen
{ {
s64 new_offset = 0; s64 new_offset = 0;
if ( ! f->Ops.read_at ) if ( ! f->ops.read_at )
f->Ops = default_file_operations; f->ops = default_file_operations;
f->Ops.seek( f->FD, 0, ESeekWhence_CURRENT, &new_offset ); f->ops.seek( f->fd, 0, ESeekWhence_CURRENT, &new_offset );
return new_offset; return new_offset;
} }
@ -2274,9 +2383,9 @@ namespace gen
GEN_IMPL_INLINE b32 file_read_at_check( FileInfo* f, void* buffer, sw size, s64 offset, sw* bytes_read ) GEN_IMPL_INLINE b32 file_read_at_check( FileInfo* f, void* buffer, sw size, s64 offset, sw* bytes_read )
{ {
if ( ! f->Ops.read_at ) if ( ! f->ops.read_at )
f->Ops = default_file_operations; f->ops = default_file_operations;
return f->Ops.read_at( f->FD, buffer, size, offset, bytes_read, false ); return f->ops.read_at( f->fd, buffer, size, offset, bytes_read, false );
} }
GEN_IMPL_INLINE b32 file_write( FileInfo* f, void const* buffer, sw size ) GEN_IMPL_INLINE b32 file_write( FileInfo* f, void const* buffer, sw size )
@ -2296,120 +2405,116 @@ namespace gen
GEN_IMPL_INLINE b32 file_write_at_check( FileInfo* f, void const* buffer, sw size, s64 offset, sw* bytes_written ) GEN_IMPL_INLINE b32 file_write_at_check( FileInfo* f, void const* buffer, sw size, s64 offset, sw* bytes_written )
{ {
if ( ! f->Ops.read_at ) if ( ! f->ops.read_at )
f->Ops = default_file_operations; f->ops = default_file_operations;
return f->Ops.write_at( f->FD, buffer, size, offset, bytes_written ); return f->ops.write_at( f->fd, buffer, size, offset, bytes_written );
} }
enum FileStreamFlags : u32
{
/* Allows us to write to the buffer directly. Beware: you can not append a new data! */
EFileStream_WRITABLE = bit( 0 ),
/* Clones the input buffer so you can write (zpl_file_write*) data into it. */
/* Since we work with a clone, the buffer size can dynamically grow as well. */
EFileStream_CLONE_WRITABLE = bit( 1 ),
};
/**
* Opens a new memory stream
* @param file
* @param allocator
*/
b8 file_stream_new( FileInfo* file, AllocatorInfo allocator );
/**
* Opens a memory stream over an existing buffer
* @param file
* @param allocator
* @param buffer Memory to create stream from
* @param size Buffer's size
* @param flags
*/
b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw size, FileStreamFlags flags );
/**
* Retrieves the stream's underlying buffer and buffer size.
* @param file memory stream
* @param size (Optional) buffer size
*/
u8* file_stream_buf( FileInfo* file, sw* size );
extern FileOperations const memory_file_operations;
#pragma endregion File Handling #pragma endregion File Handling
#pragma region ADT #pragma region ADT
enum ADT_Type : u32 enum ADT_Type : u32
{ {
EADTTYPE_UNINITIALISED, /* node was not initialised, this is a programming error! */ EADT_TYPE_UNINITIALISED, /* node was not initialised, this is a programming error! */
EADTTYPE_ARRAY, EADT_TYPE_ARRAY,
EADTTYPE_OBJECT, EADT_TYPE_OBJECT,
EADTTYPE_STRING, EADT_TYPE_STRING,
EADTTYPE_MULTISTRING, EADT_TYPE_MULTISTRING,
EADTTYPE_INTEGER, EADT_TYPE_INTEGER,
EADTTYPE_REAL, EADT_TYPE_REAL,
}; };
enum ADT_Props : u32 enum ADT_Props : u32
{ {
EADTPROPS_NONE, EADT_PROPS_NONE,
EADTPROPS_NAN, EADT_PROPS_NAN,
EADTPROPS_NAN_NEG, EADT_PROPS_NAN_NEG,
EADTPROPS_INFINITY, EADT_PROPS_INFINITY,
EADTPROPS_INFINITY_NEG, EADT_PROPS_INFINITY_NEG,
EADTPROPS_FALSE, EADT_PROPS_FALSE,
EADTPROPS_TRUE, EADT_PROPS_TRUE,
EADTPROPS_NULL, EADT_PROPS_NULL,
EADTPROPS_IS_EXP, EADT_PROPS_IS_EXP,
EADTPROPS_IS_HEX, EADT_PROPS_IS_HEX,
// Used internally so that people can fill in real numbers they plan to write. // Used internally so that people can fill in real numbers they plan to write.
EADTPROPS_IS_PARSED_REAL, EADT_PROPS_IS_PARSED_REAL,
}; };
enum ADT_NamingStyle : u32 enum ADT_NamingStyle : u32
{ {
EADTNAME_STYLE_DOUBLE_QUOTE, EADT_NAME_STYLE_DOUBLE_QUOTE,
EADTNAME_STYLE_SINGLE_QUOTE, EADT_NAME_STYLE_SINGLE_QUOTE,
EADTNAME_STYLE_NO_QUOTES, EADT_NAME_STYLE_NO_QUOTES,
}; };
enum ADT_AssignStyle : u32 enum ADT_AssignStyle : u32
{ {
EADTASSIGN_STYLE_COLON, EADT_ASSIGN_STYLE_COLON,
EADTASSIGN_STYLE_EQUALS, EADT_ASSIGN_STYLE_EQUALS,
EADTASSIGN_STYLE_LINE, EADT_ASSIGN_STYLE_LINE,
}; };
enum ADT_DelimStyle : u32 enum ADT_DelimStyle : u32
{ {
EADTDELIM_STYLE_COMMA, EADT_DELIM_STYLE_COMMA,
EADTDELIM_STYLE_LINE, EADT_DELIM_STYLE_LINE,
EADTDELIM_STYLE_NEWLINE, EADT_DELIM_STYLE_NEWLINE,
}; };
enum ADT_Error : u32 enum ADT_Error : u32
{ {
EADTERROR_NONE, EADT_ERROR_NONE,
EADTERROR_INTERNAL, EADT_ERROR_INTERNAL,
EADTERROR_ALREADY_CONVERTED, EADT_ERROR_ALREADY_CONVERTED,
EADTERROR_INVALID_TYPE, EADT_ERROR_INVALID_TYPE,
EADTERROR_OUT_OF_MEMORY, EADT_ERROR_OUT_OF_MEMORY,
}; };
struct ADT_Node struct ADT_Node
{ {
static ADT_Node* make_branch( AllocatorInfo backing, char const* name, b32 is_array );
static ADT_Node* make_leaf( AllocatorInfo backing, char const* name, u8 type );
static ADT_Node* set_arr( char const* name, AllocatorInfo backing );
static ADT_Node* set_flt( char const* name, f64 value );
static ADT_Node* set_int( char const* name, s64 value );
static ADT_Node* set_obj( char const* name, AllocatorInfo backing );
static ADT_Node* set_str( char const* name, char const* value );
static void swap( ADT_Node* node, ADT_Node* other );
ADT_Node* append_arr( char const* name );
ADT_Node* append_flt( char const* name, f64 value );
ADT_Node* append_int( char const* name, s64 value );
ADT_Node* append_obj( char const* name );
ADT_Node* append_str( char const* name, char const* value );
ADT_Node* destroy();
ADT_Node* query( char const* uri );
ADT_Node* find( char const* name, b32 deep_search );
ADT_Node* alloc();
ADT_Node* alloc_at( sw index );
ADT_Node* move_node( ADT_Node* new_parent );
ADT_Node* move_node_at( ADT_Node* new_parent, sw index );
char* parse_number( char* base );
void remove( ADT_Node* node );
ADT_Error str_to_number();
ADT_Error print_number( FileInfo* file );
ADT_Error print_string( FileInfo* file, char const* escapsed_chars, char const* escape_symbol );
#pragma region Layout
char const* name; char const* name;
ADT_Node* parent; struct ADT_Node* parent;
/* properties */ /* properties */
ADT_Type type; ADT_Type type : 4;
ADT_Props props; u8 props : 4;
#ifndef ZPL_PARSER_DISABLE_ANALYSIS #ifndef ZPL_PARSER_DISABLE_ANALYSIS
u8 cfg_mode : 1; u8 cfg_mode : 1;
u8 name_style : 2; u8 name_style : 2;
@ -2423,7 +2528,7 @@ namespace gen
union union
{ {
char const* string; char const* string;
struct ADT_Node* nodes; ///< zpl_array Array<ADT_Node> nodes; ///< zpl_array
struct struct
{ {
@ -2444,9 +2549,287 @@ namespace gen
#endif #endif
}; };
}; };
#pragma endregion Layout
}; };
/* ADT NODE LIMITS
* delimiter and assignment segment width is limited to 128 whitespace symbols each.
* real number limits decimal position to 128 places.
* real number exponent is limited to 64 digits.
*/
/**
* @brief Initialise an ADT object or array
*
* @param node
* @param backing Memory allocator used for descendants
* @param name Node's name
* @param is_array
* @return error code
*/
u8 adt_make_branch( ADT_Node* node, AllocatorInfo backing, char const* name, b32 is_array );
/**
* @brief Destroy an ADT branch and its descendants
*
* @param node
* @return error code
*/
u8 adt_destroy_branch( ADT_Node* node );
/**
* @brief Initialise an ADT leaf
*
* @param node
* @param name Node's name
* @param type Node's type (use zpl_adt_make_branch for container nodes)
* @return error code
*/
u8 adt_make_leaf( ADT_Node* node, char const* name, ADT_Type type );
/**
* @brief Fetch a node using provided URI string.
*
* This method uses a basic syntax to fetch a node from the ADT. The following features are available
* to retrieve the data:
*
* - "a/b/c" navigates through objects "a" and "b" to get to "c"
* - "arr/[foo=123]/bar" iterates over "arr" to find any object with param "foo" that matches the value "123", then gets its field called "bar"
* - "arr/3" retrieves the 4th element in "arr"
* - "arr/[apple]" retrieves the first element of value "apple" in "arr"
*
* @param node ADT node
* @param uri Locator string as described above
* @return zpl_adt_node*
*
* @see code/apps/examples/json_get.c
*/
ADT_Node* adt_query( ADT_Node* node, char const* uri );
/**
* @brief Find a field node within an object by the given name.
*
* @param node
* @param name
* @param deep_search Perform search recursively
* @return zpl_adt_node * node
*/
ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search );
/**
* @brief Allocate an unitialised node within a container at a specified index.
*
* @param parent
* @param index
* @return zpl_adt_node * node
*/
ADT_Node* adt_alloc_at( ADT_Node* parent, sw index );
/**
* @brief Allocate an unitialised node within a container.
*
* @param parent
* @return zpl_adt_node * node
*/
ADT_Node* adt_alloc( ADT_Node* parent );
/**
* @brief Move an existing node to a new container at a specified index.
*
* @param node
* @param new_parent
* @param index
* @return zpl_adt_node * node
*/
ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, sw index );
/**
* @brief Move an existing node to a new container.
*
* @param node
* @param new_parent
* @return zpl_adt_node * node
*/
ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent );
/**
* @brief Swap two nodes.
*
* @param node
* @param other_node
* @return
*/
void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node );
/**
* @brief Remove node from container.
*
* @param node
* @return
*/
void adt_remove_node( ADT_Node* node );
/**
* @brief Initialise a node as an object
*
* @param obj
* @param name
* @param backing
* @return
*/
b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing );
/**
* @brief Initialise a node as an array
*
* @param obj
* @param name
* @param backing
* @return
*/
b8 adt_set_arr( ADT_Node* obj, char const* name, AllocatorInfo backing );
/**
* @brief Initialise a node as a string
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_str( ADT_Node* obj, char const* name, char const* value );
/**
* @brief Initialise a node as a float
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_flt( ADT_Node* obj, char const* name, f64 value );
/**
* @brief Initialise a node as a signed integer
*
* @param obj
* @param name
* @param value
* @return
*/
b8 adt_set_int( ADT_Node* obj, char const* name, s64 value );
/**
* @brief Append a new node to a container as an object
*
* @param parent
* @param name
* @return*
*/
ADT_Node* adt_append_obj( ADT_Node* parent, char const* name );
/**
* @brief Append a new node to a container as an array
*
* @param parent
* @param name
* @return*
*/
ADT_Node* adt_append_arr( ADT_Node* parent, char const* name );
/**
* @brief Append a new node to a container as a string
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_str( ADT_Node* parent, char const* name, char const* value );
/**
* @brief Append a new node to a container as a float
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_flt( ADT_Node* parent, char const* name, f64 value );
/**
* @brief Append a new node to a container as a signed integer
*
* @param parent
* @param name
* @param value
* @return*
*/
ADT_Node* adt_append_int( ADT_Node* parent, char const* name, s64 value );
/* parser helpers */
/**
* @brief Parses a text and stores the result into an unitialised node.
*
* @param node
* @param base
* @return*
*/
char* adt_parse_number( ADT_Node* node, char* base );
/**
* @brief Parses a text and stores the result into an unitialised node.
* This function expects the entire input to be a number.
*
* @param node
* @param base
* @return*
*/
char* adt_parse_number_strict( ADT_Node* node, char* base_str );
/**
* @brief Parses and converts an existing string node into a number.
*
* @param node
* @return
*/
ADT_Error adt_str_to_number( ADT_Node* node );
/**
* @brief Parses and converts an existing string node into a number.
* This function expects the entire input to be a number.
*
* @param node
* @return
*/
ADT_Error adt_str_to_number_strict( ADT_Node* node );
/**
* @brief Prints a number into a file stream.
*
* The provided file handle can also be a memory mapped stream.
*
* @see zpl_file_stream_new
* @param file
* @param node
* @return
*/
ADT_Error adt_print_number( FileInfo* file, ADT_Node* node );
/**
* @brief Prints a string into a file stream.
*
* The provided file handle can also be a memory mapped stream.
*
* @see zpl_file_stream_new
* @param file
* @param node
* @param escaped_chars
* @param escape_symbol
* @return
*/
ADT_Error adt_print_string( FileInfo* file, ADT_Node* node, char const* escaped_chars, char const* escape_symbol );
#pragma endregion ADT #pragma endregion ADT
#pragma region CSV #pragma region CSV

View File

@ -1,9 +1,9 @@
#pragma once #if gen_time
#ifdef gen_time
#define GEN_FEATURE_PARSING #define GEN_FEATURE_PARSING
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES #define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#include "gen.hpp" #include "gen.hpp"
using namespace gen; using namespace gen;
@ -91,7 +91,7 @@ Code gen_SOA( CodeStruct struct_def, s32 num_entries = 0 )
} }
)); ));
String content = String::make( Memory::GlobalAllocator, "return\n{\n" ); String content = String::make( GlobalAllocator, "return\n{\n" );
for ( CodeVar member : vars ) for ( CodeVar member : vars )
{ {
@ -114,4 +114,31 @@ Code gen_SOA( CodeStruct struct_def, s32 num_entries = 0 )
return soa; return soa;
} }
void check_SOA()
{
gen::init();
Builder soa_test; soa_test.open( "SOA.gen.hpp" );
soa_test.print( parse_using( code(
using u16 = unsigned short;
)));
soa_test.print( def_include( txt_StrC("gen.hpp")));
soa_test.print( def_using_namespace( name(gen) ) );
soa_test.print( gen_SOA(
parse_struct( code(
struct TestStruct
{
u8 A;
u16 B;
u32 C;
u64 D;
};
))
));
soa_test.write();
gen::deinit();
}
#endif #endif

View File

@ -1,5 +1,11 @@
#define GEN_FEATURE_PARSING
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#include "gen.cpp" #include "gen.cpp"
#include "sanity.cpp" #include "sanity.cpp"
#include "SOA.cpp"
#if gen_time #if gen_time
int gen_main() int gen_main()
@ -9,6 +15,8 @@ int gen_main()
check_sanity(); check_sanity();
check_SOA();
return 0; return 0;
} }
#endif #endif