mirror of
https://github.com/Ed94/gencpp.git
synced 2024-11-10 11:04:52 -08:00
377 lines
9.8 KiB
C++
377 lines
9.8 KiB
C++
|
/*
|
||
|
This is based of the array container implementation in the zpl.h library.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "Bloat.hpp"
|
||
|
#include "gen.hpp"
|
||
|
|
||
|
#ifdef gen_time
|
||
|
using namespace gen;
|
||
|
|
||
|
Code gen__array_base()
|
||
|
{
|
||
|
// Make these global consts to be accessed anywhere...
|
||
|
Code t_sw = def_type( txt(sw) );
|
||
|
Code t_uw = def_type( txt(uw) );
|
||
|
Code t_allocator = def_type( txt(allocator) );
|
||
|
|
||
|
Code header;
|
||
|
{
|
||
|
Code num = def_variable( "Num", t_uw );
|
||
|
Code capacity = def_variable( "Capacity", t_uw );
|
||
|
Code allocator_var = def_variable( "Allocator", t_allocator );
|
||
|
Code header_body = def_struct_body( 3, num, capacity, allocator_var );
|
||
|
|
||
|
header = def_struct( "ArrayHeader", header_body );
|
||
|
}
|
||
|
|
||
|
Code grow_formula;
|
||
|
{
|
||
|
Code spec = def_specifiers(1, Specifier::Inline);
|
||
|
Code params = def_parameters(1, "value", t_uw );
|
||
|
Code body = untyped_fmt( "\t""return 2 * value * 8;" );
|
||
|
|
||
|
grow_formula = def_function( "grow_formula", spec, params, t_sw, body );
|
||
|
}
|
||
|
|
||
|
Code base_body = def_struct_body(2, header, grow_formula);
|
||
|
Code base = def_struct( "ArrayBase", base_body );
|
||
|
return base;
|
||
|
}
|
||
|
|
||
|
#define gen_array( Type_ ) gen__array( #Type_, sizeof(Type_), a_base )
|
||
|
Code gen__array( char const* type_str, s32 type_size, Code parent )
|
||
|
{
|
||
|
// Make these global consts to be accessed anywhere...
|
||
|
Code t_uw = def_type( txt(uw) );
|
||
|
Code t_sw = def_type( txt(sw) );
|
||
|
Code t_bool = def_type( txt(bool) );
|
||
|
Code t_allocator = def_type( txt(allocator) );
|
||
|
Code t_void = def_type( txt(void) );
|
||
|
|
||
|
Code v_nullptr = untyped_fmt( "nullptr" );
|
||
|
|
||
|
Code spec_ct = def_specifiers(1, Specifier::Constexpr );
|
||
|
Code spec_inline = def_specifiers(1, Specifier::Inline );
|
||
|
|
||
|
Code type = def_type( type_str );
|
||
|
Code ptr_type = def_type( string_sprintf_buf( g_allocator, "%s*", type_str ) );
|
||
|
Code ref_type = def_type( string_sprintf_buf( g_allocator, "%s&", type_str ) );
|
||
|
|
||
|
string name = string_sprintf_buf( g_allocator, "Array_%s", type_str );
|
||
|
|
||
|
// From ArrayBase
|
||
|
Code t_header = def_type( "Header" );
|
||
|
Code ptr_header = def_type( "Header*" );
|
||
|
Code ref_header = def_type( "Header&" );
|
||
|
|
||
|
Code array_def;
|
||
|
{
|
||
|
Code using_type = def_using( "type", type );
|
||
|
Code data = def_variable( "Data", ptr_type );
|
||
|
|
||
|
Code init;
|
||
|
{
|
||
|
Code params = def_parameters( 1, "mem_hanlder", t_allocator );
|
||
|
Code body = untyped_fmt( "\t""return init_reserve( mem_handler, grow_formula(0) );" );
|
||
|
|
||
|
init = def_function( "init", UnusedCode, params, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code init_reserve;
|
||
|
{
|
||
|
Code params = def_parameters( 2, "mem_handler", ref_type, "capacity", t_sw );
|
||
|
Code body;
|
||
|
{
|
||
|
Code header_value = untyped_fmt(
|
||
|
"rcast( Header*, alloc( mem_handler, sizeof( Header ) + sizeof(type) + capacity ))"
|
||
|
);
|
||
|
Code header = def_variable( "", ptr_header, header_value );
|
||
|
|
||
|
Code null_check = untyped_fmt(
|
||
|
"\t" "if (header == nullptr)"
|
||
|
"\n\t\t" "return false;"
|
||
|
);
|
||
|
|
||
|
Code header_init = untyped_fmt(
|
||
|
"\n\t" "header->Num = 0;"
|
||
|
"\n\t" "header->Capacity = capacity;"
|
||
|
"\n\t" "header->Allocator = mem_handler;"
|
||
|
);
|
||
|
|
||
|
Code assign_data = untyped_fmt(
|
||
|
"\t" "Data = rcast( %s, header + 1 );", ptr_type
|
||
|
);
|
||
|
|
||
|
Code ret_true = untyped_fmt( "\t""return true" );
|
||
|
|
||
|
body = def_function_body( 5
|
||
|
, header
|
||
|
, null_check
|
||
|
, header_init
|
||
|
, assign_data
|
||
|
, ret_true
|
||
|
);
|
||
|
}
|
||
|
|
||
|
init_reserve = def_function( "init_reserve", UnusedCode, params, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code free;
|
||
|
{
|
||
|
Code body = untyped_fmt(
|
||
|
"\t" "Header& header = get_header();"
|
||
|
"\n\t" "::free( header.Allocator, & get_header() );"
|
||
|
);
|
||
|
|
||
|
free = def_function( "free", UnusedCode, UnusedCode, t_void, body );
|
||
|
}
|
||
|
|
||
|
Code append;
|
||
|
{
|
||
|
Code params = def_parameters( 1, "value", type );
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "", ref_header, untyped_fmt( "get_header()") );
|
||
|
|
||
|
Code check_cap = untyped_fmt(
|
||
|
"\t" "if ( header.Capacity < header.Num + 1 )"
|
||
|
"\n\t\t" "if ( ! grow(0) )"
|
||
|
"\n\t\t\t" "return false;"
|
||
|
);
|
||
|
|
||
|
Code assign = untyped_fmt(
|
||
|
"\t" "Data[ header.Num ] = value;"
|
||
|
"\t\n" "header.Num++;"
|
||
|
"\n"
|
||
|
"\n\t" "return true;"
|
||
|
);
|
||
|
|
||
|
body = def_function_body( 3, header, check_cap, assign );
|
||
|
}
|
||
|
|
||
|
append = def_function( "append", UnusedCode, params, t_void, body );
|
||
|
}
|
||
|
|
||
|
Code back;
|
||
|
{
|
||
|
Code body = untyped_fmt(
|
||
|
"\t" "Header& header = get_header();"
|
||
|
"\n\t" "return data[ header.Num - 1 ];"
|
||
|
);
|
||
|
|
||
|
back = def_function( "back", UnusedCode, UnusedCode, type, body );
|
||
|
}
|
||
|
|
||
|
Code clear;
|
||
|
{
|
||
|
Code body = untyped_fmt( "\t""get_header().Num = 0;" );
|
||
|
|
||
|
clear = def_function( "clear", UnusedCode, UnusedCode, t_void, body );
|
||
|
}
|
||
|
|
||
|
Code fill;
|
||
|
{
|
||
|
Code params = def_parameters( 3, "begin", t_uw, "end", t_uw, "value", type );
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "", ref_header, untyped_fmt( "get_header()") );
|
||
|
|
||
|
Code check = untyped_fmt(
|
||
|
"\t" "if ( begin < 0 || end >= header.Num )"
|
||
|
"\n\t\t" "fatal( \"Range out of bounds\" );"
|
||
|
);
|
||
|
|
||
|
Code iter = untyped_fmt(
|
||
|
"\t" "for ( sw index = begin; index < end; index++ )"
|
||
|
"\n\t\t" "Data[index] = vallue;"
|
||
|
);
|
||
|
|
||
|
body = def_function_body( 3, header, check, iter );
|
||
|
}
|
||
|
|
||
|
fill = def_function( "fill", UnusedCode, params, t_void, body );
|
||
|
}
|
||
|
|
||
|
Code get_header;
|
||
|
{
|
||
|
Code body = untyped_fmt( "\t""return pcast( Header, Data - 1 );" );
|
||
|
|
||
|
get_header = def_function( "get_header", spec_inline, UnusedCode, ref_header, body );
|
||
|
}
|
||
|
|
||
|
Code grow;
|
||
|
{
|
||
|
Code param = def_parameters( 1, "min_capacity", t_uw );
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "header", ref_header, untyped_fmt("get_header") );
|
||
|
Code new_capacity = def_variable( "new_capacity", t_uw, untyped_fmt("grow_formula( header.Capacity )") );
|
||
|
|
||
|
Code check_n_set = untyped_fmt(
|
||
|
"\t" "if ( new_capacity < min_capacity )"
|
||
|
"\n\t\t" "new_capacity = min_capacity;"
|
||
|
);
|
||
|
|
||
|
Code ret = untyped_fmt( "\t" "return set_capacity( new_capacity );" );
|
||
|
|
||
|
body = def_function_body( 4, header, new_capacity, check_n_set, ret );
|
||
|
}
|
||
|
|
||
|
grow = def_function( "grow", UnusedCode, param, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code pop;
|
||
|
{
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "header", ref_header, untyped_fmt("get_header()") );
|
||
|
|
||
|
Code assertion = untyped_fmt( "\t" "assert( header.Num > 0 );" );
|
||
|
Code decrement = untyped_fmt( "\t" "header.Num--; " );
|
||
|
|
||
|
body = def_function_body( 3, header, assertion, decrement );
|
||
|
}
|
||
|
|
||
|
pop = def_function( "pop", UnusedCode, UnusedCode, t_void, body );
|
||
|
}
|
||
|
|
||
|
Code reserve;
|
||
|
{
|
||
|
Code params = def_parameters( 1, "new_capacity", t_uw );
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "header", ref_header, untyped_fmt("get_header()") );
|
||
|
|
||
|
Code check_n_set = untyped_fmt(
|
||
|
"\t" "if ( header.Capacity < new_capacity )"
|
||
|
"\n\t\t" "return set_capacity( new_capacity );"
|
||
|
);
|
||
|
|
||
|
Code ret = untyped_fmt( "\t" "return true" );
|
||
|
|
||
|
body = def_function_body( 3, header, check_n_set, ret );
|
||
|
}
|
||
|
|
||
|
reserve = def_function( "reserve", UnusedCode, params, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code resize;
|
||
|
{
|
||
|
Code param = def_parameters( 1, "new_num", t_uw );
|
||
|
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "header", ref_header, untyped_fmt("get_header()") );
|
||
|
|
||
|
Code check_n_grow = untyped_fmt(
|
||
|
"\t" "if ( header.Capacity < new_num )"
|
||
|
"\n\t\t" "if ( ! grow( new_num) )"
|
||
|
"\n\t\t\t" "return false;"
|
||
|
);
|
||
|
|
||
|
Code set_n_ret = untyped_fmt(
|
||
|
"\t" "header.Count = new_num;"
|
||
|
"\n\t" "return true;"
|
||
|
);
|
||
|
|
||
|
body = def_function_body( 3, header, check_n_grow, set_n_ret );
|
||
|
}
|
||
|
|
||
|
resize = def_function( "resize", UnusedCode, param, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code set_capacity;
|
||
|
{
|
||
|
Code param = def_parameters( 1, "capacity", t_uw );
|
||
|
|
||
|
Code body;
|
||
|
{
|
||
|
Code header = def_variable( "header", ref_header, untyped_fmt("get_header()") );
|
||
|
|
||
|
Code checks = untyped_fmt(
|
||
|
"\t" "if ( capacity == header.Capacity )"
|
||
|
"\n\t\t" "return true;"
|
||
|
"\n"
|
||
|
"\n\t" "if ( capacity < header.Num )"
|
||
|
"\n\t\t" "header.Num = capacity;"
|
||
|
);
|
||
|
|
||
|
Code size = def_variable( "size", t_uw, untyped_fmt("sizeof(Header) + sizeof(type) * capacity"));
|
||
|
Code new_header = def_variable( "new_header", ptr_header, untyped_fmt("rcast( Header*, alloc( header.Allocator, size ));"));
|
||
|
|
||
|
Code check_n_move = untyped_fmt(
|
||
|
"\t""if ( new_header == nullptr )"
|
||
|
"\n\t\t""return false;"
|
||
|
"\n"
|
||
|
"\n\t""memmove( new_header, & header, sizeof(Header) + sizeof(type) * header.Num );"
|
||
|
);
|
||
|
|
||
|
Code set_free_ret = untyped_fmt(
|
||
|
"\t" "new_header->Allocator = header.Allocator;"
|
||
|
"\n\t" "new_header->Num = header.Num;"
|
||
|
"\n\t" "new_header->Capacity = header.Capacity;"
|
||
|
"\n"
|
||
|
"\n\t" "zpl_free( header );"
|
||
|
"\n"
|
||
|
"\n\t" "*Data = new_header + 1;"
|
||
|
"\n"
|
||
|
"\n\t" "return true;"
|
||
|
);
|
||
|
|
||
|
body = def_function_body( 6, header, checks, size, new_header, check_n_move, set_free_ret );
|
||
|
}
|
||
|
|
||
|
set_capacity = def_function( "set_capacity", UnusedCode, param, t_bool, body );
|
||
|
}
|
||
|
|
||
|
Code body = def_struct_body( 15
|
||
|
, using_type
|
||
|
, data
|
||
|
|
||
|
, init
|
||
|
, init_reserve
|
||
|
, append
|
||
|
, back
|
||
|
, clear
|
||
|
, fill
|
||
|
, free
|
||
|
, get_header
|
||
|
, grow
|
||
|
, pop
|
||
|
, reserve
|
||
|
, resize
|
||
|
, set_capacity
|
||
|
);
|
||
|
|
||
|
array_def = def_struct( name, body, parent );
|
||
|
}
|
||
|
|
||
|
return array_def;
|
||
|
}
|
||
|
|
||
|
u32 gen_array_file()
|
||
|
{
|
||
|
Code a_base = gen__array_base();
|
||
|
|
||
|
Code a_u32 = gen_array( u32 );
|
||
|
Code a_cstr = gen_array( char const* );
|
||
|
|
||
|
Builder
|
||
|
arraygen;
|
||
|
arraygen.open( "Array.gen.hpp" );
|
||
|
arraygen.print( a_u32 );
|
||
|
arraygen.print( a_cstr );
|
||
|
arraygen.write();
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifndef gen_time
|
||
|
# include "Array.gen.hpp"
|
||
|
|
||
|
# define array( Type_ ) array_##Type_
|
||
|
#endif
|