mirror of
https://github.com/Ed94/gencpp.git
synced 2025-07-01 11:21:04 -07:00
renamed parsed and upfront dirs to lowercase
This commit is contained in:
294
test/parsed/Array.Parsed.hpp
Normal file
294
test/parsed/Array.Parsed.hpp
Normal file
@ -0,0 +1,294 @@
|
||||
#pragma once
|
||||
|
||||
#if GEN_TIME
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#define GEN_BENCHMARK
|
||||
#include "gen.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
Code gen__array_base()
|
||||
{
|
||||
return parse_global_body( code(
|
||||
struct ArrayHeader
|
||||
{
|
||||
AllocatorInfo Allocator;
|
||||
uw Capacity;
|
||||
uw Num;
|
||||
};
|
||||
|
||||
static inline uw array_grow_formula( uw value )
|
||||
{
|
||||
return 2 * value * 8;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Code gen__array( StrC type )
|
||||
{
|
||||
StrC name;
|
||||
{
|
||||
char const* name_str = str_fmt_buf( "Array_%s\0", type.Ptr );
|
||||
s32 name_len = str_len( name_str );
|
||||
|
||||
name = { name_len, name_str };
|
||||
};
|
||||
|
||||
CodeStruct array = parse_struct( token_fmt( "ArrayType", name, "type", type,
|
||||
stringize(
|
||||
struct <ArrayType>
|
||||
{
|
||||
using Header = ArrayHeader;
|
||||
using Type = <type>;
|
||||
|
||||
static constexpr auto grow_formula = &array_grow_formula;
|
||||
|
||||
static
|
||||
<ArrayType> init( AllocatorInfo allocator )
|
||||
{
|
||||
return init_reserve( allocator, grow_formula(0) );
|
||||
}
|
||||
|
||||
static
|
||||
<ArrayType> init_reserve( AllocatorInfo allocator, sw capacity )
|
||||
{
|
||||
Header* header = rcast( Header*, alloc( allocator, sizeof(Header) + sizeof(Type) ));
|
||||
|
||||
if ( header == nullptr )
|
||||
return { nullptr };
|
||||
|
||||
header->Allocator = allocator;
|
||||
header->Capacity = capacity;
|
||||
header->Num = 0;
|
||||
|
||||
return { rcast( Type*, header + 1) };
|
||||
}
|
||||
|
||||
bool append( Type value )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
if ( header.Num == header.Capacity )
|
||||
{
|
||||
if ( ! grow( header.Capacity ))
|
||||
return false;
|
||||
}
|
||||
|
||||
Data[ header.Num ] = value;
|
||||
header.Num++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Type& back( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
return Data[ header.Num - 1 ];
|
||||
}
|
||||
|
||||
void clear( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
header.Num = 0;
|
||||
}
|
||||
|
||||
bool fill( uw begin, uw end, Type value )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
if ( begin < 0 || end >= header.Num )
|
||||
return false;
|
||||
|
||||
for ( sw idx = begin; idx < end; idx++ )
|
||||
{
|
||||
Data[ idx ] = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void free( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
gen::free( header.Allocator, &header );
|
||||
}
|
||||
|
||||
Header& get_header( void )
|
||||
{
|
||||
return *( reinterpret_cast< Header* >( Data ) - 1 );
|
||||
}
|
||||
|
||||
bool grow( uw min_capacity )
|
||||
{
|
||||
Header& header = get_header();
|
||||
uw new_capacity = grow_formula( header.Capacity );
|
||||
|
||||
if ( new_capacity < min_capacity )
|
||||
new_capacity = 8;
|
||||
|
||||
return set_capacity( new_capacity );
|
||||
}
|
||||
|
||||
uw num( void )
|
||||
{
|
||||
return get_header().Num;
|
||||
}
|
||||
|
||||
bool pop( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
GEN_ASSERT( header.Num > 0 );
|
||||
header.Num--;
|
||||
}
|
||||
|
||||
void remove_at( uw idx )
|
||||
{
|
||||
Header* header = &get_header();
|
||||
GEN_ASSERT( idx < header->Num );
|
||||
|
||||
mem_move( header + idx, header + idx + 1, sizeof( Type ) * ( header->Num - idx - 1 ) );
|
||||
header->Num--;
|
||||
}
|
||||
|
||||
bool reserve( uw new_capacity )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
if ( header.Capacity < new_capacity )
|
||||
return set_capacity( new_capacity );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool resize( uw num )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
if ( num > header.Capacity )
|
||||
{
|
||||
if ( ! grow( header.Capacity ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
header.Num = num;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_capacity( uw new_capacity )
|
||||
{
|
||||
Header& header = get_header();
|
||||
|
||||
if ( new_capacity == header.Capacity )
|
||||
return true;
|
||||
|
||||
if ( new_capacity < header.Num )
|
||||
header.Num = new_capacity;
|
||||
|
||||
sw size = sizeof( Header ) + sizeof( Type ) * new_capacity;
|
||||
Header* new_header = rcast( Header*, alloc( header.Allocator, size ) );
|
||||
|
||||
if ( new_header == nullptr )
|
||||
return false;
|
||||
|
||||
mem_move( new_header, &header, sizeof( Header ) + sizeof( Type ) * header.Num );
|
||||
|
||||
new_header->Allocator = header.Allocator;
|
||||
new_header->Num = header.Num;
|
||||
new_header->Capacity = new_capacity;
|
||||
|
||||
gen::free( header.Allocator, &header );
|
||||
|
||||
Data = ( Type* )new_header + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
Type* Data;
|
||||
|
||||
operator Type*()
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
};
|
||||
)
|
||||
));
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
struct GenArrayRequest
|
||||
{
|
||||
StrC Dependency;
|
||||
StrC Type;
|
||||
};
|
||||
Array<GenArrayRequest> GenArrayRequests;
|
||||
|
||||
void gen__array_request( StrC type, StrC dep = {} )
|
||||
{
|
||||
do_once_start
|
||||
GenArrayRequests = Array<GenArrayRequest>::init( GlobalAllocator );
|
||||
do_once_end
|
||||
|
||||
// Make sure we don't already have a request for the type.
|
||||
for ( sw idx = 0; idx < GenArrayRequests.num(); ++idx )
|
||||
{
|
||||
StrC const reqest_type = GenArrayRequests[ idx ].Type;
|
||||
|
||||
if ( reqest_type.Len != type.Len )
|
||||
continue;
|
||||
|
||||
if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
GenArrayRequest request = { dep, type };
|
||||
GenArrayRequests.append( request );
|
||||
}
|
||||
#define gen_array( type ) gen__array_request( code(type) )
|
||||
|
||||
u32 gen_array_file()
|
||||
{
|
||||
Builder
|
||||
gen_array_file;
|
||||
gen_array_file.open( "array.Parsed.gen.hpp" );
|
||||
|
||||
Code include_gen = def_include( txt_StrC("gen.hpp") );
|
||||
gen_array_file.print( include_gen );
|
||||
|
||||
gen_array_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
Code array_base = gen__array_base();
|
||||
gen_array_file.print( array_base );
|
||||
|
||||
GenArrayRequest* current = GenArrayRequests;
|
||||
s32 left = GenArrayRequests.num();
|
||||
while (left--)
|
||||
{
|
||||
GenArrayRequest const& request = * current;
|
||||
|
||||
Code generated_array = gen__array( request.Type );
|
||||
|
||||
if ( request.Dependency )
|
||||
{
|
||||
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
|
||||
s32 cmt_len = str_len( cmt_str );
|
||||
|
||||
Code cmt = def_comment( { cmt_len, cmt_str } );
|
||||
Code include = def_include( request.Dependency );
|
||||
|
||||
gen_array_file.print( cmt );
|
||||
gen_array_file.print( include );
|
||||
}
|
||||
|
||||
gen_array_file.print( generated_array );
|
||||
current++;
|
||||
}
|
||||
|
||||
gen_array_file.write();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
205
test/parsed/Buffer.Parsed.hpp
Normal file
205
test/parsed/Buffer.Parsed.hpp
Normal file
@ -0,0 +1,205 @@
|
||||
#pragma once
|
||||
|
||||
#if GEN_TIME
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#define GEN_BENCHMARK
|
||||
#include "gen.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
Code gen__buffer_base()
|
||||
{
|
||||
return parse_global_body( code(
|
||||
struct BufferHeader
|
||||
{
|
||||
AllocatorInfo Backing;
|
||||
uw Capacity;
|
||||
uw Num;
|
||||
};
|
||||
));
|
||||
}
|
||||
|
||||
Code gen__buffer( StrC type )
|
||||
{
|
||||
StrC name;
|
||||
{
|
||||
char const* name_str = str_fmt_buf( "Buffer_%s\0", type.Ptr );
|
||||
s32 name_len = str_len( name_str );
|
||||
|
||||
name = { name_len, name_str };
|
||||
};
|
||||
|
||||
Code buffer = parse_struct( token_fmt( "BufferName", name, "type", type,
|
||||
stringize(
|
||||
struct <BufferName>
|
||||
{
|
||||
using Header = BufferHeader;
|
||||
using Type = <type>;
|
||||
|
||||
static <BufferName> init( AllocatorInfo allocator, sw capacity )
|
||||
{
|
||||
Header* header = rcast( Header*, alloc( allocator, sizeof( Header ) + capacity * sizeof( Type ) ) );
|
||||
|
||||
if ( header == nullptr )
|
||||
return { nullptr };
|
||||
|
||||
header->Backing = allocator;
|
||||
header->Capacity = capacity;
|
||||
header->Num = 0;
|
||||
|
||||
return { rcast( Type*, header + 1 ) };
|
||||
}
|
||||
|
||||
<BufferName> init( AllocatorInfo allocator, <BufferName> other )
|
||||
{
|
||||
Header& other_header = other.get_header();
|
||||
Header* header = rcast( Header*, alloc( allocator, sizeof( Header ) + other_header.Capacity * sizeof( Type ) ) );
|
||||
|
||||
if ( header == nullptr )
|
||||
return { nullptr };
|
||||
|
||||
header->Backing = allocator;
|
||||
header->Capacity = other_header.Capacity;
|
||||
header->Num = other_header.Num;
|
||||
|
||||
mem_copy( header + 1, other.Data, other_header.Num * sizeof( Type ) );
|
||||
|
||||
return { rcast( Type*, header + 1 ) };
|
||||
}
|
||||
|
||||
void append( Type value )
|
||||
{
|
||||
Header& header = get_header();
|
||||
Data[ header.Num ] = value;
|
||||
header.Num++;
|
||||
}
|
||||
|
||||
void append( Type* values, sw num )
|
||||
{
|
||||
Header& header = get_header();
|
||||
GEN_ASSERT( header.Num + num <= header.Capacity);
|
||||
|
||||
mem_copy( Data + header.Num, values, num * sizeof( Type ) );
|
||||
header.Num += num;
|
||||
}
|
||||
|
||||
void clear( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
header.Num = 0;
|
||||
}
|
||||
|
||||
Type& end( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
return Data[ header.Num - 1 ];
|
||||
}
|
||||
|
||||
void free( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
gen::free( header.Backing, &header );
|
||||
}
|
||||
|
||||
Header& get_header( void )
|
||||
{
|
||||
return *( rcast( Header*, Data ) - 1 );
|
||||
}
|
||||
|
||||
sw num( void )
|
||||
{
|
||||
return get_header().Num;
|
||||
}
|
||||
|
||||
void wipe( void )
|
||||
{
|
||||
Header& header = get_header();
|
||||
header.Num = 0;
|
||||
mem_set( Data, 0, header.Capacity * sizeof( Type ) );
|
||||
}
|
||||
|
||||
operator Type*()
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
|
||||
Type* Data;
|
||||
};
|
||||
)
|
||||
));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
struct GenBufferRequest
|
||||
{
|
||||
StrC Dependency;
|
||||
StrC Type;
|
||||
};
|
||||
Array<GenBufferRequest> GenBufferRequests;
|
||||
|
||||
void gen__buffer_request( StrC type, StrC dep = {} )
|
||||
{
|
||||
do_once_start
|
||||
GenBufferRequests = Array<GenBufferRequest>::init( GlobalAllocator );
|
||||
do_once_end
|
||||
|
||||
// Make sure we don't already have a request for the type.
|
||||
for ( sw idx = 0; idx < GenBufferRequests.num(); ++idx )
|
||||
{
|
||||
StrC const reqest_type = GenBufferRequests[ idx ].Type;
|
||||
|
||||
if ( reqest_type.Len != type.Len )
|
||||
continue;
|
||||
|
||||
if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
GenBufferRequest request = { dep, type };
|
||||
GenBufferRequests.append( request );
|
||||
}
|
||||
#define gen_buffer( type ) gen__buffer_request( code(type) )
|
||||
|
||||
u32 gen_buffer_file()
|
||||
{
|
||||
Builder
|
||||
gen_buffer_file;
|
||||
gen_buffer_file.open( "buffer.Parsed.gen.hpp" );
|
||||
|
||||
gen_buffer_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_buffer_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
gen_buffer_file.print( gen__buffer_base() );
|
||||
|
||||
GenBufferRequest* current = GenBufferRequests;
|
||||
s32 left = GenBufferRequests.num();
|
||||
while (left--)
|
||||
{
|
||||
GenBufferRequest const& request = * current;
|
||||
|
||||
Code generated_buffer = gen__buffer( current->Type );
|
||||
|
||||
if ( request.Dependency )
|
||||
{
|
||||
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
|
||||
s32 cmt_len = str_len( cmt_str );
|
||||
|
||||
Code cmt = def_comment( { cmt_len, cmt_str } );
|
||||
Code include = def_include( request.Dependency );
|
||||
|
||||
gen_buffer_file.print( cmt );
|
||||
gen_buffer_file.print( include );
|
||||
}
|
||||
|
||||
gen_buffer_file.print( generated_buffer );
|
||||
current++;
|
||||
}
|
||||
|
||||
gen_buffer_file.write();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // GEN_TIME
|
359
test/parsed/HashTable.Parsed.hpp
Normal file
359
test/parsed/HashTable.Parsed.hpp
Normal file
@ -0,0 +1,359 @@
|
||||
#pragma once
|
||||
|
||||
#if GEN_TIME
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#define GEN_BENCHMARK
|
||||
#include "gen.hpp"
|
||||
#include "Array.Parsed.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
Code gen__hashtable_base()
|
||||
{
|
||||
return parse_global_body( code(
|
||||
struct HashTable_FindResult
|
||||
{
|
||||
sw HashIndex;
|
||||
sw PrevIndex;
|
||||
sw EntryIndex;
|
||||
};
|
||||
));
|
||||
}
|
||||
|
||||
Code gen__hashtable( StrC type )
|
||||
{
|
||||
StringCached name;
|
||||
{
|
||||
char const* name_str = str_fmt_buf( "HashTable_%s", type.Ptr );
|
||||
s32 len = str_len( name_str );
|
||||
|
||||
name = get_cached_string({ len, name_str });
|
||||
}
|
||||
|
||||
Code ht_entry = parse_struct( token_fmt( "HashTableName", (StrC)name, "type", type,
|
||||
stringize(
|
||||
struct <HashTableName>_Entry
|
||||
{
|
||||
u64 Key;
|
||||
sw Next;
|
||||
<type> Value;
|
||||
};
|
||||
)
|
||||
));
|
||||
|
||||
StringCached ht_entry_name = get_cached_string( token_fmt( "HashTableName", (StrC)name, "<HashTableName>_Entry" ));
|
||||
|
||||
Code array_ht_entry = gen__array( ht_entry_name );
|
||||
|
||||
Code hashtable = parse_struct( token_fmt( "HashTableName", (StrC)name, "type", type,
|
||||
stringize(
|
||||
struct <HashTableName>
|
||||
{
|
||||
using Type = <type>;
|
||||
using Entry = <HashTableName>_Entry;
|
||||
using Array_Entry = Array_<HashTableName>_Entry;
|
||||
using FindResult = HashTable_FindResult;
|
||||
using MapProc = void ( * )( u64 key, Type value );
|
||||
using MapMutProc = void ( * )( u64 key, Type* value );
|
||||
|
||||
static
|
||||
<HashTableName> init( AllocatorInfo allocator )
|
||||
{
|
||||
<HashTableName>
|
||||
result = { 0 };
|
||||
result.Hashes = Array_sw ::init( allocator );
|
||||
result.Entries = Array_Entry::init( allocator );
|
||||
return result;
|
||||
}
|
||||
|
||||
void clear( void )
|
||||
{
|
||||
for ( s32 idx = 0; idx < Hashes.num(); idx++ )
|
||||
Hashes[ idx ] = -1;
|
||||
|
||||
Entries.clear();
|
||||
}
|
||||
|
||||
void destroy( void )
|
||||
{
|
||||
if ( Hashes )
|
||||
Hashes.free();
|
||||
if ( Entries )
|
||||
Entries.free();
|
||||
}
|
||||
|
||||
Type* get( u64 key )
|
||||
{
|
||||
sw idx = find( key ).EntryIndex;
|
||||
|
||||
if ( idx > 0 )
|
||||
return &Entries[ idx ].Value;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void grow( void )
|
||||
{
|
||||
sw new_num = array_grow_formula( Entries.num() );
|
||||
|
||||
rehash( new_num );
|
||||
}
|
||||
|
||||
void map( MapProc map_proc )
|
||||
{
|
||||
GEN_ASSERT_NOT_NULL( map_proc );
|
||||
|
||||
for ( sw idx = 0; idx < Entries.num(); idx++ )
|
||||
{
|
||||
map_proc( Entries[ idx ].Key, Entries[ idx ].Value );
|
||||
}
|
||||
}
|
||||
|
||||
void map_mut( MapMutProc map_proc )
|
||||
{
|
||||
GEN_ASSERT_NOT_NULL( map_proc );
|
||||
|
||||
for ( sw idx = 0; idx < Entries.num(); idx++ )
|
||||
{
|
||||
map_proc( Entries[ idx ].Key, &Entries[ idx ].Value );
|
||||
}
|
||||
}
|
||||
|
||||
void rehash( sw new_num )
|
||||
{
|
||||
sw idx;
|
||||
sw last_added_index;
|
||||
HashTable_u32 new_ht = HashTable_u32::init( Hashes.get_header().Allocator );
|
||||
|
||||
new_ht.Hashes.resize( new_num );
|
||||
new_ht.Entries.reserve( new_ht.Hashes.num() );
|
||||
|
||||
for ( idx = 0; idx < new_ht.Hashes.num(); ++idx )
|
||||
new_ht.Hashes[ idx ] = -1;
|
||||
|
||||
for ( idx = 0; idx < Entries.num(); ++idx )
|
||||
{
|
||||
Entry& entry = Entries[ idx ];
|
||||
FindResult find_result;
|
||||
|
||||
if ( new_ht.Hashes.num() == 0 )
|
||||
new_ht.grow();
|
||||
|
||||
entry = Entries[ idx ];
|
||||
find_result = new_ht.find( entry.Key );
|
||||
last_added_index = new_ht.add_entry( entry.Key );
|
||||
|
||||
if ( find_result.PrevIndex < 0 )
|
||||
new_ht.Hashes[ find_result.HashIndex ] = last_added_index;
|
||||
|
||||
else
|
||||
new_ht.Entries[ find_result.PrevIndex ].Next = last_added_index;
|
||||
|
||||
new_ht.Entries[ last_added_index ].Next = find_result.EntryIndex;
|
||||
new_ht.Entries[ last_added_index ].Value = entry.Value;
|
||||
}
|
||||
|
||||
destroy();
|
||||
|
||||
Hashes = new_ht.Hashes;
|
||||
Entries = new_ht.Entries;
|
||||
}
|
||||
|
||||
void rehash_fast( void )
|
||||
{
|
||||
sw idx;
|
||||
|
||||
for ( idx = 0; idx < Entries.num(); idx++ )
|
||||
Entries[ idx ].Next = -1;
|
||||
|
||||
for ( idx = 0; idx < Hashes.num(); idx++ )
|
||||
Hashes[ idx ] = -1;
|
||||
|
||||
for ( idx = 0; idx < Entries.num(); idx++ )
|
||||
{
|
||||
Entry* entry;
|
||||
FindResult find_result;
|
||||
}
|
||||
}
|
||||
|
||||
void remove( u64 key )
|
||||
{
|
||||
FindResult find_result = find( key );
|
||||
|
||||
if ( find_result.EntryIndex >= 0 )
|
||||
{
|
||||
Entries.remove_at( find_result.EntryIndex );
|
||||
rehash_fast();
|
||||
}
|
||||
}
|
||||
|
||||
void remove_entry( sw idx )
|
||||
{
|
||||
Entries.remove_at( idx );
|
||||
}
|
||||
|
||||
void set( u64 key, Type value )
|
||||
{
|
||||
sw idx;
|
||||
FindResult find_result;
|
||||
|
||||
if ( Hashes.num() == 0 )
|
||||
grow();
|
||||
|
||||
find_result = find( key );
|
||||
|
||||
if ( find_result.EntryIndex >= 0 )
|
||||
{
|
||||
idx = find_result.EntryIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = add_entry( key );
|
||||
|
||||
if ( find_result.PrevIndex >= 0 )
|
||||
{
|
||||
Entries[ find_result.PrevIndex ].Next = idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
Hashes[ find_result.HashIndex ] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
Entries[ idx ].Value = value;
|
||||
|
||||
if ( full() )
|
||||
grow();
|
||||
}
|
||||
|
||||
sw slot( u64 key )
|
||||
{
|
||||
for ( sw idx = 0; idx < Hashes.num(); ++idx )
|
||||
if ( Hashes[ idx ] == key )
|
||||
return idx;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Array_sw Hashes;
|
||||
Array_Entry Entries;
|
||||
|
||||
protected:
|
||||
|
||||
sw add_entry( u64 key )
|
||||
{
|
||||
sw idx;
|
||||
Entry entry = { key, -1 };
|
||||
idx = Entries.num();
|
||||
Entries.append( entry );
|
||||
return idx;
|
||||
}
|
||||
|
||||
HashTable_FindResult find( u64 key )
|
||||
{
|
||||
FindResult result = { -1, -1, -1 };
|
||||
if ( Hashes.num() > 0 )
|
||||
{
|
||||
result.HashIndex = key % Hashes.num();
|
||||
result.EntryIndex = Hashes[ result.HashIndex ];
|
||||
|
||||
while ( result.EntryIndex >= 0 )
|
||||
{
|
||||
if ( Entries[ result.EntryIndex ].Key == key )
|
||||
break;
|
||||
|
||||
result.PrevIndex = result.EntryIndex;
|
||||
result.EntryIndex = Entries[ result.EntryIndex ].Next;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
b32 full( void )
|
||||
{
|
||||
return 0.75f * Hashes.num() < Entries.num();
|
||||
}
|
||||
};
|
||||
)
|
||||
));
|
||||
|
||||
return def_global_body( args( ht_entry, array_ht_entry, hashtable ));
|
||||
}
|
||||
|
||||
struct GenHashTableRequest
|
||||
{
|
||||
StrC Dependency;
|
||||
StrC Type;
|
||||
};
|
||||
Array<GenHashTableRequest> GenHashTableRequests;
|
||||
|
||||
void gen__hashtable_request( StrC type, StrC dep = {} )
|
||||
{
|
||||
do_once_start
|
||||
GenHashTableRequests = Array<GenHashTableRequest>::init( GlobalAllocator );
|
||||
|
||||
gen_array( sw );
|
||||
do_once_end
|
||||
|
||||
// Make sure we don't already have a request for the type.
|
||||
for ( sw idx = 0; idx < GenHashTableRequests.num(); ++idx )
|
||||
{
|
||||
StrC const reqest_type = GenHashTableRequests[ idx ].Type;
|
||||
|
||||
if ( reqest_type.Len != type.Len )
|
||||
continue;
|
||||
|
||||
if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
GenHashTableRequest request = { dep, type };
|
||||
GenHashTableRequests.append( request );
|
||||
}
|
||||
#define gen_hashtable( type ) gen__hashtable_request( code(type) )
|
||||
|
||||
u32 gen_hashtable_file()
|
||||
{
|
||||
Builder
|
||||
gen_hashtable_file;
|
||||
gen_hashtable_file.open( "hashtable.Parsed.gen.hpp" );
|
||||
|
||||
gen_hashtable_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("Array.Parsed.hpp")) );
|
||||
gen_hashtable_file.print( def_include( txt_StrC("array.Parsed.gen.hpp")) );
|
||||
|
||||
gen_hashtable_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
gen_hashtable_file.print( gen__hashtable_base());
|
||||
|
||||
GenHashTableRequest* current = GenHashTableRequests;
|
||||
s32 left = GenHashTableRequests.num();
|
||||
while (left--)
|
||||
{
|
||||
GenHashTableRequest const& request = * current;
|
||||
|
||||
Code generated_buffer = gen__hashtable( current->Type );
|
||||
|
||||
if ( request.Dependency )
|
||||
{
|
||||
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
|
||||
s32 cmt_len = str_len( cmt_str );
|
||||
|
||||
Code cmt = def_comment( { cmt_len, cmt_str } );
|
||||
Code include = def_include( request.Dependency );
|
||||
|
||||
gen_hashtable_file.print( cmt );
|
||||
gen_hashtable_file.print( include );
|
||||
}
|
||||
|
||||
gen_hashtable_file.print( generated_buffer );
|
||||
current++;
|
||||
}
|
||||
|
||||
gen_hashtable_file.write();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // GEN_TIME
|
175
test/parsed/Ring.Parsed.hpp
Normal file
175
test/parsed/Ring.Parsed.hpp
Normal file
@ -0,0 +1,175 @@
|
||||
#pragma once
|
||||
|
||||
#if GEN_TIME
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#define GEN_BENCHMARK
|
||||
#include "gen.hpp"
|
||||
#include "Buffer.Parsed.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
Code gen__ring( StrC type )
|
||||
{
|
||||
static Code t_allocator_info = def_type( name(AllocatorInfo) );
|
||||
|
||||
StringCached name;
|
||||
{
|
||||
char const* name_str = str_fmt_buf( "Ring_%s\0", type.Ptr );
|
||||
s32 name_len = str_len( name_str );
|
||||
|
||||
name = get_cached_string({ name_len, name_str });
|
||||
};
|
||||
|
||||
StrC buffer_name = to_StrC( str_fmt_buf( "Buffer_%s", type.Ptr ));
|
||||
|
||||
Code ring = parse_struct( token_fmt( "RingName", (StrC)name, "type", type, "BufferName", buffer_name,
|
||||
stringize(
|
||||
struct <RingName>
|
||||
{
|
||||
using Type = <type>;
|
||||
|
||||
static <RingName> init( AllocatorInfo allocator, uw max_size )
|
||||
{
|
||||
<RingName> result = { 0 };
|
||||
|
||||
result.Backing = allocator;
|
||||
result.Buffer = <BufferName>::init( allocator, max_size + 1 );
|
||||
|
||||
if ( result.Buffer == nullptr )
|
||||
return { nullptr };
|
||||
|
||||
result.Capacity = max_size + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void append( s16 value )
|
||||
{
|
||||
Buffer[ Head ] = value;
|
||||
Head = ( Head + 1 ) % Capacity;
|
||||
if ( Head == Tail )
|
||||
Tail = ( Tail + 1 ) % Capacity;
|
||||
}
|
||||
|
||||
inline void append( Type* values, sw num )
|
||||
{
|
||||
for ( sw idx = 0; idx < num; idx++ )
|
||||
append( values[ idx ] );
|
||||
}
|
||||
|
||||
bool empty( void )
|
||||
{
|
||||
return Head == Tail;
|
||||
}
|
||||
|
||||
void free( void )
|
||||
{
|
||||
Buffer.free();
|
||||
}
|
||||
|
||||
bool full( void )
|
||||
{
|
||||
return ( Head + 1 ) % Capacity == Tail;
|
||||
}
|
||||
|
||||
Type& get( void )
|
||||
{
|
||||
Type& data = Buffer[ Tail ];
|
||||
Tail = ( Tail + 1 ) % Capacity;
|
||||
return data;
|
||||
}
|
||||
|
||||
void wipe( void )
|
||||
{
|
||||
Head = 0;
|
||||
Tail = 0;
|
||||
Buffer.wipe();
|
||||
}
|
||||
|
||||
AllocatorInfo Backing;
|
||||
uw Capacity;
|
||||
uw Head;
|
||||
uw Tail;
|
||||
<BufferName> Buffer;
|
||||
};
|
||||
)
|
||||
));
|
||||
|
||||
return ring;
|
||||
}
|
||||
|
||||
struct GenRingRequest
|
||||
{
|
||||
StrC Dependency;
|
||||
StrC Type;
|
||||
};
|
||||
Array<GenRingRequest> GenRingRequests;
|
||||
|
||||
void gen__ring_request( StrC type, StrC dep = {} )
|
||||
{
|
||||
do_once_start
|
||||
GenRingRequests = Array<GenRingRequest>::init( GlobalAllocator );
|
||||
do_once_end
|
||||
|
||||
// Make sure we don't already have a request for the type.
|
||||
for ( sw idx = 0; idx < GenRingRequests.num(); ++idx )
|
||||
{
|
||||
StrC const reqest_type = GenRingRequests[ idx ].Type;
|
||||
|
||||
if ( reqest_type.Len != type.Len )
|
||||
continue;
|
||||
|
||||
if ( str_compare( reqest_type.Ptr, type.Ptr, reqest_type.Len ) == 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
// Ring definition depends on a array and buffer definition.
|
||||
gen__buffer_request( type, dep );
|
||||
|
||||
GenRingRequest request = { dep, type };
|
||||
GenRingRequests.append( request );
|
||||
}
|
||||
#define gen_ring( type ) gen__ring_request( code(type) )
|
||||
|
||||
u32 gen_ring_file()
|
||||
{
|
||||
Builder
|
||||
gen_ring_file;
|
||||
gen_ring_file.open( "ring.Parsed.gen.hpp" );
|
||||
|
||||
gen_ring_file.print( def_include( txt_StrC("gen.hpp")) );
|
||||
gen_ring_file.print( def_include( txt_StrC("buffer.Parsed.gen.hpp")) );
|
||||
// gen_ring_file.print( gen__ring_base() );
|
||||
|
||||
gen_ring_file.print( def_using_namespace( name(gen)));
|
||||
|
||||
GenRingRequest* current = GenRingRequests;
|
||||
s32 left = GenRingRequests.num();
|
||||
while (left--)
|
||||
{
|
||||
GenRingRequest const& request = * current;
|
||||
|
||||
Code generated_ring = gen__ring( current->Type );
|
||||
|
||||
if ( request.Dependency )
|
||||
{
|
||||
char const* cmt_str = str_fmt_buf( "// Dependency for %s type", request.Type );
|
||||
s32 cmt_len = str_len( cmt_str );
|
||||
|
||||
Code cmt = def_comment( { cmt_len, cmt_str } );
|
||||
Code include = def_include( request.Dependency );
|
||||
|
||||
gen_ring_file.print( cmt );
|
||||
gen_ring_file.print( include );
|
||||
}
|
||||
|
||||
gen_ring_file.print( generated_ring );
|
||||
current++;
|
||||
}
|
||||
|
||||
gen_ring_file.write();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // GEN_TIME
|
344
test/parsed/Sanity.Parsed.hpp
Normal file
344
test/parsed/Sanity.Parsed.hpp
Normal file
@ -0,0 +1,344 @@
|
||||
#pragma once
|
||||
#ifdef GEN_TIME
|
||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||
#define GEN_EXPOSE_BACKEND
|
||||
#define GEN_BENCHMARK
|
||||
#include "gen.hpp"
|
||||
|
||||
using namespace gen;
|
||||
|
||||
u32 gen_sanity()
|
||||
{
|
||||
Builder
|
||||
gen_sanity_file;
|
||||
gen_sanity_file.open("./sanity.Parsed.gen.hpp");
|
||||
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
"The following will show a series of base cases for the gen parsed api.\n"
|
||||
)));
|
||||
|
||||
// Typedef
|
||||
{
|
||||
CodeTypedef u8_typedef = parse_typedef( code(
|
||||
typedef unsigned char u8;
|
||||
));
|
||||
|
||||
gen_sanity_file.print(u8_typedef);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Class
|
||||
{
|
||||
CodeClass fwd = parse_class( code(
|
||||
class TestEmptyClass;
|
||||
));
|
||||
|
||||
CodeClass empty_body = parse_class( code(
|
||||
class TestEmptyClass
|
||||
{};
|
||||
));
|
||||
|
||||
empty_body->Body.append( def_comment( txt_StrC("Empty class body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(empty_body);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Enum
|
||||
{
|
||||
CodeEnum fwd = parse_enum( code(
|
||||
enum ETestEnum : u8;
|
||||
));
|
||||
|
||||
CodeEnum def = parse_enum( code(
|
||||
enum ETestEnum : u8
|
||||
{
|
||||
A,
|
||||
B,
|
||||
C
|
||||
};
|
||||
));
|
||||
|
||||
CodeEnum fwd_enum_class = parse_enum( code(
|
||||
enum class ETestEnumClass : u8;
|
||||
));
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
gen_sanity_file.print(fwd_enum_class);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// External Linkage
|
||||
{
|
||||
CodeComment empty_comment = def_comment( txt_StrC("Empty external linkage") );
|
||||
|
||||
CodeExtern c_extern = parse_extern_link( code(
|
||||
extern "C"
|
||||
{
|
||||
};
|
||||
));
|
||||
|
||||
c_extern->Body.append( empty_comment );
|
||||
|
||||
gen_sanity_file.print(c_extern);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Friend
|
||||
{
|
||||
CodeClass fwd = parse_class( code(
|
||||
class TestFriendClass;
|
||||
));
|
||||
|
||||
CodeClass def = parse_class( code(
|
||||
class TestFriend
|
||||
{
|
||||
friend class TestFriendClass;
|
||||
};
|
||||
));
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Function
|
||||
{
|
||||
CodeFn fwd = parse_function( code(
|
||||
void test_function();
|
||||
));
|
||||
|
||||
CodeFn def = parse_function( code(
|
||||
void test_function()
|
||||
{
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty function body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Namespace
|
||||
{
|
||||
CodeNamespace def = parse_namespace( code(
|
||||
namespace TestNamespace
|
||||
{
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty namespace body") ) );
|
||||
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Operator
|
||||
{
|
||||
CodeEnum bitflagtest = parse_enum( code(
|
||||
enum class EBitFlagTest : u8
|
||||
{
|
||||
A = 1 << 0,
|
||||
B = 1 << 1,
|
||||
C = 1 << 2
|
||||
};
|
||||
));
|
||||
|
||||
CodeOperator op_fwd = parse_operator( code(
|
||||
EBitFlagTest operator | ( EBitFlagTest a, EBitFlagTest b );
|
||||
));
|
||||
|
||||
CodeOperator op_or = parse_operator( code(
|
||||
EBitFlagTest operator | ( EBitFlagTest a, EBitFlagTest b )
|
||||
{
|
||||
return EBitFlagTest( (u8)a | (u8)b );
|
||||
}
|
||||
));
|
||||
|
||||
gen_sanity_file.print(bitflagtest);
|
||||
gen_sanity_file.print(op_fwd);
|
||||
gen_sanity_file.print(op_or);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Operator cast
|
||||
{
|
||||
CodeOpCast op_ptr = parse_operator_cast( code(
|
||||
operator u8* ();
|
||||
));
|
||||
|
||||
CodeClass class_def = parse_class( code(
|
||||
class TestClass
|
||||
{
|
||||
};
|
||||
));
|
||||
|
||||
class_def->Body.append( op_ptr );
|
||||
|
||||
gen_sanity_file.print(class_def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Parameters
|
||||
{
|
||||
CodeFn fwd = parse_function( code(
|
||||
void test_function_param( int a );
|
||||
));
|
||||
|
||||
CodeFn def = parse_function( code(
|
||||
void test_function_param2( int a, int b )
|
||||
{
|
||||
}
|
||||
));
|
||||
|
||||
def->Body.append( def_comment( txt_StrC("Empty function body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Specifiers
|
||||
{
|
||||
CodeFn fwd_fn = parse_function( code(
|
||||
inline
|
||||
void test_function_specifiers();
|
||||
));
|
||||
|
||||
CodeTypedef typedef_u8_ptr = parse_typedef( code(
|
||||
typedef u8* u8_ptr;
|
||||
));
|
||||
|
||||
gen_sanity_file.print(fwd_fn);
|
||||
gen_sanity_file.print(typedef_u8_ptr);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Struct
|
||||
{
|
||||
CodeStruct fwd = parse_struct( code(
|
||||
struct TestEmptyStruct;
|
||||
));
|
||||
|
||||
CodeStruct empty_body = parse_struct( code(
|
||||
struct TestEmptyStruct
|
||||
{};
|
||||
));
|
||||
|
||||
empty_body->Body.append( def_comment( txt_StrC("Empty struct body") ) );
|
||||
|
||||
gen_sanity_file.print(fwd);
|
||||
gen_sanity_file.print(empty_body);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Union
|
||||
{
|
||||
CodeUnion empty = parse_union( code(
|
||||
union TestEmptyUnion
|
||||
{
|
||||
};
|
||||
));
|
||||
|
||||
empty->Body.append( def_comment( txt_StrC("Empty union body") ) );
|
||||
|
||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned short u16; )) );
|
||||
gen_sanity_file.print( parse_typedef( code( typedef unsigned long u32; )) );
|
||||
|
||||
CodeUnion def = parse_union( code(
|
||||
union TestUnion
|
||||
{
|
||||
u8 a;
|
||||
u16 b;
|
||||
u32 c;
|
||||
};
|
||||
));
|
||||
|
||||
gen_sanity_file.print(empty);
|
||||
gen_sanity_file.print(def);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Using
|
||||
{
|
||||
CodeUsing reg = (CodeUsing) parse_using( code(
|
||||
using TestUsing = u8;
|
||||
));
|
||||
|
||||
CodeNamespace nspace = parse_namespace( code(
|
||||
namespace TestNamespace
|
||||
{
|
||||
};
|
||||
|
||||
));
|
||||
|
||||
CodeUsing npspace_using = parse_using( code(
|
||||
using namespace TestNamespace;
|
||||
));
|
||||
|
||||
gen_sanity_file.print(reg);
|
||||
gen_sanity_file.print(nspace);
|
||||
gen_sanity_file.print(npspace_using);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// Variable
|
||||
{
|
||||
CodeVar bss = parse_variable( code(
|
||||
u8 test_variable;
|
||||
));
|
||||
|
||||
CodeVar data = parse_variable( code(
|
||||
u8 test_variable = 0x12;
|
||||
));
|
||||
|
||||
gen_sanity_file.print(bss);
|
||||
gen_sanity_file.print(data);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
// template
|
||||
{
|
||||
#pragma push_macro("template")
|
||||
#undef template
|
||||
CodeTemplate tmpl = parse_template( code(
|
||||
template< typename Type >
|
||||
void test_template( Type a )
|
||||
{
|
||||
}
|
||||
));
|
||||
#pragma pop_macro("template")
|
||||
|
||||
gen_sanity_file.print(tmpl);
|
||||
}
|
||||
|
||||
gen_sanity_file.print_fmt("\n");
|
||||
|
||||
gen_sanity_file.print( def_comment( txt_StrC(
|
||||
"End of base case tests\n"
|
||||
)));
|
||||
|
||||
gen_sanity_file.write();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user