mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-30 14:30:53 -07:00 
			
		
		
		
	Compare commits
	
		
			44 Commits
		
	
	
		
			v0.17-Alph
			...
			9e88cb8724
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9e88cb8724 | |||
| f61c1c560d | |||
| 8ef982003a | |||
| 31691b1466 | |||
| ed0c0422ad | |||
| e5acac1d18 | |||
| c7b072266f | |||
| a96d03eaed | |||
| 0b4ccac8f9 | |||
| 31a3609b28 | |||
| fbdb870986 | |||
| 6d04165b96 | |||
| cc245cc263 | |||
| 06deb1e836 | |||
| 5527a27f7b | |||
| a67fdef20a | |||
| 056a5863b8 | |||
| 79eb5f1f76 | |||
| c6cb583518 | |||
| 34eec66f35 | |||
| 4137ebfbd8 | |||
| 5958dd2055 | |||
| 163ad0a511 | |||
| e3c2a577ba | |||
| 81a0376c99 | |||
| 1417a68757 | |||
| 1e4d5ce630 | |||
| 0f2763a115 | |||
| 420f452d35 | |||
| 908c385de5 | |||
| c1878265c8 | |||
| 23742868c4 | |||
| 2e5e31ed3b | |||
| 00df336610 | |||
| d89c9a6072 | |||
| 6aa99ac1d5 | |||
| 3989f5fa83 | |||
| f90c0a59b6 | |||
| 33f992ef56 | |||
| 0542204b35 | |||
| e5616c5879 | |||
| 40a256f6c3 | |||
| b8e1aa6eb7 | |||
| e1592ba410 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -29,3 +29,6 @@ release/** | |||||||
| ! **/Unreal/validate.unreal.cpp | ! **/Unreal/validate.unreal.cpp | ||||||
| project/auxillary/vis_ast/dependencies/temp | project/auxillary/vis_ast/dependencies/temp | ||||||
| test/gen/original | test/gen/original | ||||||
|  | singleheader/gen/scratch.hpp | ||||||
|  | test/gen/scratch.cpp | ||||||
|  | gen_c_library/gen | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @@ -41,6 +41,15 @@ | |||||||
| 			"cwd": "${workspaceFolder}/singleheader/", | 			"cwd": "${workspaceFolder}/singleheader/", | ||||||
| 			"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis" | 			"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis" | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"type": "cppvsdbg", | ||||||
|  | 			"request": "launch", | ||||||
|  | 			"name": "Debug unreal vsdbg", | ||||||
|  | 			"program": "${workspaceFolder}/unreal_engine/build/unreal.exe", | ||||||
|  | 			"args": [], | ||||||
|  | 			"cwd": "${workspaceFolder}/unreal_engine/", | ||||||
|  | 			"visualizerFile": "${workspaceFolder}/scripts/gencpp.natvis" | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			"type": "cppvsdbg", | 			"type": "cppvsdbg", | ||||||
| 			"request": "launch", | 			"request": "launch", | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -37,7 +37,10 @@ | |||||||
| 		"propidl.h": "c", | 		"propidl.h": "c", | ||||||
| 		"android_native_app_glue.h": "c", | 		"android_native_app_glue.h": "c", | ||||||
| 		"raylib.h": "c", | 		"raylib.h": "c", | ||||||
| 		"*.m": "cpp" | 		"*.m": "cpp", | ||||||
|  | 		"atomic": "cpp", | ||||||
|  | 		"gen.h": "c", | ||||||
|  | 		"string_ops.hpp": "c" | ||||||
| 	}, | 	}, | ||||||
| 	"C_Cpp.intelliSenseEngineFallback": "disabled", | 	"C_Cpp.intelliSenseEngineFallback": "disabled", | ||||||
| 	"mesonbuild.configureOnOpen": true, | 	"mesonbuild.configureOnOpen": true, | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								Readme.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Readme.md
									
									
									
									
									
								
							| @@ -10,7 +10,9 @@ Its not meant to be a black box metaprogramming utility, it should be easy to in | |||||||
|  |  | ||||||
| ## Notes | ## Notes | ||||||
|  |  | ||||||
| **On Partial Hiatus: Working on handmade hero for now. Only fixes will be pushed as I come across them until I get what I want done from the series** | **On Partial Hiatus: Life has got me tackling other issues..**   | ||||||
|  | I will be passively updating the library with bug fixes and minor improvements as I use it for my personal projects.   | ||||||
|  | There won't be any major reworks or features to this thing for a while. | ||||||
|  |  | ||||||
| This project is still in development (very much an alpha state), so expect bugs and missing features.   | This project is still in development (very much an alpha state), so expect bugs and missing features.   | ||||||
| See [issues](https://github.com/Ed94/gencpp/issues) for a list of known bugs or todos. | See [issues](https://github.com/Ed94/gencpp/issues) for a list of known bugs or todos. | ||||||
| @@ -65,7 +67,7 @@ Example using each construction interface: | |||||||
| Validation and construction through a functional interface. | Validation and construction through a functional interface. | ||||||
|  |  | ||||||
| ```cpp | ```cpp | ||||||
| Code t_uw           = def_type( name(uw) ); | Code t_uw           = def_type( name(usize) ); | ||||||
| Code t_allocator    = def_type( name(allocator) ); | Code t_allocator    = def_type( name(allocator) ); | ||||||
| Code t_string_const = def_type( name(char), def_specifiers( args( ESpecifier::Const, ESpecifier::Ptr ) )); | Code t_string_const = def_type( name(char), def_specifiers( args( ESpecifier::Const, ESpecifier::Ptr ) )); | ||||||
|  |  | ||||||
| @@ -88,8 +90,8 @@ Validation through ast construction. | |||||||
| Code header = parse_struct( code( | Code header = parse_struct( code( | ||||||
|     struct ArrayHeader |     struct ArrayHeader | ||||||
|     { |     { | ||||||
|         uw        Num; |         usize        Num; | ||||||
|         uw        Capacity; |         usize        Capacity; | ||||||
|         allocator Allocator; |         allocator Allocator; | ||||||
|     }; |     }; | ||||||
| )); | )); | ||||||
| @@ -104,8 +106,8 @@ No validation, just glorified text injection. | |||||||
| Code header = code_str( | Code header = code_str( | ||||||
|     struct ArrayHeader |     struct ArrayHeader | ||||||
|     { |     { | ||||||
|         uw        Num; |         usize        Num; | ||||||
|         uw        Capacity; |         usize        Capacity; | ||||||
|         allocator Allocator; |         allocator Allocator; | ||||||
|     }; |     }; | ||||||
| ); | ); | ||||||
| @@ -121,8 +123,8 @@ All three constrcuton interfaces will generate the following C code: | |||||||
| ```cpp | ```cpp | ||||||
| struct ArrayHeader | struct ArrayHeader | ||||||
| { | { | ||||||
|     uw        Num; |     usize        Num; | ||||||
|     uw        Capacity; |     usize        Capacity; | ||||||
|     allocator Allocator; |     allocator Allocator; | ||||||
| }; | }; | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -136,7 +136,7 @@ The width dictates how much the static array can hold before it must give way to | |||||||
|  |  | ||||||
| ```cpp | ```cpp | ||||||
| constexpr static | constexpr static | ||||||
| uw ArrSpecs_Cap = | usize ArrSpecs_Cap = | ||||||
| ( | ( | ||||||
|     AST_POD_Size |     AST_POD_Size | ||||||
|     - sizeof(AST*) * 3 |     - sizeof(AST*) * 3 | ||||||
| @@ -158,7 +158,7 @@ Data Notes: | |||||||
|   * Most of the work is just defining the allocation procedure: |   * Most of the work is just defining the allocation procedure: | ||||||
|  |  | ||||||
| ```cpp | ```cpp | ||||||
|     void* ( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ); |     void* ( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| * ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type. | * ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type. | ||||||
|   | |||||||
							
								
								
									
										358
									
								
								gen_c_library/c_library.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										358
									
								
								gen_c_library/c_library.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,358 @@ | |||||||
|  | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
|  | #define GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
|  | #define GEN_EXPOSE_BACKEND | ||||||
|  | #define GEN_SUPPORT_CPP_MEMBER_FEATURES 1 | ||||||
|  | #include "../project/gen.cpp" | ||||||
|  |  | ||||||
|  | #include "helpers/push_ignores.inline.hpp" | ||||||
|  | #include "helpers/helper.hpp" | ||||||
|  |  | ||||||
|  | GEN_NS_BEGIN | ||||||
|  | #include "dependencies/parsing.cpp" | ||||||
|  | GEN_NS_END | ||||||
|  |  | ||||||
|  | #include "auxillary/builder.hpp" | ||||||
|  | #include "auxillary/builder.cpp" | ||||||
|  | #include "auxillary/scanner.hpp" | ||||||
|  |  | ||||||
|  | #include <cstdlib>   // for system() | ||||||
|  |  | ||||||
|  | #include "components/memory.fixed_arena.hpp" | ||||||
|  | #include "components/misc.hpp" | ||||||
|  | #include "components/containers.array.hpp" | ||||||
|  | #include "components/containers.hashtable.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | constexpr char const* generation_notice = | ||||||
|  | "// This file was generated automatially by gencpp's c_library.cpp" | ||||||
|  | "(See: https://github.com/Ed94/gencpp)\n\n"; | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_start = txt(R"( | ||||||
|  | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | ||||||
|  | // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | ||||||
|  | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_end = txt(R"( | ||||||
|  | // GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | #endif | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_start = txt(R"( | ||||||
|  | #pragma region GENCPP IMPLEMENTATION GUARD | ||||||
|  | #if defined(GEN_IMPLEMENTATION) && ! defined(GEN_IMPLEMENTED) | ||||||
|  | #	define GEN_IMPLEMENTED | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_end = txt(R"( | ||||||
|  | #endif | ||||||
|  | #pragma endregion GENCPP IMPLEMENTATION GUARD | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | void format_file( char const* path ) | ||||||
|  | { | ||||||
|  | 	String resolved_path = String::make(GlobalAllocator, to_str(path)); | ||||||
|  |  | ||||||
|  | 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | ||||||
|  | 	style_arg.append("../scripts/.clang-format "); | ||||||
|  |  | ||||||
|  | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
|  | 	#define clang_format      "clang-format " | ||||||
|  | 	#define cf_format_inplace "-i " | ||||||
|  | 	#define cf_verbose        "-verbose " | ||||||
|  | 	String command = String::make( GlobalAllocator, clang_format ); | ||||||
|  | 	command.append( cf_format_inplace ); | ||||||
|  | 	command.append( cf_verbose ); | ||||||
|  | 	command.append( style_arg ); | ||||||
|  | 	command.append( resolved_path ); | ||||||
|  | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
|  | 		system( command ); | ||||||
|  | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
|  | 	#undef cf_cmd | ||||||
|  | 	#undef cf_format_inplace | ||||||
|  | 	#undef cf_style | ||||||
|  | 	#undef cf_verbse | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code dump_to_scratch_and_retireve( Code code ) | ||||||
|  | { | ||||||
|  | 	Builder ecode_file_temp = Builder::open("gen/scratch.hpp"); | ||||||
|  | 	ecode_file_temp.print(code); | ||||||
|  | 	ecode_file_temp.write(); | ||||||
|  | 	format_file("gen/scratch.hpp"); | ||||||
|  | 	Code result = scan_file( "gen/scratch.hpp" ); | ||||||
|  | 	remove("gen/scratch.hpp"); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeBody parse_file( const char* path ) | ||||||
|  | { | ||||||
|  | 	FileContents file = file_read_contents( GlobalAllocator, true, path ); | ||||||
|  | 	CodeBody     code = parse_global_body( { file.size, (char const*)file.data } ); | ||||||
|  | 	log_fmt("\nParsed: %s\n", path); | ||||||
|  | 	return code; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int gen_main() | ||||||
|  | { | ||||||
|  | #define project_dir "../project/" | ||||||
|  | 	gen::init(); | ||||||
|  |  | ||||||
|  | 	Code push_ignores           = scan_file( project_dir "helpers/push_ignores.inline.hpp" ); | ||||||
|  | 	Code pop_ignores            = scan_file( project_dir "helpers/pop_ignores.inline.hpp" ); | ||||||
|  | 	Code c_library_header_start = scan_file( "components/header_start.hpp" ); | ||||||
|  |  | ||||||
|  | 	Builder | ||||||
|  | 	header = Builder::open( "gen/gen.h" ); | ||||||
|  | 	header.print_fmt( generation_notice ); | ||||||
|  | 	header.print_fmt("#pragma once\n\n"); | ||||||
|  | 	header.print( push_ignores ); | ||||||
|  |  | ||||||
|  | 	// Headers | ||||||
|  | 	{ | ||||||
|  | 		header.print( c_library_header_start ); | ||||||
|  |  | ||||||
|  | 		Code platform     = scan_file( project_dir "dependencies/platform.hpp" ); | ||||||
|  | 		Code macros       = scan_file( project_dir "dependencies/macros.hpp" ); | ||||||
|  | 		Code basic_types  = scan_file( project_dir "dependencies/basic_types.hpp" ); | ||||||
|  | 		Code debug        = scan_file( project_dir "dependencies/debug.hpp" ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_start ); | ||||||
|  | 		header.print( platform ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
|  | 		header.print( macros ); | ||||||
|  | 		header.print( basic_types ); | ||||||
|  | 		header.print( debug ); | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | ||||||
|  | 		CodeBody memory        = def_body(ECode::Global_Body); | ||||||
|  | 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case ECode::Using: | ||||||
|  | 				{ | ||||||
|  | 					log_fmt("REPLACE THIS MANUALLY: %S\n", entry->Name); | ||||||
|  | 					CodeUsing   using_ver   = entry.cast<CodeUsing>(); | ||||||
|  | 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | ||||||
|  |  | ||||||
|  | 					memory.append(typedef_ver); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Function: | ||||||
|  | 				{ | ||||||
|  | 					CodeFn fn = entry.cast<CodeFn>(); | ||||||
|  | 					s32 constexpr_found = fn->Specs.remove( ESpecifier::Constexpr ); | ||||||
|  | 					if (constexpr_found > -1) { | ||||||
|  | 						log_fmt("Found constexpr: %S\n", entry->to_string()); | ||||||
|  | 						fn->Specs.append(ESpecifier::Inline); | ||||||
|  | 					} | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Template: | ||||||
|  | 				{ | ||||||
|  | 					CodeTemplate tmpl = entry.cast<CodeTemplate>(); | ||||||
|  | 					if ( tmpl->Declaration->Name.contains(txt("swap"))) | ||||||
|  | 					{ | ||||||
|  | 						CodeBody macro_swap = parse_global_body( txt(R"( | ||||||
|  | #define swap( a, b )              \ | ||||||
|  | 	do                            \ | ||||||
|  | 	{                             \ | ||||||
|  | 		typeof( a ) temp = ( a ); \ | ||||||
|  | 		( a )            = ( b ); \ | ||||||
|  | 		( b )            = temp;  \ | ||||||
|  | 	} while ( 0 ) | ||||||
|  | )" | ||||||
|  | 						)); | ||||||
|  | 						memory.append(macro_swap); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Class: | ||||||
|  | 				case ECode::Struct: | ||||||
|  | 				{ | ||||||
|  | 					CodeBody body     = entry->Body->operator CodeBody(); | ||||||
|  | 					CodeBody new_body = def_body( entry->Body->Type ); | ||||||
|  | 					for ( Code body_entry = body.begin(); body_entry != body.end(); ++ body_entry ) switch | ||||||
|  | 					(body_entry->Type) { | ||||||
|  | 						case ECode::Preprocess_If: | ||||||
|  | 						{ | ||||||
|  | 							ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), body_entry, body ); | ||||||
|  | 						} | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 						default: | ||||||
|  | 							new_body.append(body_entry); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					entry->Body = rcast(AST*, new_body.ast); | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Preprocess_If: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, parsed_memory ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_memory ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Preprocess_Pragma: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				default: { | ||||||
|  | 					memory.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(memory) ); | ||||||
|  |  | ||||||
|  | 		Code string_ops = scan_file( project_dir "dependencies/string_ops.hpp" ); | ||||||
|  | 		header.print( string_ops ); | ||||||
|  |  | ||||||
|  | 		CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" ); | ||||||
|  | 		CodeBody printing        = def_body(ECode::Global_Body); | ||||||
|  | 		for ( Code entry = printing_parsed.begin(); entry != printing_parsed.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case ECode::Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, printing_parsed ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					printing.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				case ECode::Variable: | ||||||
|  | 				{ | ||||||
|  | 					if (contains(entry->Name, txt("Msg_Invalid_Value"))) | ||||||
|  | 					{ | ||||||
|  | 						CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
|  | 						printing.append(define); | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					printing.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 				default: | ||||||
|  | 					printing.append(entry); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		header.print(dump_to_scratch_and_retireve(printing)); | ||||||
|  |  | ||||||
|  | 		CodeBody containers = def_body(ECode::Global_Body); | ||||||
|  | 		{ | ||||||
|  | 			containers.append( def_pragma(code(region Containers))); | ||||||
|  |  | ||||||
|  | 			containers.append( gen_array_base() ); | ||||||
|  | 			containers.append( gen_hashtable_base() ); | ||||||
|  |  | ||||||
|  | 			containers.append( def_pragma(code(endregion Containers))); | ||||||
|  | 		} | ||||||
|  | 		header.print(fmt_newline); | ||||||
|  | 		header.print(dump_to_scratch_and_retireve(containers)); | ||||||
|  |  | ||||||
|  | 		Code hashing = scan_file( project_dir "dependencies/hashing.hpp" ); | ||||||
|  | 		header.print( hashing ); | ||||||
|  |  | ||||||
|  | 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | ||||||
|  | 		CodeBody strings        = def_body(ECode::Global_Body); | ||||||
|  | 		for ( Code entry = parsed_strings.begin(); entry != parsed_strings.end(); ++ entry ) | ||||||
|  | 		{ | ||||||
|  | 			switch (entry->Type) | ||||||
|  | 			{ | ||||||
|  | 				case ECode::Preprocess_If: | ||||||
|  | 				{ | ||||||
|  | 					ignore_preprocess_cond_block(txt("! GEN_COMPILER_C"), entry, parsed_strings); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				case ECode::Preprocess_IfDef: | ||||||
|  | 				{ | ||||||
|  | 					ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_strings ); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				case ECode::Struct_Fwd: | ||||||
|  | 				{ | ||||||
|  | 					if ( entry->Name.is_equal(txt("String")) ) | ||||||
|  | 					{ | ||||||
|  | 						CodeTypedef c_def = parse_typedef(code( typedef Type* String; )); | ||||||
|  | 						strings.append(c_def); | ||||||
|  | 						strings.append(fmt_newline); | ||||||
|  | 						++ entry; | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 					strings.append(entry); | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 				default: | ||||||
|  | 					strings.append(entry); | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		header.print(dump_to_scratch_and_retireve(strings)); | ||||||
|  |  | ||||||
|  | 		Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" ); | ||||||
|  | 		Code timing = scan_file( project_dir "dependencies/timing.hpp" ); | ||||||
|  | 		header.print( filesystem ); | ||||||
|  | 		header.print( timing ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "\nGEN_NS_END\n" ); | ||||||
|  | 		header.print_fmt( roll_own_dependencies_guard_end ); | ||||||
|  |  | ||||||
|  | 		Code types      = scan_file( project_dir "components/types.hpp" ); | ||||||
|  | 		Code ast        = scan_file( project_dir "components/ast.hpp" ); | ||||||
|  | 		Code ast_types  = scan_file( project_dir "components/ast_types.hpp" ); | ||||||
|  | 		Code code_types = scan_file( project_dir "components/code_types.hpp" ); | ||||||
|  | 		Code interface  = scan_file( project_dir "components/interface.hpp" ); | ||||||
|  | 		Code inlines 	= scan_file( project_dir "components/inlines.hpp" ); | ||||||
|  | 		Code header_end = scan_file( project_dir "components/header_end.hpp" ); | ||||||
|  |  | ||||||
|  | 		CodeBody ecode       = gen_ecode     ( project_dir "enums/ECode.csv" ); | ||||||
|  | 		CodeBody eoperator   = gen_eoperator ( project_dir "enums/EOperator.csv" ); | ||||||
|  | 		CodeBody especifier  = gen_especifier( project_dir "enums/ESpecifier.csv" ); | ||||||
|  | 		CodeBody ast_inlines = gen_ast_inlines(); | ||||||
|  |  | ||||||
|  | 		header.print_fmt("#pragma region Types\n"); | ||||||
|  | 		header.print( types ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( ecode )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( eoperator )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( especifier )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print_fmt("#pragma endregion Types\n\n"); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	header.print( pop_ignores ); | ||||||
|  | 	header.write(); | ||||||
|  |  | ||||||
|  | 	// format_file( "gen/gen.h" ); | ||||||
|  |  | ||||||
|  | 	gen::deinit(); | ||||||
|  | 	return 0; | ||||||
|  | #undef project_dir | ||||||
|  | } | ||||||
							
								
								
									
										295
									
								
								gen_c_library/components/containers.array.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								gen_c_library/components/containers.array.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,295 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | CodeBody gen_array_base() | ||||||
|  | { | ||||||
|  | 	CodeTypedef td_header = parse_typedef( code( typedef struct ArrayHeader ArrayHeader; )); | ||||||
|  | 	CodeStruct  header    = parse_struct( code( | ||||||
|  | 		struct ArrayHeader | ||||||
|  | 		{ | ||||||
|  | 			AllocatorInfo Allocator; | ||||||
|  | 			usize         Capacity; | ||||||
|  | 			usize         Num; | ||||||
|  | 		}; | ||||||
|  | 	)); | ||||||
|  |  | ||||||
|  | 	// Code grow_formula = untyped_str( txt( "#define gen_array_grow_formula( value ) ( 2 * value + 8 )\n" )); | ||||||
|  | 	Code get_header   = untyped_str( txt( "#define array_get_header( Type, self ) ( (ArrayHeader*)( self ) - 1)\n" )); | ||||||
|  |  | ||||||
|  | 	return def_global_body( args( fmt_newline, td_header, header, get_header, fmt_newline ) ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | CodeBody gen_array( StrC type, StrC array_name ) | ||||||
|  | { | ||||||
|  | 	String array_type = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr ); | ||||||
|  | 	String fn         = String::fmt_buf( GlobalAllocator, "%.*s", array_name.Len, array_name.Ptr ); | ||||||
|  | 	str_to_lower(fn.Data); | ||||||
|  |  | ||||||
|  | #pragma push_macro( "GEN_ASSERT" ) | ||||||
|  | #undef GEN_ASSERT | ||||||
|  | 	CodeBody result = parse_global_body( token_fmt( "array_type", (StrC)array_type, "fn", (StrC)fn, "type", (StrC)type | ||||||
|  | 	, stringize( | ||||||
|  | 		typedef <type>* <array_type>; | ||||||
|  |  | ||||||
|  | 		<array_type> <fn>_init           ( AllocatorInfo allocator ); | ||||||
|  | 		<array_type> <fn>_init_reserve   ( AllocatorInfo allocator, usize capacity ); | ||||||
|  | 		bool         <fn>_append         ( <array_type>*  self, <type> value ); | ||||||
|  | 		bool         <fn>_append_items   ( <array_type>*  self, <type>* items, usize item_num ); | ||||||
|  | 		bool         <fn>_append_at      ( <array_type>*  self, <type> item, usize idx ); | ||||||
|  | 		bool         <fn>_append_items_at( <array_type>*  self, <type>* items, usize item_num, usize idx ); | ||||||
|  | 		<type>*      <fn>_back           ( <array_type>  self ); | ||||||
|  | 		void         <fn>_clear          ( <array_type>  self ); | ||||||
|  | 		bool         <fn>_fill		     ( <array_type>  self, usize begin, usize end, <type> value ); | ||||||
|  | 		void         <fn>_free           ( <array_type>  self ); | ||||||
|  | 		bool         <fn>_grow           ( <array_type>* self, usize min_capacity ); | ||||||
|  | 		usize        <fn>_num            ( <array_type>  self ); | ||||||
|  | 		<type>       <fn>_pop 	         ( <array_type>  self ); | ||||||
|  | 		bool         <fn>_reserve        ( <array_type>* self, usize new_capacity ); | ||||||
|  | 		bool         <fn>_resize         ( <array_type>* self, usize num ); | ||||||
|  | 		bool         <fn>_set_capacity   ( <array_type>* self, usize new_capacity ); | ||||||
|  |  | ||||||
|  | 		<array_type> <fn>_init( AllocatorInfo allocator ) | ||||||
|  | 		{ | ||||||
|  | 			return <fn>_init_reserve( allocator, array_grow_formula( 0 ) ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<array_type> <fn>_init_reserve( AllocatorInfo allocator, usize capacity ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = cast(ArrayHeader*, alloc( allocator, sizeof(ArrayHeader) + sizeof(<type>) * capacity ) ); | ||||||
|  |  | ||||||
|  | 			if ( header == NULL ) | ||||||
|  | 				return NULL; | ||||||
|  |  | ||||||
|  | 			header->Allocator = allocator; | ||||||
|  | 			header->Capacity  = capacity; | ||||||
|  | 			header->Num       = 0; | ||||||
|  |  | ||||||
|  | 			return cast( <type>*, header + 1 ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_append( <array_type>* self, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num == header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! <fn>_grow( self, header->Capacity)) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			(* self)[ header->Num ] = value; | ||||||
|  | 			header->Num++; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_append_items( <array_type>* self, <type>* items, usize item_num ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num + item_num > header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! <fn>_grow( self, header->Capacity + item_num )) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			mem_copy( (* self) + header->Num, items, sizeof(<type>) * item_num ); | ||||||
|  | 			header->Num += item_num; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_append_at( <array_type>* self, <type> item, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( idx >= header->Num ) | ||||||
|  | 				idx = header->Num - 1; | ||||||
|  |  | ||||||
|  | 			if ( idx < 0 ) | ||||||
|  | 				idx = 0; | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < header->Num + 1 ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! <fn>_grow( self, header->Capacity + 1 ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<array_type> target = (* self) + idx; | ||||||
|  |  | ||||||
|  | 			mem_move( target + 1, target, (header->Num - idx) * sizeof(<type>) ); | ||||||
|  | 			header->Num++; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_append_items_at( <array_type>* self, <type>* items, usize item_num, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( idx >= header->Num ) | ||||||
|  | 			{ | ||||||
|  | 				return <fn>_append_items( self, items, item_num ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ( item_num > header->Capacity ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! <fn>_grow( self, item_num + header->Capacity ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<type>* target = (* self) + idx + item_num; | ||||||
|  | 			<type>* src    = (* self) + 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>* <fn>_back( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Num == 0 ) | ||||||
|  | 				return NULL; | ||||||
|  |  | ||||||
|  | 			return self + header->Num - 1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_clear( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  | 			header->Num = 0; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_fill( <array_type> self, usize begin, usize end, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  |  | ||||||
|  | 			if ( begin < 0 || end >= header->Num ) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = begin; idx < end; idx ++ ) | ||||||
|  | 				self[ idx ] = value; | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_free( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  | 			free( header->Allocator, header ); | ||||||
|  | 			self = NULL; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_grow( <array_type>* self, usize min_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header      = get_header( *self ); | ||||||
|  | 			usize       new_capacity = array_grow_formula( header->Capacity ); | ||||||
|  |  | ||||||
|  | 			if ( new_capacity < min_capacity ) | ||||||
|  | 				new_capacity = min_capacity; | ||||||
|  |  | ||||||
|  | 			return <fn>_set_capacity( self, new_capacity ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		usize <fn>_num( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			return get_header(self)->Num; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<type> <fn>_pop( <array_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  | 			GEN_ASSERT( header->Num > 0 ); | ||||||
|  |  | ||||||
|  | 			<type> result = self[ header->Num - 1 ]; | ||||||
|  | 			header->Num--; | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_remove_at( <array_type> self, usize idx ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( self ); | ||||||
|  | 			GEN_ASSERT( idx < header->Num ); | ||||||
|  |  | ||||||
|  | 			mem_move( self + idx, self + idx + 1, sizeof( <type> ) * ( header->Num - idx - 1 ) ); | ||||||
|  | 			header->Num--; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_reserve( <array_type>* self, usize new_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < new_capacity ) | ||||||
|  | 				return <fn>_set_capacity( self, new_capacity ); | ||||||
|  |  | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_resize( <array_type>* self, usize num ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( header->Capacity < num ) | ||||||
|  | 			{ | ||||||
|  | 				if ( ! <fn>_grow( self, num ) ) | ||||||
|  | 					return false; | ||||||
|  |  | ||||||
|  | 				header = get_header( * self ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			header->Num = num; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		bool <fn>_set_capacity( <array_type>* self, usize new_capacity ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* header = get_header( * self ); | ||||||
|  |  | ||||||
|  | 			if ( new_capacity == header->Capacity ) | ||||||
|  | 				return true; | ||||||
|  |  | ||||||
|  | 			if ( new_capacity < header->Num ) | ||||||
|  | 				header->Num = new_capacity; | ||||||
|  |  | ||||||
|  | 			usize       size       = sizeof( ArrayHeader ) + sizeof( <type> ) * new_capacity; | ||||||
|  | 			ArrayHeader* new_header = cast( ArrayHeader*, alloc( header->Allocator, size )); | ||||||
|  |  | ||||||
|  | 			if ( new_header == NULL ) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
|  | 			mem_move( new_header, header, sizeof( ArrayHeader ) + sizeof( <type> ) * header->Num ); | ||||||
|  | 			free( header->Allocator, & header ); | ||||||
|  |  | ||||||
|  | 			new_header->Capacity = new_capacity; | ||||||
|  | 			* self = cast( <type>*, new_header + 1 ); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	))); | ||||||
|  | #pragma pop_macro( "GEN_ASSERT" ) | ||||||
|  |  | ||||||
|  | 	return def_global_body( args( | ||||||
|  | 		def_pragma( to_str( str_fmt_buf( "region %S", array_type ))), | ||||||
|  | 		fmt_newline, | ||||||
|  | 		result, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		def_pragma( to_str( str_fmt_buf( "endregion %S", array_type ))), | ||||||
|  | 		fmt_newline | ||||||
|  | 	)); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // CodeBody gen_ | ||||||
							
								
								
									
										354
									
								
								gen_c_library/components/containers.hashtable.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								gen_c_library/components/containers.hashtable.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  | #include "containers.array.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | CodeBody gen_hashtable_base() | ||||||
|  | { | ||||||
|  | 	return parse_global_body( code( | ||||||
|  | 		typedef struct HT_FindResult HT_FindResult; | ||||||
|  | 		struct HT_FindResult | ||||||
|  | 		{ | ||||||
|  | 			ssize HashIndex; | ||||||
|  | 			ssize PrevIndex; | ||||||
|  | 			ssize EntryIndex; | ||||||
|  | 		}; | ||||||
|  | 	)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | ||||||
|  | { | ||||||
|  | 	String | ||||||
|  | 	fn = String::make_reserve( GlobalAllocator, hashtable_name.Len + sizeof("gen") ); | ||||||
|  | 	fn.append_fmt( "%.*s", hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  | 	str_to_lower(fn.Data); | ||||||
|  |  | ||||||
|  | 	String | ||||||
|  | 	tbl_type = String::make_reserve( GlobalAllocator, hashtable_name.Len + sizeof("gen") ); | ||||||
|  | 	tbl_type.append_fmt( "%.*s", hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  |  | ||||||
|  | 	String name_lower = String::make( GlobalAllocator, hashtable_name ); | ||||||
|  | 	str_to_lower( name_lower.Data ); | ||||||
|  |  | ||||||
|  | 	String hashtable_entry   = String::fmt_buf( GlobalAllocator, "HTE_%.*s",     hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  | 	String entry_array_name  = String::fmt_buf( GlobalAllocator, "Arr_HTE_%.*s", hashtable_name.Len, hashtable_name.Ptr ); | ||||||
|  | 	String entry_array_fn_ns = String::fmt_buf( GlobalAllocator, "arr_hte_%.*s", name_lower.length(), name_lower.Data ); | ||||||
|  |  | ||||||
|  | 	CodeBody hashtable_types = parse_global_body( token_fmt( | ||||||
|  | 		"type",        (StrC) type, | ||||||
|  | 		"tbl_name",    (StrC) hashtable_name, | ||||||
|  | 		"tbl_type",    (StrC) tbl_type, | ||||||
|  | 	stringize( | ||||||
|  | 		typedef struct HTE_<tbl_name> HTE_<tbl_name>; | ||||||
|  | 		struct HTE_<tbl_name> | ||||||
|  | 		{ | ||||||
|  | 			u64    Key; | ||||||
|  | 			ssize  Next; | ||||||
|  | 			<type> Value; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		typedef void (* <tbl_type>_MapProc)    ( <tbl_type> self, u64 key, <type> value ); | ||||||
|  | 		typedef void (* <tbl_type>_MapMutProc) ( <tbl_type> self, u64 key, <type>* value ); | ||||||
|  | 	))); | ||||||
|  |  | ||||||
|  | 	CodeBody entry_array = gen_array( hashtable_entry, entry_array_name ); | ||||||
|  |  | ||||||
|  | #pragma push_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma push_macro( "GEN_ASSERT_NOT_NULL" ) | ||||||
|  | #undef GEN_ASSERT | ||||||
|  | #undef GEN_ASSERT_NOT_NULL | ||||||
|  | 	CodeBody hashtable_def = parse_global_body( token_fmt( | ||||||
|  | 		"type",           (StrC) type, | ||||||
|  | 		"tbl_name",       (StrC) hashtable_name, | ||||||
|  | 		"tbl_type",       (StrC) tbl_type, | ||||||
|  | 		"fn",             (StrC) fn, | ||||||
|  | 		"entry_type",     (StrC) hashtable_entry, | ||||||
|  | 		"array_entry",    (StrC) entry_array_name, | ||||||
|  | 		"fn_array",       (StrC) entry_array_fn_ns, | ||||||
|  | 	stringize( | ||||||
|  | 		typedef struct <tbl_type> <tbl_type>; | ||||||
|  | 		struct <tbl_type> | ||||||
|  | 		{ | ||||||
|  | 			Array_ssize   Hashes; | ||||||
|  | 			<array_entry> Entries; | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>_make        ( AllocatorInfo allocator ); | ||||||
|  | 		<tbl_type> <fn>_make_reserve( AllocatorInfo allocator, ssize num ); | ||||||
|  | 		void       <fn>_clear       ( <tbl_type> self ); | ||||||
|  | 		void       <fn>_destroy     ( <tbl_type> self ); | ||||||
|  | 		<type>*    <fn>_get         ( <tbl_type> self, u64 key ); | ||||||
|  | 		void       <fn>_map         ( <tbl_type> self, <tbl_type>_MapProc map_proc ); | ||||||
|  | 		void       <fn>_map_mut     ( <tbl_type> self, <tbl_type>_MapMutProc map_proc ); | ||||||
|  | 		void       <fn>_grow        ( <tbl_type>* self ); | ||||||
|  | 		void       <fn>_rehash      ( <tbl_type>* self, ssize new_num ); | ||||||
|  | 		void       <fn>_rehash_fast ( <tbl_type> self ); | ||||||
|  | 		void       <fn>_remove      ( <tbl_type> self, u64 key ); | ||||||
|  | 		void       <fn>_remove_entry( <tbl_type> self, ssize idx ); | ||||||
|  | 		void       <fn>_set         ( <tbl_type>* self, u64 key, <type> value ); | ||||||
|  | 		ssize         <fn>_slot        ( <tbl_type> self, u64 key ); | ||||||
|  |  | ||||||
|  | 		ssize            <fn>__add_entry( <tbl_type> self, u64 key ); | ||||||
|  | 		HT_FindResult <fn>__find     ( <tbl_type> self, u64 key ); | ||||||
|  | 		b32           <fn>__full     ( <tbl_type> self ); | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>_make( AllocatorInfo allocator ) | ||||||
|  | 		{ | ||||||
|  | 			<tbl_type> | ||||||
|  | 			result        = { NULL, NULL }; | ||||||
|  | 			result.Hashes  = array_ssize_make( allocator ); | ||||||
|  | 			result.Entries = <fn_array>_make( allocator ); | ||||||
|  |  | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<tbl_type> <fn>_make_reserve( AllocatorInfo allocator, ssize num ) | ||||||
|  | 		{ | ||||||
|  | 			<tbl_type> | ||||||
|  | 			result         = { NULL, NULL }; | ||||||
|  | 			result.Hashes  = array_ssize_make_reserve( allocator, num ); | ||||||
|  | 			result.Entries = <fn_array>_make_reserve( allocator, num ); | ||||||
|  |  | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_clear( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			for ( ssize idx = 0; idx < array_header( self.Hashes )->Num; idx++ ) | ||||||
|  | 				self.Hashes[idx] = -1; | ||||||
|  |  | ||||||
|  | 			array_ssize_clear( self.Hashes ); | ||||||
|  | 			<fn_array>_clear( self.Entries ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_destroy( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			if ( self.Hashes && self.Entries ) | ||||||
|  | 			{ | ||||||
|  | 				array_ssize_free( self.Hashes ); | ||||||
|  | 				<fn_array>_free( self.Entries ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		<type>* <fn>_get( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			ssize idx = <fn>__find( self, key ).EntryIndex; | ||||||
|  | 			if ( idx > 0 ) | ||||||
|  | 				return & self.Entries[idx].Value; | ||||||
|  |  | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_map( <tbl_type> self, <tbl_type>_MapProc map_proc ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL( map_proc ); | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = 0; idx < array_header( self.Entries )->Num; idx++ ) | ||||||
|  | 			{ | ||||||
|  | 				map_proc( self, self.Entries[idx].Key, self.Entries[idx].Value ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_map_mut( <tbl_type> self, <tbl_type>_MapMutProc map_proc ) | ||||||
|  | 		{ | ||||||
|  | 			GEN_ASSERT_NOT_NULL( map_proc ); | ||||||
|  |  | ||||||
|  | 			for ( ssize idx = 0; idx < array_header( self.Entries )->Num; idx++ ) | ||||||
|  | 			{ | ||||||
|  | 				map_proc( self, self.Entries[idx].Key, & self.Entries[idx].Value ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_grow( <tbl_type>* self ) | ||||||
|  | 		{ | ||||||
|  | 			ssize new_num = array_grow_formula( array_header( self->Entries )->Num ); | ||||||
|  | 			<fn>_rehash( self, new_num ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_rehash( <tbl_type>* self, ssize new_num ) | ||||||
|  | 		{ | ||||||
|  | 			ssize idx; | ||||||
|  | 			ssize last_added_index; | ||||||
|  |  | ||||||
|  | 			ArrayHeader* old_hash_header    = array_header( self->Hashes ); | ||||||
|  | 			ArrayHeader* old_entries_header = array_header( self->Entries ); | ||||||
|  |  | ||||||
|  | 			<tbl_type> new_tbl = <fn>_make_reserve( old_hash_header->Allocator, old_hash_header->Num ); | ||||||
|  |  | ||||||
|  | 			ArrayHeader* new_hash_header = array_header( new_tbl.Hashes ); | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < new_hash_header->Num; idx++ ) | ||||||
|  | 				new_tbl.Hashes[idx] = -1; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < old_entries_header->Num; idx++ ) | ||||||
|  | 			{ | ||||||
|  | 				<entry_type>*  entry; | ||||||
|  | 				HT_FindResult  find_result; | ||||||
|  |  | ||||||
|  | 				if ( new_hash_header->Num == 0 ) | ||||||
|  | 					<fn>_grow( & new_tbl ); | ||||||
|  |  | ||||||
|  | 				entry            = & self->Entries[ idx ]; | ||||||
|  | 				find_result      = <fn>__find( new_tbl, entry->Key ); | ||||||
|  | 				last_added_index = <fn>__add_entry( new_tbl, entry->Key ); | ||||||
|  |  | ||||||
|  | 				if ( find_result.PrevIndex < 0 ) | ||||||
|  | 					new_tbl.Hashes[ find_result.HashIndex ] = last_added_index; | ||||||
|  | 				else | ||||||
|  | 					new_tbl.Entries[ find_result.PrevIndex ].Next = last_added_index; | ||||||
|  |  | ||||||
|  | 				new_tbl.Entries[ last_added_index ].Next  = find_result.EntryIndex; | ||||||
|  | 				new_tbl.Entries[ last_added_index ].Value = entry->Value; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			<fn>_destroy( *self ); | ||||||
|  | 			* self = new_tbl; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_rehash_fast( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ssize idx; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_header( self.Entries )->Num; idx++ ) | ||||||
|  | 				self.Entries[ idx ].Next = -1; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_header( self.Hashes )->Num; idx++ ) | ||||||
|  | 				self.Hashes[ idx ] = -1; | ||||||
|  |  | ||||||
|  | 			for ( idx = 0; idx < array_header( self.Entries )->Num; idx++ ) | ||||||
|  | 			{ | ||||||
|  | 				<entry_type>*     entry; | ||||||
|  | 				HT_FindResult find_result; | ||||||
|  |  | ||||||
|  | 				entry       = & self.Entries[ idx ]; | ||||||
|  | 				find_result = <fn>__find( self, entry->Key ); | ||||||
|  |  | ||||||
|  | 				if ( find_result.PrevIndex < 0 ) | ||||||
|  | 					self.Hashes[ find_result.HashIndex ] = idx; | ||||||
|  | 				else | ||||||
|  | 					self.Entries[ find_result.PrevIndex ].Next = idx; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_remove( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			HT_FindResult find_result = <fn>__find( self, key ); | ||||||
|  |  | ||||||
|  | 			if ( find_result.EntryIndex >= 0 ) | ||||||
|  | 			{ | ||||||
|  | 				<fn_array>_remove_at( self.Entries, find_result.EntryIndex ); | ||||||
|  | 				<fn>_rehash_fast( self ); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_remove_entry( <tbl_type> self, ssize idx ) | ||||||
|  | 		{ | ||||||
|  | 			<fn_array>_remove_at( self.Entries, idx ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		void <fn>_set( <tbl_type>* self, u64 key, <type> value ) | ||||||
|  | 		{ | ||||||
|  | 			ssize            idx; | ||||||
|  | 			HT_FindResult find_result; | ||||||
|  |  | ||||||
|  | 			if ( array_header( self->Hashes )->Num == 0 ) | ||||||
|  | 				<fn>_grow( self ); | ||||||
|  |  | ||||||
|  | 			find_result = <fn>__find( * self, key ); | ||||||
|  |  | ||||||
|  | 			if ( find_result.EntryIndex >= 0 ) | ||||||
|  | 			{ | ||||||
|  | 				idx = find_result.EntryIndex; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				idx = <fn>__add_entry( * self, key ); | ||||||
|  |  | ||||||
|  | 				if ( find_result.PrevIndex >= 0 ) | ||||||
|  | 				{ | ||||||
|  | 					self->Entries[ find_result.PrevIndex ].Next = idx; | ||||||
|  | 				} | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					self->Hashes[ find_result.HashIndex ] = idx; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			self->Entries[ idx ].Value = value; | ||||||
|  |  | ||||||
|  | 			if ( <fn>__full( * self ) ) | ||||||
|  | 				<fn>_grow( self ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ssize <fn>_slot( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			for ( ssize idx = 0; idx < array_header( self.Hashes )->Num; ++idx ) | ||||||
|  | 				if ( self.Hashes[ idx ] == key ) | ||||||
|  | 					return idx; | ||||||
|  |  | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ssize <fn>__add_entry( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			ssize idx; | ||||||
|  | 			<entry_type> entry = { key, -1 }; | ||||||
|  |  | ||||||
|  | 			idx = array_header( self.Entries )->Num; | ||||||
|  | 			<fn_array>_append( & self.Entries, entry ); | ||||||
|  | 			return idx; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		HT_FindResult <fn>__find( <tbl_type> self, u64 key ) | ||||||
|  | 		{ | ||||||
|  | 			HT_FindResult result = { -1, -1, -1 }; | ||||||
|  |  | ||||||
|  | 			ArrayHeader* hash_header = array_header( self.Hashes ); | ||||||
|  |  | ||||||
|  | 			if ( hash_header->Num > 0 ) | ||||||
|  | 			{ | ||||||
|  | 				result.HashIndex  = key % hash_header->Num; | ||||||
|  | 				result.EntryIndex = self.Hashes[ result.HashIndex ]; | ||||||
|  |  | ||||||
|  | 				while ( result.EntryIndex >= 0 ) | ||||||
|  | 				{ | ||||||
|  | 					if ( self.Entries[ result.EntryIndex ].Key == key ) | ||||||
|  | 						break; | ||||||
|  |  | ||||||
|  | 					result.PrevIndex  = result.EntryIndex; | ||||||
|  | 					result.EntryIndex = self.Entries[ result.EntryIndex ].Next; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return result; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		b32 <fn>__full( <tbl_type> self ) | ||||||
|  | 		{ | ||||||
|  | 			ArrayHeader* hash_header    = array_header( self.Hashes ); | ||||||
|  | 			ArrayHeader* entries_header = array_header( self.Entries ); | ||||||
|  |  | ||||||
|  | 			return 0.75f * hash_header->Num < entries_header->Num; | ||||||
|  | 		} | ||||||
|  | 	))); | ||||||
|  | #pragma pop_macro( "GEN_ASSERT" ) | ||||||
|  | #pragma pop_macro( "GEN_ASSERT_NOT_NULL" ) | ||||||
|  |  | ||||||
|  | 	char const* cmt_str = str_fmt_buf( "Name: %.*s Type: %.*s" | ||||||
|  | 		, tbl_type.length(), tbl_type.Data | ||||||
|  | 		, type.Len, type.Ptr ); | ||||||
|  |  | ||||||
|  | 	return def_global_body(args( | ||||||
|  | 		def_pragma( to_str( str_fmt_buf( "region %S", tbl_type ))), | ||||||
|  | 		fmt_newline, | ||||||
|  | 		hashtable_types, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		entry_array, | ||||||
|  | 		hashtable_def, | ||||||
|  | 		fmt_newline, | ||||||
|  | 		def_pragma( to_str( str_fmt_buf( "endregion %S", tbl_type ))), | ||||||
|  | 		fmt_newline | ||||||
|  | 	)); | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								gen_c_library/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								gen_c_library/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | /* | ||||||
|  | 	gencpp: An attempt at "simple" staged metaprogramming for c/c++. | ||||||
|  |  | ||||||
|  | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
|  | 	Public Address: | ||||||
|  | 	https://github.com/Ed94/gencpp | ||||||
|  |  | ||||||
|  | 	This is a single header C-Library variant. | ||||||
|  | 	Define GEN_IMPLEMENTATION before including this file in a single compilation unit. | ||||||
|  | */ | ||||||
|  | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
|  | #	error Gen.hpp : GEN_TIME not defined | ||||||
|  | #endif | ||||||
							
								
								
									
										122
									
								
								gen_c_library/components/memory.fixed_arena.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								gen_c_library/components/memory.fixed_arena.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | CodeBody gen_fixed_arenas() | ||||||
|  | { | ||||||
|  | 	CodeBody result = def_body(ECode::Global_Body); | ||||||
|  | 	result.append(def_pragma(txt("region FixedArena"))); | ||||||
|  |  | ||||||
|  | 	char const* template_struct = stringize( | ||||||
|  | 		struct FixedArena_<Name> | ||||||
|  | 		{ | ||||||
|  | 			char  memory[<Size>]; | ||||||
|  | 			Arena arena; | ||||||
|  | 		}; | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	char const* template_interface = stringize( | ||||||
|  | 		inline | ||||||
|  | 		void fixed_arena_init_<Name>(FixedArena_<Name>* result) { | ||||||
|  | 			zero_size(& result->memory[0], <Size>); | ||||||
|  | 			result.arena = arena_init_from_memory(& result->memory[0], <Size>); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline | ||||||
|  | 		ssize fixed_arena_size_remaining_<Name>(FixedArena_<Name>* fixed_arena, ssize alignment) { | ||||||
|  | 			return size_remaining(fixed_arena->arena, alignment); | ||||||
|  | 		} | ||||||
|  | 	); | ||||||
|  |  | ||||||
|  | 	CodeStruct arena_struct_1kb   = parse_struct( token_fmt_impl( 3, "Name", txt("1KB"),   "Size", txt("kilobytes(1)"),   template_struct )); | ||||||
|  | 	CodeStruct arena_struct_4kb   = parse_struct( token_fmt_impl( 3, "Name", txt("4KB"),   "Size", txt("kilobytes(4)"),   template_struct )); | ||||||
|  | 	CodeStruct arena_struct_8kb   = parse_struct( token_fmt_impl( 3, "Name", txt("8KB"),   "Size", txt("kilobytes(8)"),   template_struct )); | ||||||
|  | 	CodeStruct arena_struct_16kb  = parse_struct( token_fmt_impl( 3, "Name", txt("16KB"),  "Size", txt("kilobytes(16)"),  template_struct )); | ||||||
|  | 	CodeStruct arena_struct_32kb  = parse_struct( token_fmt_impl( 3, "Name", txt("32KB"),  "Size", txt("kilobytes(32)"),  template_struct )); | ||||||
|  | 	CodeStruct arena_struct_64kb  = parse_struct( token_fmt_impl( 3, "Name", txt("64KB"),  "Size", txt("kilobytes(64)"),  template_struct )); | ||||||
|  | 	CodeStruct arena_struct_128kb = parse_struct( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_struct )); | ||||||
|  | 	CodeStruct arena_struct_256kb = parse_struct( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_struct )); | ||||||
|  | 	CodeStruct arena_struct_512kb = parse_struct( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_struct )); | ||||||
|  | 	CodeStruct arena_struct_1mb   = parse_struct( token_fmt_impl( 3, "Name", txt("1MB"),   "Size", txt("megabytes(1)"),   template_struct )); | ||||||
|  | 	CodeStruct arena_struct_2mb   = parse_struct( token_fmt_impl( 3, "Name", txt("2MB"),   "Size", txt("megabytes(2)"),   template_struct )); | ||||||
|  | 	CodeStruct arena_struct_4mb   = parse_struct( token_fmt_impl( 3, "Name", txt("4MB"),   "Size", txt("megabytes(4)"),   template_struct )); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	CodeBody arena_interface_1kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1KB"),   "Size", txt("kilobytes(1)"),    template_interface )); | ||||||
|  | 	CodeBody arena_interface_4kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4KB"),   "Size", txt("kilobytes(4)"),    template_interface )); | ||||||
|  | 	CodeBody arena_interface_8kb   = parse_global_body( token_fmt_impl( 3, "Name", txt("8KB"),   "Size", txt("kilobytes(8)"),    template_interface )); | ||||||
|  | 	CodeBody arena_interface_16kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("16KB"),  "Size", txt("kilobytes(16)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_32kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("32KB"),  "Size", txt("kilobytes(32)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_64kb  = parse_global_body( token_fmt_impl( 3, "Name", txt("64KB"),  "Size", txt("kilobytes(64)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_128kb = parse_global_body( token_fmt_impl( 3, "Name", txt("128KB"), "Size", txt("kilobytes(128)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_256kb = parse_global_body( token_fmt_impl( 3, "Name", txt("256KB"), "Size", txt("kilobytes(256)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_512kb = parse_global_body( token_fmt_impl( 3, "Name", txt("512KB"), "Size", txt("kilobytes(512)"), template_interface )); | ||||||
|  | 	CodeBody arena_interface_1mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("1MB"),   "Size", txt("megabytes(1)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_2mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("2MB"),   "Size", txt("megabytes(2)"),   template_interface )); | ||||||
|  | 	CodeBody arena_interface_4mb   = parse_global_body( token_fmt_impl( 3, "Name", txt("4MB"),   "Size", txt("megabytes(4)"),   template_interface )); | ||||||
|  |  | ||||||
|  | 	result.append(arena_struct_1kb); | ||||||
|  | 	result.append(arena_struct_4kb); | ||||||
|  | 	result.append(arena_struct_8kb); | ||||||
|  | 	result.append(arena_struct_16kb); | ||||||
|  | 	result.append(arena_struct_32kb); | ||||||
|  | 	result.append(arena_struct_128kb); | ||||||
|  | 	result.append(arena_struct_256kb); | ||||||
|  | 	result.append(arena_struct_512kb); | ||||||
|  | 	result.append(arena_struct_1mb); | ||||||
|  | 	result.append(arena_struct_2mb); | ||||||
|  | 	result.append(arena_struct_4mb); | ||||||
|  |  | ||||||
|  | 	result.append(arena_interface_1kb); | ||||||
|  | 	result.append(arena_interface_4kb); | ||||||
|  | 	result.append(arena_interface_8kb); | ||||||
|  | 	result.append(arena_interface_16kb); | ||||||
|  | 	result.append(arena_interface_32kb); | ||||||
|  | 	result.append(arena_interface_128kb); | ||||||
|  | 	result.append(arena_interface_256kb); | ||||||
|  | 	result.append(arena_interface_512kb); | ||||||
|  | 	result.append(arena_interface_1mb); | ||||||
|  | 	result.append(arena_interface_2mb); | ||||||
|  | 	result.append(arena_interface_4mb); | ||||||
|  |  | ||||||
|  | 	CodeDefine def = def_define(txt("fixed_arena_allocator_info(fixed_arena)"), code({ arena_allocator_proc, & fixed_arena.arena }) ); | ||||||
|  | 	result.append(def); | ||||||
|  |  | ||||||
|  | 	result.append(parse_global_body(txt(R"( | ||||||
|  | #define fixed_arena_init(expr) _Generic((expr), \ | ||||||
|  |     FixedArena_1KB*   : fixed_arena_init_1KB,   \ | ||||||
|  |     FixedArena_4KB*   : fixed_arena_init_4KB,   \ | ||||||
|  |     FixedArena_8KB*   : fixed_arena_init_8KB,   \ | ||||||
|  |     FixedArena_16KB*  : fixed_arena_init_16KB,  \ | ||||||
|  |     FixedArena_32KB*  : fixed_arena_init_32KB,  \ | ||||||
|  |     FixedArena_64KB*  : fixed_arena_init_64KB,  \ | ||||||
|  |     FixedArena_128KB* : fixed_arena_init_128KB, \ | ||||||
|  |     FixedArena_256KB* : fixed_arena_init_256KB, \ | ||||||
|  |     FixedArena_512KB* : fixed_arena_init_512KB, \ | ||||||
|  |     FixedArena_1MB*   : fixed_arena_init_1MB,   \ | ||||||
|  |     FixedArena_2MB*   : fixed_arena_init_2MB,   \ | ||||||
|  |     FixedArena_4MB*   : fixed_arena_init_4MB    \ | ||||||
|  | )(expr) | ||||||
|  |  | ||||||
|  | #define fixed_arena_size_remaining(expr, alignment) _Generic((expr), \ | ||||||
|  |     FixedArena_1KB*   : fixed_arena_size_remaining_1KB,              \ | ||||||
|  |     FixedArena_4KB*   : fixed_arena_size_remaining_4KB,              \ | ||||||
|  |     FixedArena_8KB*   : fixed_arena_size_remaining_8KB,              \ | ||||||
|  |     FixedArena_16KB*  : fixed_arena_size_remaining_16KB,             \ | ||||||
|  |     FixedArena_32KB*  : fixed_arena_size_remaining_32KB,             \ | ||||||
|  |     FixedArena_64KB*  : fixed_arena_size_remaining_64KB,             \ | ||||||
|  |     FixedArena_128KB* : fixed_arena_size_remaining_128KB,            \ | ||||||
|  |     FixedArena_256KB* : fixed_arena_size_remaining_256KB,            \ | ||||||
|  |     FixedArena_512KB* : fixed_arena_size_remaining_512KB,            \ | ||||||
|  |     FixedArena_1MB*   : fixed_arena_size_remaining_1MB,              \ | ||||||
|  |     FixedArena_2MB*   : fixed_arena_size_remaining_2MB,              \ | ||||||
|  |     FixedArena_4MB*   : fixed_arena_size_remaining_4MB               \ | ||||||
|  | )(expr, alignment) | ||||||
|  | )" | ||||||
|  | 	))); | ||||||
|  |  | ||||||
|  | 	result.append(def_pragma(txt("endregion FixedArena"))); | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								gen_c_library/components/misc.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								gen_c_library/components/misc.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | // #pragma once | ||||||
|  | // #include "../project/gen.hpp" | ||||||
|  |  | ||||||
|  | // using namespace gen; | ||||||
|  |  | ||||||
|  | using SwapContentProc = CodeBody(void); | ||||||
|  |  | ||||||
|  | b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& body ) | ||||||
|  | { | ||||||
|  | 	b32 found = false; | ||||||
|  | 	CodePreprocessCond cond = entry_iter.cast<CodePreprocessCond>(); | ||||||
|  | 	if ( cond->Content.contains(cond_sig) ) | ||||||
|  | 	{ | ||||||
|  | 		log_fmt("Preprocess cond found: %S\n", cond->Content); | ||||||
|  | 		found = true; | ||||||
|  |  | ||||||
|  | 		s32 depth = 1; | ||||||
|  | 		++ entry_iter; for(b32 continue_for = true; continue_for && entry_iter != body.end(); ) switch | ||||||
|  | 		(entry_iter->Type) { | ||||||
|  | 			case ECode::Preprocess_If: | ||||||
|  | 			case ECode::Preprocess_IfDef: | ||||||
|  | 			case ECode::Preprocess_IfNotDef: | ||||||
|  | 				depth ++; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case ECode::Preprocess_EndIf: | ||||||
|  | 			{ | ||||||
|  | 				depth --; | ||||||
|  | 				if (depth == 0) { | ||||||
|  | 					continue_for = false; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 			default: | ||||||
|  | 				++ entry_iter; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return found; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body ) | ||||||
|  | { | ||||||
|  | 	bool found = false; | ||||||
|  | 	CodePragma possible_region = entry_iter.cast<CodePragma>(); | ||||||
|  |  | ||||||
|  | 	String region_sig    = string_fmt_buf(GlobalAllocator, "region %s",    region_name.Ptr); | ||||||
|  | 	String endregion_sig = string_fmt_buf(GlobalAllocator, "endregion %s", region_name.Ptr); | ||||||
|  | 	if ( possible_region->Content.contains(region_sig)) | ||||||
|  | 	{ | ||||||
|  | 		found = true; | ||||||
|  | 		// body.append(possible_region); | ||||||
|  | 		body.append(swap_content()); | ||||||
|  |  | ||||||
|  | 		++ entry_iter; for(b32 continue_for = true; continue_for; ++entry_iter) switch | ||||||
|  | 		(entry_iter->Type) { | ||||||
|  | 			case ECode::Preprocess_Pragma: | ||||||
|  | 			{ | ||||||
|  | 				CodePragma possible_end_region = entry_iter.cast<CodePragma>(); | ||||||
|  | 				if ( possible_end_region->Content.contains(endregion_sig) ) { | ||||||
|  | 					// body.append(possible_end_region); | ||||||
|  | 					continue_for = false; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		body.append(entry_iter); | ||||||
|  | 	} | ||||||
|  | 	return found; | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| # Singleheader | # Singleheader | ||||||
| 
 | 
 | ||||||
| Creates a single header file version of the library using `gen.singleheader.cpp`. | Creates a single header file version of the library using `singleheader.cpp`. | ||||||
| Follows the same convention seen in the gb, stb, and zpl libraries. | Follows the same convention seen in the gb, stb, and zpl libraries. | ||||||
| @@ -12,12 +12,3 @@ | |||||||
| #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
| #	error Gen.hpp : GEN_TIME not defined | #	error Gen.hpp : GEN_TIME not defined | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
| #ifdef GEN_DONT_USE_NAMESPACE |  | ||||||
| #	define GEN_NS_BEGIN |  | ||||||
| #	define GEN_NS_END |  | ||||||
| #else |  | ||||||
| #	define GEN_NS_BEGIN namespace gen { |  | ||||||
| #	define GEN_NS_END   } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| @@ -14,6 +14,8 @@ GEN_NS_END | |||||||
| #include "auxillary/builder.cpp" | #include "auxillary/builder.cpp" | ||||||
| #include "auxillary/scanner.hpp" | #include "auxillary/scanner.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include <cstdlib>   // for system()
 | ||||||
|  | 
 | ||||||
| using namespace gen; | using namespace gen; | ||||||
| 
 | 
 | ||||||
| constexpr char const* generation_notice = | constexpr char const* generation_notice = | ||||||
| @@ -35,7 +37,6 @@ constexpr StrC roll_own_dependencies_guard_start = txt(R"( | |||||||
| //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file.
 | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file.
 | ||||||
| // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl
 | // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl
 | ||||||
| #ifndef GEN_ROLL_OWN_DEPENDENCIES | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
| 
 |  | ||||||
| )"); | )"); | ||||||
| 
 | 
 | ||||||
| constexpr StrC roll_own_dependencies_guard_end = txt(R"( | constexpr StrC roll_own_dependencies_guard_end = txt(R"( | ||||||
| @@ -48,6 +49,42 @@ global bool generate_builder = true; | |||||||
| global bool generate_editor  = true; | global bool generate_editor  = true; | ||||||
| global bool generate_scanner = true; | global bool generate_scanner = true; | ||||||
| 
 | 
 | ||||||
|  | void format_file( char const* path ) | ||||||
|  | { | ||||||
|  | 	String resolved_path = String::make(GlobalAllocator, to_str(path)); | ||||||
|  | 
 | ||||||
|  | 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | ||||||
|  | 	style_arg.append("../scripts/.clang-format "); | ||||||
|  | 
 | ||||||
|  | 	// Need to execute clang format on the generated file to get it to match the original.
 | ||||||
|  | 	#define clang_format      "clang-format " | ||||||
|  | 	#define cf_format_inplace "-i " | ||||||
|  | 	#define cf_verbose        "-verbose " | ||||||
|  | 	String command = String::make( GlobalAllocator, clang_format ); | ||||||
|  | 	command.append( cf_format_inplace ); | ||||||
|  | 	command.append( cf_verbose ); | ||||||
|  | 	command.append( style_arg ); | ||||||
|  | 	command.append( resolved_path ); | ||||||
|  | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
|  | 		system( command ); | ||||||
|  | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
|  | 	#undef cf_cmd | ||||||
|  | 	#undef cf_format_inplace | ||||||
|  | 	#undef cf_style | ||||||
|  | 	#undef cf_verbse | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Code dump_to_scratch_and_retireve( Code code ) | ||||||
|  | { | ||||||
|  | 	Builder ecode_file_temp = Builder::open("gen/scratch.hpp"); | ||||||
|  | 	ecode_file_temp.print(code); | ||||||
|  | 	ecode_file_temp.write(); | ||||||
|  | 	format_file("gen/scratch.hpp"); | ||||||
|  | 	Code result = scan_file( "gen/scratch.hpp" ); | ||||||
|  | 	remove("gen/scratch.hpp"); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int gen_main() | int gen_main() | ||||||
| { | { | ||||||
| #define project_dir "../project/" | #define project_dir "../project/" | ||||||
| @@ -69,7 +106,7 @@ int gen_main() | |||||||
| 
 | 
 | ||||||
| 		if ( generate_gen_dep ) | 		if ( generate_gen_dep ) | ||||||
| 		{ | 		{ | ||||||
| 			Code header_start = scan_file( project_dir "dependencies/header_start.hpp" ); | 			Code platform     = scan_file( project_dir "dependencies/platform.hpp" ); | ||||||
| 			Code macros       = scan_file( project_dir "dependencies/macros.hpp" ); | 			Code macros       = scan_file( project_dir "dependencies/macros.hpp" ); | ||||||
| 			Code basic_types  = scan_file( project_dir "dependencies/basic_types.hpp" ); | 			Code basic_types  = scan_file( project_dir "dependencies/basic_types.hpp" ); | ||||||
| 			Code debug        = scan_file( project_dir "dependencies/debug.hpp" ); | 			Code debug        = scan_file( project_dir "dependencies/debug.hpp" ); | ||||||
| @@ -83,7 +120,7 @@ int gen_main() | |||||||
| 			Code timing       = scan_file( project_dir "dependencies/timing.hpp" ); | 			Code timing       = scan_file( project_dir "dependencies/timing.hpp" ); | ||||||
| 
 | 
 | ||||||
| 			header.print_fmt( roll_own_dependencies_guard_start ); | 			header.print_fmt( roll_own_dependencies_guard_start ); | ||||||
| 			header.print( header_start ); | 			header.print( platform ); | ||||||
| 			header.print_fmt( "\nGEN_NS_BEGIN\n" ); | 			header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
| 
 | 
 | ||||||
| 			header.print( macros ); | 			header.print( macros ); | ||||||
| @@ -127,9 +164,13 @@ int gen_main() | |||||||
| 
 | 
 | ||||||
| 		header.print_fmt("#pragma region Types\n"); | 		header.print_fmt("#pragma region Types\n"); | ||||||
| 		header.print( types ); | 		header.print( types ); | ||||||
| 		header.print( ecode ); | 		header.print( fmt_newline ); | ||||||
| 		header.print( eoperator ); | 		header.print( dump_to_scratch_and_retireve( ecode )); | ||||||
| 		header.print( especifier ); | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( eoperator )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve( especifier )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
| 		header.print_fmt("#pragma endregion Types\n\n"); | 		header.print_fmt("#pragma endregion Types\n\n"); | ||||||
| 
 | 
 | ||||||
| 		header.print_fmt("#pragma region AST\n"); | 		header.print_fmt("#pragma region AST\n"); | ||||||
| @@ -142,7 +183,8 @@ int gen_main() | |||||||
| 
 | 
 | ||||||
| 		header.print_fmt( "\n#pragma region Inlines\n" ); | 		header.print_fmt( "\n#pragma region Inlines\n" ); | ||||||
| 		header.print( inlines ); | 		header.print( inlines ); | ||||||
| 		header.print( ast_inlines ); | 		header.print( dump_to_scratch_and_retireve( ast_inlines )); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
| 		header.print_fmt( "#pragma endregion Inlines\n" ); | 		header.print_fmt( "#pragma endregion Inlines\n" ); | ||||||
| 
 | 
 | ||||||
| 		header.print( header_end ); | 		header.print( header_end ); | ||||||
| @@ -209,7 +251,7 @@ int gen_main() | |||||||
| 		Code untyped           = scan_file( project_dir "components/interface.untyped.cpp" ); | 		Code untyped           = scan_file( project_dir "components/interface.untyped.cpp" ); | ||||||
| 
 | 
 | ||||||
| 		CodeBody etoktype      = gen_etoktype( project_dir "enums/ETokType.csv", project_dir "enums/AttributeTokens.csv" ); | 		CodeBody etoktype      = gen_etoktype( project_dir "enums/ETokType.csv", project_dir "enums/AttributeTokens.csv" ); | ||||||
| 		CodeNS   parser_nspace = def_namespace( name(Parser), def_namespace_body( args(etoktype)) ); | 		CodeNS   parser_nspace = def_namespace( name(parser), def_namespace_body( args(etoktype)) ); | ||||||
| 
 | 
 | ||||||
| 		header.print_fmt( "\nGEN_NS_BEGIN\n"); | 		header.print_fmt( "\nGEN_NS_BEGIN\n"); | ||||||
| 		header.print( static_data ); | 		header.print( static_data ); | ||||||
| @@ -224,7 +266,7 @@ int gen_main() | |||||||
| 		header.print( interface ); | 		header.print( interface ); | ||||||
| 		header.print( upfront ); | 		header.print( upfront ); | ||||||
| 		header.print_fmt( "\n#pragma region Parsing\n\n" ); | 		header.print_fmt( "\n#pragma region Parsing\n\n" ); | ||||||
| 		header.print( parser_nspace ); | 		header.print( dump_to_scratch_and_retireve(parser_nspace) ); | ||||||
| 		header.print( lexer ); | 		header.print( lexer ); | ||||||
| 		header.print( parser ); | 		header.print( parser ); | ||||||
| 		header.print( parsing_interface ); | 		header.print( parsing_interface ); | ||||||
							
								
								
									
										3
									
								
								gen_unreal_engine/Readme.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								gen_unreal_engine/Readme.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | # Unreal Engine Version Generator | ||||||
|  |  | ||||||
|  | This generates a variant of gencpp thats compatiable with use as a thirdparty module within a plugin or module of an Unreal Project or the Engine itself. | ||||||
							
								
								
									
										31
									
								
								gen_unreal_engine/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								gen_unreal_engine/components/header_start.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | /* | ||||||
|  | 	gencpp: An attempt at "simple" staged metaprogramming for c/c++. | ||||||
|  |  | ||||||
|  | 	See Readme.md for more information from the project repository. | ||||||
|  |  | ||||||
|  | 	Public Address: | ||||||
|  | 	https://github.com/Ed94/gencpp | ||||||
|  |  | ||||||
|  | 	This is a variant intended for use with Unreal Engine 5 | ||||||
|  | */ | ||||||
|  | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
|  | #	error Gen.hpp : GEN_TIME not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | ||||||
|  | // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | ||||||
|  | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | #	include "gen.dep.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef GEN_NS_BEGIN | ||||||
|  | #	ifdef GEN_DONT_USE_NAMESPACE | ||||||
|  | #		define GEN_NS | ||||||
|  | #		define GEN_NS_BEGIN | ||||||
|  | #		define GEN_NS_END | ||||||
|  | #	else | ||||||
|  | #		define GEN_NS       gen:: | ||||||
|  | #		define GEN_NS_BEGIN namespace gen { | ||||||
|  | #		define GEN_NS_END   } | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
							
								
								
									
										5
									
								
								gen_unreal_engine/components/src_start.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								gen_unreal_engine/components/src_start.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | #if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) | ||||||
|  | #	error Gen.hpp : GEN_TIME not defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #include "gen.hpp" | ||||||
							
								
								
									
										7
									
								
								gen_unreal_engine/enums/AttributeTokens.csv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								gen_unreal_engine/enums/AttributeTokens.csv
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | API_Export,            GEN_API_Export_Code | ||||||
|  | API_Import,            GEN_API_Import_Code | ||||||
|  | COREUOBJECT_API,       COREUOBJECT_API | ||||||
|  | ENGINE_API,            ENGINE_API | ||||||
|  | GAMEPLAYABILITIES_API, GAMEPLAYABILITIES_API | ||||||
|  | UMG_API,               UMG_API | ||||||
|  | UE_DEPRECATED,         UE_DEPRECATED | ||||||
| 
 | 
							
								
								
									
										397
									
								
								gen_unreal_engine/unreal.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								gen_unreal_engine/unreal.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,397 @@ | |||||||
|  | #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
|  | #define GEN_ENFORCE_STRONG_CODE_TYPES | ||||||
|  | #define GEN_EXPOSE_BACKEND | ||||||
|  | #include "gen.cpp" | ||||||
|  |  | ||||||
|  | #include "helpers/push_ignores.inline.hpp" | ||||||
|  | #include "helpers/helper.hpp" | ||||||
|  |  | ||||||
|  | GEN_NS_BEGIN | ||||||
|  | #include "dependencies/parsing.cpp" | ||||||
|  | GEN_NS_END | ||||||
|  |  | ||||||
|  | #include "auxillary/builder.hpp" | ||||||
|  | #include "auxillary/builder.cpp" | ||||||
|  | #include "auxillary/scanner.hpp" | ||||||
|  |  | ||||||
|  | #include <cstdlib>   // for system() | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
|  | constexpr char const* generation_notice = | ||||||
|  | "// This file was generated automatially by gencpp's unreal.cpp " | ||||||
|  | "(See: https://github.com/Ed94/gencpp)\n\n"; | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_start = txt(R"( | ||||||
|  | #pragma region GENCPP IMPLEMENTATION GUARD | ||||||
|  | #if defined(GEN_IMPLEMENTATION) && ! defined(GEN_IMPLEMENTED) | ||||||
|  | #	define GEN_IMPLEMENTED | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC implementation_guard_end = txt(R"( | ||||||
|  | #endif | ||||||
|  | #pragma endregion GENCPP IMPLEMENTATION GUARD | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_start = txt(R"( | ||||||
|  | //! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. | ||||||
|  | // Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl | ||||||
|  | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  |  | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | constexpr StrC roll_own_dependencies_guard_end = txt(R"( | ||||||
|  | // GEN_ROLL_OWN_DEPENDENCIES | ||||||
|  | #endif | ||||||
|  | )"); | ||||||
|  |  | ||||||
|  | global bool generate_gen_dep = true; | ||||||
|  | global bool generate_builder = true; | ||||||
|  | global bool generate_editor  = true; | ||||||
|  | global bool generate_scanner = true; | ||||||
|  |  | ||||||
|  | void format_file( char const* path ) | ||||||
|  | { | ||||||
|  | 	String resolved_path = String::make(GlobalAllocator, to_str(path)); | ||||||
|  |  | ||||||
|  | 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | ||||||
|  | 	style_arg.append("../scripts/.clang-format "); | ||||||
|  |  | ||||||
|  | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
|  | 	#define clang_format      "clang-format " | ||||||
|  | 	#define cf_format_inplace "-i " | ||||||
|  | 	#define cf_verbose        "-verbose " | ||||||
|  | 	String command = String::make( GlobalAllocator, clang_format ); | ||||||
|  | 	command.append( cf_format_inplace ); | ||||||
|  | 	command.append( cf_verbose ); | ||||||
|  | 	command.append( style_arg ); | ||||||
|  | 	command.append( resolved_path ); | ||||||
|  | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
|  | 		system( command ); | ||||||
|  | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
|  | 	#undef cf_cmd | ||||||
|  | 	#undef cf_format_inplace | ||||||
|  | 	#undef cf_style | ||||||
|  | 	#undef cf_verbse | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code dump_to_scratch_and_retireve( Code code ) | ||||||
|  | { | ||||||
|  | 	Builder ecode_file_temp = Builder::open("gen/scratch.hpp"); | ||||||
|  | 	ecode_file_temp.print(code); | ||||||
|  | 	ecode_file_temp.write(); | ||||||
|  | 	format_file("gen/scratch.hpp"); | ||||||
|  | 	Code result = scan_file( "gen/scratch.hpp" ); | ||||||
|  | 	remove("gen/scratch.hpp"); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int gen_main() | ||||||
|  | { | ||||||
|  | #define project_dir "../project/" | ||||||
|  | 	gen::init(); | ||||||
|  |  | ||||||
|  | 	Code push_ignores        = scan_file( project_dir "helpers/push_ignores.inline.hpp" ); | ||||||
|  | 	Code pop_ignores         = scan_file( project_dir "helpers/pop_ignores.inline.hpp" ); | ||||||
|  |  | ||||||
|  | 	Code ue_forceinline = code_str(FORCEINLINE); | ||||||
|  | 	// Code | ||||||
|  |  | ||||||
|  | 	// gen_dep.hpp | ||||||
|  | 	{ | ||||||
|  | 		CodeBody macros = def_body( CodeT::Global_Body ); | ||||||
|  | 		{ | ||||||
|  | 			FileContents content    = file_read_contents( GlobalAllocator, true, project_dir "dependencies/macros.hpp" ); | ||||||
|  | 			CodeBody     ori_macros = parse_global_body( StrC { content.size, (char const*)content.data }); | ||||||
|  |  | ||||||
|  | 			for (Code	code =  ori_macros.begin(); | ||||||
|  | 						code != ori_macros.end(); | ||||||
|  | 						++ code ) | ||||||
|  | 			{ | ||||||
|  | 				switch (code->Type) | ||||||
|  | 				{ | ||||||
|  | 					using namespace ECode; | ||||||
|  | 					case Preprocess_Define: | ||||||
|  | 					{ | ||||||
|  | 						CodeDefine define = code.cast<CodeDefine>(); | ||||||
|  | 						if ( define->Name.starts_with(txt("global")) ) | ||||||
|  | 						{ | ||||||
|  | 							macros.append(parse_global_body(txt("#define global // Global variables"))); | ||||||
|  | 							continue; | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						macros.append(define); | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 					default: | ||||||
|  | 						macros.append(code); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Code platform     = scan_file( project_dir "dependencies/platform.hpp" ); | ||||||
|  | 		Code basic_types  = scan_file( project_dir "dependencies/basic_types.hpp" ); | ||||||
|  | 		Code debug        = scan_file( project_dir "dependencies/debug.hpp" ); | ||||||
|  | 		Code memory	      = scan_file( project_dir "dependencies/memory.hpp" ); | ||||||
|  | 		Code string_ops   = scan_file( project_dir "dependencies/string_ops.hpp" ); | ||||||
|  | 		Code printing     = scan_file( project_dir "dependencies/printing.hpp" ); | ||||||
|  | 		Code containers   = scan_file( project_dir "dependencies/containers.hpp" ); | ||||||
|  | 		Code hashing 	  = scan_file( project_dir "dependencies/hashing.hpp" ); | ||||||
|  | 		Code strings      = scan_file( project_dir "dependencies/strings.hpp" ); | ||||||
|  | 		Code filesystem   = scan_file( project_dir "dependencies/filesystem.hpp" ); | ||||||
|  | 		Code timing       = scan_file( project_dir "dependencies/timing.hpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		header = Builder::open("gen/gen.dep.hpp"); | ||||||
|  | 		header.print_fmt( generation_notice ); | ||||||
|  | 		header.print( pragma_once ); | ||||||
|  | 		header.print( push_ignores ); | ||||||
|  | 		header.print( platform ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
|  | 		header.print( fmt_newline); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(macros) ); | ||||||
|  | 		header.print( basic_types ); | ||||||
|  | 		header.print( debug ); | ||||||
|  | 		header.print( memory ); | ||||||
|  | 		header.print( string_ops ); | ||||||
|  | 		header.print( printing ); | ||||||
|  | 		header.print( containers ); | ||||||
|  | 		header.print( hashing ); | ||||||
|  | 		header.print( strings ); | ||||||
|  | 		header.print( filesystem ); | ||||||
|  | 		header.print( timing ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "\nGEN_NS_END\n" ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( pop_ignores ); | ||||||
|  | 		header.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen_dep.cpp | ||||||
|  | 	{ | ||||||
|  | 		Code src_start  = scan_file( project_dir "dependencies/src_start.cpp" ); | ||||||
|  | 		Code debug      = scan_file( project_dir "dependencies/debug.cpp" ); | ||||||
|  | 		Code string_ops = scan_file( project_dir "dependencies/string_ops.cpp" ); | ||||||
|  | 		Code printing   = scan_file( project_dir "dependencies/printing.cpp" ); | ||||||
|  | 		Code memory     = scan_file( project_dir "dependencies/memory.cpp" ); | ||||||
|  | 		Code hashing    = scan_file( project_dir "dependencies/hashing.cpp" ); | ||||||
|  | 		Code strings    = scan_file( project_dir "dependencies/strings.cpp" ); | ||||||
|  | 		Code filesystem = scan_file( project_dir "dependencies/filesystem.cpp" ); | ||||||
|  | 		Code timing     = scan_file( project_dir "dependencies/timing.cpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		src = Builder::open( "gen/gen.dep.cpp" ); | ||||||
|  | 		src.print_fmt( generation_notice ); | ||||||
|  | 		src.print( def_include(txt("gen.dep.hpp"))); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( push_ignores ); | ||||||
|  | 		src.print( src_start ); | ||||||
|  | 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
|  | 		src.print( debug ); | ||||||
|  | 		src.print( string_ops ); | ||||||
|  | 		src.print( printing ); | ||||||
|  | 		src.print( hashing ); | ||||||
|  | 		src.print( memory ); | ||||||
|  | 		src.print( strings ); | ||||||
|  | 		src.print( filesystem ); | ||||||
|  | 		src.print( timing ); | ||||||
|  |  | ||||||
|  | 		src.print_fmt( "\nGEN_NS_END\n" ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( pop_ignores ); | ||||||
|  | 		src.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen.hpp | ||||||
|  | 	{ | ||||||
|  | 		Code header_start = scan_file(             "components/header_start.hpp" ); | ||||||
|  | 		Code types        = scan_file( project_dir "components/types.hpp" ); | ||||||
|  | 		Code ast          = scan_file( project_dir "components/ast.hpp" ); | ||||||
|  | 		Code ast_types    = scan_file( project_dir "components/ast_types.hpp" ); | ||||||
|  | 		Code code_types   = scan_file( project_dir "components/code_types.hpp" ); | ||||||
|  | 		Code interface    = scan_file( project_dir "components/interface.hpp" ); | ||||||
|  | 		Code inlines      = scan_file( project_dir "components/inlines.hpp" ); | ||||||
|  | 		Code header_end   = scan_file( project_dir "components/header_end.hpp" ); | ||||||
|  |  | ||||||
|  | 		CodeBody ecode       = gen_ecode     ( project_dir "enums/ECode.csv" ); | ||||||
|  | 		CodeBody eoperator   = gen_eoperator ( project_dir "enums/EOperator.csv" ); | ||||||
|  | 		CodeBody especifier  = gen_especifier( project_dir "enums/ESpecifier.csv" ); | ||||||
|  | 		CodeBody ast_inlines = gen_ast_inlines(); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		header = Builder::open( "gen/gen.hpp" ); | ||||||
|  | 		header.print_fmt( generation_notice ); | ||||||
|  | 		header.print_fmt( "#pragma once\n\n" ); | ||||||
|  | 		header.print( push_ignores ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( header_start ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n\n" ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "#pragma region Types\n" ); | ||||||
|  | 		header.print( types ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(ecode) ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(eoperator) ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(especifier) ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print_fmt( "#pragma endregion Types\n\n" ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "#pragma region AST\n" ); | ||||||
|  | 		header.print( ast ); | ||||||
|  | 		header.print( code_types ); | ||||||
|  | 		header.print( ast_types ); | ||||||
|  | 		header.print_fmt( "\n#pragma endregion AST\n" ); | ||||||
|  |  | ||||||
|  | 		header.print( interface ); | ||||||
|  |  | ||||||
|  | 		header.print_fmt( "\n#pragma region Inlines\n" ); | ||||||
|  | 		header.print( inlines ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(ast_inlines) ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print_fmt( "#pragma endregion Inlines\n" ); | ||||||
|  |  | ||||||
|  | 		header.print( header_end ); | ||||||
|  | 		header.print_fmt( "GEN_NS_END\n\n" ); | ||||||
|  | 		header.print( pop_ignores ); | ||||||
|  | 		header.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen.cpp | ||||||
|  | 	{ | ||||||
|  | 		Code        src_start          = scan_file(             "components/src_start.cpp" ); | ||||||
|  | 		Code        static_data 	   = scan_file( project_dir "components/static_data.cpp" ); | ||||||
|  | 		Code        ast_case_macros    = scan_file( project_dir "components/ast_case_macros.cpp" ); | ||||||
|  | 		Code        ast			       = scan_file( project_dir "components/ast.cpp" ); | ||||||
|  | 		Code        code_serialization = scan_file( project_dir "components/code_serialization.cpp" ); | ||||||
|  | 		Code        interface	       = scan_file( project_dir "components/interface.cpp" ); | ||||||
|  | 		Code        upfront 	       = scan_file( project_dir "components/interface.upfront.cpp" ); | ||||||
|  | 		Code        lexer              = scan_file( project_dir "components/lexer.cpp" ); | ||||||
|  | 		Code        parser             = scan_file( project_dir "components/parser.cpp" ); | ||||||
|  | 		Code 	    parsing_interface  = scan_file( project_dir "components/interface.parsing.cpp" ); | ||||||
|  | 		Code        untyped 	       = scan_file( project_dir "components/interface.untyped.cpp" ); | ||||||
|  |  | ||||||
|  | 		// Note(Ed): The Attribute tokens need to be expanded and regenerated on a per-project/installation of this library for a specific codebase of Unreal. | ||||||
|  | 		// We can support an arbitrary set of modules or plugin apis for parsing | ||||||
|  | 		// but its up to the user to define them all (This will just provide whats I've used up till now). | ||||||
|  | 		CodeBody etoktype         = gen_etoktype( project_dir "enums/ETokType.csv", "enums/AttributeTokens.csv" ); | ||||||
|  | 		CodeNS   nspaced_etoktype = def_namespace( name(parser), def_namespace_body( args(etoktype)) ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		src = Builder::open( "gen/gen.cpp" ); | ||||||
|  | 		src.print_fmt( generation_notice ); | ||||||
|  | 		src.print( push_ignores ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( src_start ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print_fmt( "GEN_NS_BEGIN\n"); | ||||||
|  |  | ||||||
|  | 		src.print( static_data ); | ||||||
|  |  | ||||||
|  | 		src.print_fmt( "\n#pragma region AST\n\n" ); | ||||||
|  | 		src.print( ast_case_macros ); | ||||||
|  | 		src.print( ast ); | ||||||
|  | 		src.print( code_serialization ); | ||||||
|  | 		src.print_fmt( "\n#pragma endregion AST\n" ); | ||||||
|  |  | ||||||
|  | 		src.print_fmt( "\n#pragma region Interface\n" ); | ||||||
|  | 		src.print( interface ); | ||||||
|  | 		src.print( upfront ); | ||||||
|  | 		src.print_fmt( "\n#pragma region Parsing\n\n" ); | ||||||
|  | 		src.print( dump_to_scratch_and_retireve(nspaced_etoktype) ); | ||||||
|  | 		src.print( lexer ); | ||||||
|  | 		src.print( parser ); | ||||||
|  | 		src.print( parsing_interface ); | ||||||
|  | 		src.print( untyped ); | ||||||
|  | 		src.print_fmt( "\n#pragma endregion Parsing\n\n" ); | ||||||
|  | 		src.print_fmt( "#pragma endregion Interface\n\n" ); | ||||||
|  |  | ||||||
|  | 		src.print_fmt( "GEN_NS_END\n\n"); | ||||||
|  | 		src.print( pop_ignores ); | ||||||
|  | 		src.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen_builder.hpp | ||||||
|  | 	{ | ||||||
|  | 		Code builder = scan_file( project_dir "auxillary/builder.hpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		header = Builder::open( "gen/gen.builder.hpp" ); | ||||||
|  | 		header.print_fmt( generation_notice ); | ||||||
|  | 		header.print( push_ignores ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print_fmt( "#pragma once\n\n" ); | ||||||
|  | 		header.print( def_include( txt("gen.hpp") )); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  | 		header.print( builder ); | ||||||
|  | 		header.print_fmt( "GEN_NS_END\n" ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( pop_ignores ); | ||||||
|  | 		header.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen_builder.cpp | ||||||
|  | 	{ | ||||||
|  | 		Code builder = scan_file( project_dir "auxillary/builder.cpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		src = Builder::open( "gen/gen.builder.cpp" ); | ||||||
|  | 		src.print_fmt( generation_notice ); | ||||||
|  | 		src.print( push_ignores ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( def_include( txt("gen.builder.hpp") ) ); | ||||||
|  | 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  | 		src.print( builder ); | ||||||
|  | 		src.print_fmt( "\nGEN_NS_END\n" ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( pop_ignores ); | ||||||
|  | 		src.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen_scanner.hpp | ||||||
|  | 	{ | ||||||
|  | 		Code parsing = scan_file( project_dir "dependencies/parsing.hpp" ); | ||||||
|  | 		Code scanner = scan_file( project_dir "auxillary/scanner.hpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		header = Builder::open( "gen/gen.scanner.hpp" ); | ||||||
|  | 		header.print_fmt( generation_notice ); | ||||||
|  | 		header.print_fmt( "#pragma once\n\n" ); | ||||||
|  | 		header.print( push_ignores ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( def_include( txt("gen.hpp") ) ); | ||||||
|  | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  | 		header.print( parsing ); | ||||||
|  | 		header.print( scanner ); | ||||||
|  | 		header.print_fmt( "GEN_NS_END\n" ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
|  | 		header.print( pop_ignores ); | ||||||
|  | 		header.write(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// gen.scanner.cpp | ||||||
|  | 	{ | ||||||
|  | 		Code parsing = scan_file( project_dir "dependencies/parsing.cpp" ); | ||||||
|  | 		Code scanner = scan_file( project_dir "auxillary/scanner.cpp" ); | ||||||
|  |  | ||||||
|  | 		Builder | ||||||
|  | 		src = Builder::open( "gen/gen.scanner.cpp" ); | ||||||
|  | 		src.print_fmt( generation_notice ); | ||||||
|  | 		src.print( push_ignores ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( def_include( txt("gen.scanner.hpp") ) ); | ||||||
|  | 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  | 		src.print( parsing ); | ||||||
|  | 		// src.print( scanner ); | ||||||
|  | 		src.print_fmt( "GEN_NS_END\n" ); | ||||||
|  | 		src.print( fmt_newline ); | ||||||
|  | 		src.print( pop_ignores ); | ||||||
|  | 		src.write(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								gencpp.10x
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								gencpp.10x
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ | |||||||
| 		<SyncFiles>true</SyncFiles> | 		<SyncFiles>true</SyncFiles> | ||||||
| 		<Recursive>true</Recursive> | 		<Recursive>true</Recursive> | ||||||
| 		<ShowEmptyFolders>true</ShowEmptyFolders> | 		<ShowEmptyFolders>true</ShowEmptyFolders> | ||||||
|  | 		<IncludeFilesWithoutExt>false</IncludeFilesWithoutExt> | ||||||
| 		<IsVirtual>false</IsVirtual> | 		<IsVirtual>false</IsVirtual> | ||||||
| 		<IsFolder>false</IsFolder> | 		<IsFolder>false</IsFolder> | ||||||
| 		<BuildCommand>pwsh ./scripts/build.ps1 msvc debug bootstrap</BuildCommand> | 		<BuildCommand>pwsh ./scripts/build.ps1 msvc debug bootstrap</BuildCommand> | ||||||
| @@ -14,12 +15,13 @@ | |||||||
| 		<CleanCommand>pwsh ./scripts/clean.ps1</CleanCommand> | 		<CleanCommand>pwsh ./scripts/clean.ps1</CleanCommand> | ||||||
| 		<BuildWorkingDirectory></BuildWorkingDirectory> | 		<BuildWorkingDirectory></BuildWorkingDirectory> | ||||||
| 		<CancelBuild></CancelBuild> | 		<CancelBuild></CancelBuild> | ||||||
| 		<RunCommand>./test/gen/build/gencpp.exe</RunCommand> | 		<Exe>./test/gen/build/gencpp.exe</Exe> | ||||||
| 		<RunCommandWorkingDirectory></RunCommandWorkingDirectory> | 		<Args></Args> | ||||||
|  | 		<WorkingDirectory></WorkingDirectory> | ||||||
| 		<DebugCommand>pwsh ./scripts/build.ps1</DebugCommand> | 		<DebugCommand>pwsh ./scripts/build.ps1</DebugCommand> | ||||||
| 		<ExePathCommand>./test/gen/build/gencpp.exe</ExePathCommand> |  | ||||||
| 		<DebugSln></DebugSln> | 		<DebugSln></DebugSln> | ||||||
| 		<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat> | 		<UseVisualStudioEnvBat>true</UseVisualStudioEnvBat> | ||||||
|  | 		<CaptureExeOutput>false</CaptureExeOutput> | ||||||
| 		<Configurations> | 		<Configurations> | ||||||
| 			<Configuration>Debug</Configuration> | 			<Configuration>Debug</Configuration> | ||||||
| 			<Configuration>Release</Configuration> | 			<Configuration>Release</Configuration> | ||||||
| @@ -44,6 +46,8 @@ | |||||||
| 			<Define>GEN_SYSTEM_WINDOWS</Define> | 			<Define>GEN_SYSTEM_WINDOWS</Define> | ||||||
| 			<Define>GEN_INTELLISENSE_DIRECTIVES</Define> | 			<Define>GEN_INTELLISENSE_DIRECTIVES</Define> | ||||||
| 			<Define>GEN_EXECUTION_EXPRESSION_SUPPORT</Define> | 			<Define>GEN_EXECUTION_EXPRESSION_SUPPORT</Define> | ||||||
|  | 			<Define>GEN_BENCHMARK</Define> | ||||||
|  | 			<Define>GEN_COMPILER_MSVC</Define> | ||||||
| 		</Defines> | 		</Defines> | ||||||
| 		<ConfigProperties> | 		<ConfigProperties> | ||||||
| 			<ConfigAndPlatform> | 			<ConfigAndPlatform> | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| Builder Builder::open( char const* path ) | Builder Builder::open( char const* path ) | ||||||
| { | { | ||||||
| 	Builder result; | 	Builder result; | ||||||
| 	 |  | ||||||
| 	FileError error = file_open_mode( & result.File, EFileMode_WRITE, path ); | 	FileError error = file_open_mode( & result.File, EFileMode_WRITE, path ); | ||||||
| 	if ( error != EFileError_NONE ) | 	if ( error != EFileError_NONE ) | ||||||
| 	{ | 	{ | ||||||
| @@ -13,7 +13,7 @@ Builder Builder::open( char const* path ) | |||||||
| 		return result; | 		return result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	result.Buffer = String::make_reserve( GlobalAllocator, Builder_StrBufferReserve ); | 	result.Buffer = string_make_reserve( GlobalAllocator, Builder_StrBufferReserve ); | ||||||
|  |  | ||||||
| 	// log_fmt("$Builder - Opened file: %s\n", result.File.filename ); | 	// log_fmt("$Builder - Opened file: %s\n", result.File.filename ); | ||||||
| 	return result; | 	return result; | ||||||
| @@ -21,20 +21,20 @@ Builder Builder::open( char const* path ) | |||||||
|  |  | ||||||
| void Builder::pad_lines( s32 num ) | void Builder::pad_lines( s32 num ) | ||||||
| { | { | ||||||
| 	Buffer.append( "\n" ); | 	append( Buffer,  "\n" ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print( Code code ) | void Builder::print( Code code ) | ||||||
| { | { | ||||||
| 	String   str = code->to_string(); | 	String   str = code->to_string(); | ||||||
| 	// const sw len = str.length(); | 	// const ssize len = str.length(); | ||||||
| 	// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); | 	// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data ); | ||||||
| 	Buffer.append( str ); | 	append( Buffer, str ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print_fmt( char const* fmt, ... ) | void Builder::print_fmt( char const* fmt, ... ) | ||||||
| { | { | ||||||
| 	sw   res; | 	ssize   res; | ||||||
| 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; | 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; | ||||||
|  |  | ||||||
| 	va_list va; | 	va_list va; | ||||||
| @@ -43,17 +43,17 @@ void Builder::print_fmt( char const* fmt, ... ) | |||||||
| 	va_end( va ); | 	va_end( va ); | ||||||
|  |  | ||||||
| 	// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf ); | 	// log_fmt( "$%s - print_fmt: %.*s\n", File.filename, res > 80 ? 80 : res, buf ); | ||||||
| 	Buffer.append( buf, res ); | 	append( Buffer, buf, res ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::write() | void Builder::write() | ||||||
| { | { | ||||||
| 	bool result = file_write( & File, Buffer, Buffer.length() ); | 	b32 result = file_write( & File, Buffer, length(Buffer) ); | ||||||
|  |  | ||||||
| 	if ( result == false ) | 	if ( result == false ) | ||||||
| 		log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); | 		log_failure("gen::File::write - Failed to write to file: %s\n", file_name( & File ) ); | ||||||
|  |  | ||||||
| 	log_fmt( "Generated: %s\n", File.filename ); | 	log_fmt( "Generated: %s\n", File.filename ); | ||||||
| 	file_close( & File ); | 	file_close( & File ); | ||||||
| 	Buffer.free(); | 	free(Buffer); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								project/auxillary/gen_template.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								project/auxillary/gen_template.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
|  | #	pragma once | ||||||
|  | #	include "../gen.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | 	Explicitly generates a resolved definition of a cpp template definition. | ||||||
|  |  | ||||||
|  | 	TODO(Ed): Needs implementing for the C-library variant. | ||||||
|  | 	TODO(Ed): We need a non <token> syntax subst implemtnation for Strings for this to work. It must subst keywords directly based on template parameter names. | ||||||
|  |  | ||||||
|  | 	This is only meant to be used on relatively trivial templates, where the type or numeric is mostly a 'duck' type. | ||||||
|  | 	It cannot parse complex template parameters. | ||||||
|  |  | ||||||
|  | 	The varadic args should correspond 1:1 with the type of objects the generator expects from the template's parameters.alignas. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | CodeOperator gen_operator_template( CodeTemplate template, ... ); | ||||||
|  | CodeFn       gen_func_template( CodeTemplate template, ...  ); | ||||||
|  | Code         gen_class_struct_template( CodeTemplate template, ... ); | ||||||
|  |  | ||||||
|  | Code gen_template( CodeTemplate template, ... ); | ||||||
|  | Code gen_template( StrC template, StrC instantiation ); | ||||||
| @@ -1 +1,5 @@ | |||||||
| #include "scanner.hpp" | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
|  | #	include "scanner.hpp" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ | |||||||
| // This is a simple file reader that reads the entire file into memory. | // This is a simple file reader that reads the entire file into memory. | ||||||
| // It has an extra option to skip the first few lines for undesired includes. | // It has an extra option to skip the first few lines for undesired includes. | ||||||
| // This is done so that includes can be kept in dependency and component files so that intellisense works. | // This is done so that includes can be kept in dependency and component files so that intellisense works. | ||||||
|  | inline | ||||||
| Code scan_file( char const* path ) | Code scan_file( char const* path ) | ||||||
| { | { | ||||||
| 	FileInfo file; | 	FileInfo file; | ||||||
| @@ -16,15 +17,15 @@ Code scan_file( char const* path ) | |||||||
| 		GEN_FATAL( "scan_file: Could not open: %s", path ); | 		GEN_FATAL( "scan_file: Could not open: %s", path ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	sw fsize = file_size( & file ); | 	ssize fsize = file_size( & file ); | ||||||
| 	if ( fsize <= 0 ) | 	if ( fsize <= 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		GEN_FATAL("scan_file: %s is empty", path ); | 		GEN_FATAL("scan_file: %s is empty", path ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String str = String::make_reserve( GlobalAllocator, fsize ); | 	String str = string_make_reserve( GlobalAllocator, fsize ); | ||||||
| 		file_read( & file, str, fsize ); | 		file_read( & file, str, fsize ); | ||||||
| 		str.get_header().Length = fsize; | 		get_header(str).Length = fsize; | ||||||
|  |  | ||||||
| 	// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks | 	// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks | ||||||
| 	// Its designed so that the directive should be the first thing in the file. | 	// Its designed so that the directive should be the first thing in the file. | ||||||
| @@ -96,12 +97,12 @@ Code scan_file( char const* path ) | |||||||
| 					if ( (scanner + 2) >= ( str.Data + fsize ) ) | 					if ( (scanner + 2) >= ( str.Data + fsize ) ) | ||||||
| 					{ | 					{ | ||||||
| 						mem_move( str, scanner, left ); | 						mem_move( str, scanner, left ); | ||||||
| 						str.get_header().Length = left; | 						get_header(str).Length = left; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					mem_move( str, scanner, left ); | 					mem_move( str, scanner, left ); | ||||||
| 					str.get_header().Length = left; | 					get_header(str).Length = left; | ||||||
|  |  | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -1,126 +0,0 @@ | |||||||
| Clear-Host |  | ||||||
|  |  | ||||||
| $path_root     = git rev-parse --show-toplevel |  | ||||||
| $path_scripts  = Join-Path $path_root 'scripts' |  | ||||||
|  |  | ||||||
| $target_arch        = Join-Path $path_scripts 'helpers/target_arch.psm1' |  | ||||||
| $devshell           = Join-Path $path_scripts 'helpers/devshell.ps1' |  | ||||||
| $format_cpp	        = Join-Path $path_scripts 'helpers/format_cpp.psm1' |  | ||||||
| $incremental_checks = Join-Path $path_scripts 'helpers/incremental_checks.ps1' |  | ||||||
| $vendor_toolchain   = Join-Path $path_scripts 'helpers/vendor_toolchain.ps1' |  | ||||||
|  |  | ||||||
| $path_project  = Join-Path $path_root     'project' |  | ||||||
| $path_aux      = Join-Path $path_project  'auxillary' |  | ||||||
| $path_vis_root = Join-Path $path_aux      'vis_ast' |  | ||||||
| $path_binaries = Join-Path $path_vis_root 'binaries' |  | ||||||
| $path_build    = Join-Path $path_vis_root 'build' |  | ||||||
| $path_code     = Join-Path $path_vis_root 'code' |  | ||||||
| $path_deps     = Join-Path $path_vis_root 'dependencies' |  | ||||||
| $path_win32    = Join-Path $path_code     'win32' |  | ||||||
|  |  | ||||||
| Import-Module $target_arch |  | ||||||
| Import-Module $format_cpp |  | ||||||
|  |  | ||||||
| #region Arguments |  | ||||||
| $vendor           = $null |  | ||||||
| $optimize         = $null |  | ||||||
| $debug 	          = $null |  | ||||||
| $analysis	      = $false |  | ||||||
| $dev              = $false |  | ||||||
| $verbose          = $null |  | ||||||
| $platform         = $null |  | ||||||
| $module_specified = $false |  | ||||||
|  |  | ||||||
| [array] $vendors = @( "clang", "msvc" ) |  | ||||||
|  |  | ||||||
| # This is a really lazy way of parsing the args, could use actual params down the line... |  | ||||||
|  |  | ||||||
| if ( $args ) { $args | ForEach-Object { |  | ||||||
| switch ($_){ |  | ||||||
|  { $_ -in $vendors }   { $vendor    = $_; break } |  | ||||||
|  "optimize"            { $optimize  = $true } |  | ||||||
|  "debug"               { $debug     = $true } |  | ||||||
|  "analysis"            { $analysis  = $true } |  | ||||||
|  "dev"                 { $dev       = $true } |  | ||||||
|  "verbose"             { $verbose   = $true } |  | ||||||
|  "platform"            { $platform  = $true; $module_specified = $true } |  | ||||||
| } |  | ||||||
| }} |  | ||||||
| #endregion Argument |  | ||||||
|  |  | ||||||
| if ( -not $module_specified ) |  | ||||||
| { |  | ||||||
| 	$platform = $true |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # Load up toolchain configuraion |  | ||||||
| . $vendor_toolchain |  | ||||||
| . $incremental_checks |  | ||||||
|  |  | ||||||
| write-host "Building Vis AST with $vendor" |  | ||||||
|  |  | ||||||
| if ( (Test-Path $path_build) -eq $false ) { |  | ||||||
| 	New-Item $path_build -ItemType Directory |  | ||||||
| } |  | ||||||
|  |  | ||||||
| if ( (Test-Path $path_binaries) -eq $false ) { |  | ||||||
| 	New-Item $path_binaries -ItemType Directory |  | ||||||
| } |  | ||||||
|  |  | ||||||
| $path_raylib     = join-path $path_deps   'raylib' |  | ||||||
| $path_raylib_inc = join-path $path_raylib 'include' |  | ||||||
| $path_raylib_lib = join-path $path_raylib 'lib' |  | ||||||
|  |  | ||||||
| $path_raylib_dll     = join-path $path_raylib_lib 'raylib.dll' |  | ||||||
| $path_raylib_dll_bin = join-path $path_binaries   'raylib.dll' |  | ||||||
|  |  | ||||||
| Copy-Item $path_raylib_dll $path_raylib_dll_bin -Force |  | ||||||
|  |  | ||||||
| $includes = @( |  | ||||||
| 	$path_code, |  | ||||||
| 	$path_deps |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| write-host $path_code |  | ||||||
|  |  | ||||||
| foreach ( $include in $includes ) { |  | ||||||
| 	Write-Host 'include: ' $include |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # Microsoft |  | ||||||
| $lib_gdi32  = 'Gdi32.lib' |  | ||||||
| $lib_xinput = 'Xinput.lib' |  | ||||||
| $lib_user32 = 'User32.lib' |  | ||||||
| $lib_winmm  = 'Winmm.lib' |  | ||||||
|  |  | ||||||
| $stack_size = 1024 * 1024 * 4 |  | ||||||
|  |  | ||||||
| $compiler_args = @( |  | ||||||
| 	( $flag_define + 'UNICODE'), |  | ||||||
| 	( $flag_define + '_UNICODE') |  | ||||||
| 	( $flag_define + 'INTELLISENSE_DIRECTIVES=0'), |  | ||||||
| 	( $flag_define + 'RL_USE_LIBTYPE_SHARED') |  | ||||||
| 	# ($flag_set_stack_size + $stack_size) |  | ||||||
| 	$flag_wall |  | ||||||
| 	$flag_warnings_as_errors |  | ||||||
| 	$flag_optimize_intrinsics |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| if ( $dev ) { |  | ||||||
| 	$compiler_args += ( $flag_define + 'Build_Development=1' ) |  | ||||||
| } |  | ||||||
| else { |  | ||||||
| 	$compiler_args += ( $flag_define + 'Build_Development=0' ) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| $linker_args = @( |  | ||||||
| 	$flag_link_win_subsystem_windows, |  | ||||||
| 	$flag_link_optiiize_references, |  | ||||||
|  |  | ||||||
| 	( join-path $path_raylib_lib 'raylib.lib' ) |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| $unit       = join-path $path_code     'vis_ast_windows.cpp' |  | ||||||
| $executable = join-path $path_binaries 'vis_ast.exe' |  | ||||||
|  |  | ||||||
| $build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| $path_root     = git rev-parse --show-toplevel |  | ||||||
| $path_scripts  = Join-Path $path_root 'scripts' |  | ||||||
|  |  | ||||||
| $target_arch        = Join-Path $path_scripts 'helpers/target_arch.psm1' |  | ||||||
| $devshell           = Join-Path $path_scripts 'helpers/devshell.ps1' |  | ||||||
| $format_cpp	        = Join-Path $path_scripts 'helpers/format_cpp.psm1' |  | ||||||
| $incremental_checks = Join-Path $path_scripts 'helpers/incremental_checks.ps1' |  | ||||||
| $vendor_toolchain   = Join-Path $path_scripts 'helpers/vendor_toolchain.ps1' |  | ||||||
|  |  | ||||||
| $path_project  = Join-Path $path_root     'project' |  | ||||||
| $path_aux      = Join-Path $path_project  'auxillary' |  | ||||||
| $path_vis_root = Join-Path $path_aux      'vis_ast' |  | ||||||
| $path_binaries = Join-Path $path_vis_root 'binaries' |  | ||||||
| $path_build    = Join-Path $path_vis_root 'build' |  | ||||||
|  |  | ||||||
| if ( test-path $path_build ) { |  | ||||||
| 	remove-item $path_build -Recurse |  | ||||||
| } |  | ||||||
|  |  | ||||||
| if ( test-path $path_binaries ) { |  | ||||||
| 	remove-item $path_binaries -recurse |  | ||||||
| } |  | ||||||
| @@ -1,25 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #if INTELLISENSE_DIRECTIVES |  | ||||||
| #include "vendor/compiler.hpp" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #define global        static // Global variables |  | ||||||
| #define internal      static // Internal linkage |  | ||||||
| #define local_persist static // Local Persisting variables |  | ||||||
|  |  | ||||||
| #define api_c extern "C" |  | ||||||
|  |  | ||||||
| #define ccast( type, value ) ( const_cast< type >( (value) ) ) |  | ||||||
| #define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) ) |  | ||||||
| #define rcast( type, value ) reinterpret_cast< type >( value ) |  | ||||||
| #define scast( type, value ) static_cast< type >( value ) |  | ||||||
|  |  | ||||||
| #define do_once()   for ( local_persist b32 once = true; once; once = false ) |  | ||||||
| #define stmt( ... ) do { __VA_ARGS__; } while ( 0 ) |  | ||||||
|  |  | ||||||
| #define array_count( array ) ( sizeof( array ) / sizeof( ( array )[0] ) ) |  | ||||||
|  |  | ||||||
| #define kilobytes( x ) ( ( x ) * ( s64 )( 1024 ) ) |  | ||||||
| #define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) ) |  | ||||||
| #define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) ) |  | ||||||
| #define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) ) |  | ||||||
| @@ -1,10 +0,0 @@ | |||||||
| // Platform architecture |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ ) |  | ||||||
| #	ifndef ARCH_64_BIT |  | ||||||
| #		define ARCH_64_BIT 1 |  | ||||||
| #	endif |  | ||||||
| #else |  | ||||||
| #	error A 32-bit architecture is not supported |  | ||||||
| #endif |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| // Platform compiler |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #if defined( _MSC_VER ) |  | ||||||
| #	define Compiler_MSVC 1 |  | ||||||
| #elif defined( __clang__ ) |  | ||||||
| #	define Compiler_Clang 1 |  | ||||||
| #else |  | ||||||
| #	error "Unknown compiler" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined( __has_attribute ) |  | ||||||
| #	define HAS_ATTRIBUTE( attribute ) __has_attribute( attribute ) |  | ||||||
| #else |  | ||||||
| #	define HAS_ATTRIBUTE( attribute ) ( 0 ) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef Compiler_Clang |  | ||||||
| #	define compiler_decorated_func_name __PRETTY_NAME__ |  | ||||||
| #elif defined(Compiler_MSVC) |  | ||||||
| #	define compiler_decorated_func_name __FUNCDNAME__ |  | ||||||
| #endif |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| #if INTELLISENSE_DIRECTIVES |  | ||||||
| #include "compiler.hpp" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef Compiler_MSVC |  | ||||||
| #pragma warning( disable: 4201 ) // Support for non-standard nameless struct or union extesnion |  | ||||||
| #pragma warning( disable: 4100 ) // Support for unreferenced formal parameters |  | ||||||
| #pragma warning( disable: 4800 ) // Support implicit conversion to bools |  | ||||||
| #pragma warning( disable: 4365 ) // Support for signed/unsigned mismatch auto-conversion |  | ||||||
| #pragma warning( disable: 4189 ) // Support for unused variables |  | ||||||
| #pragma warning( disable: 4514 ) // Support for unused inline functions |  | ||||||
| #pragma warning( disable: 4505 ) // Support for unused static functions |  | ||||||
| #pragma warning( disable: 5045 ) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified |  | ||||||
| #pragma warning( disable: 5264 ) // Support for 'const' variables unused |  | ||||||
| #pragma warning( disable: 4820 ) // Support auto-adding padding to structs |  | ||||||
| #pragma warning( disable: 4711 ) // Support automatic inline expansion |  | ||||||
| #pragma warning( disable: 4710 ) // Support automatic inline expansion |  | ||||||
| #pragma warning( disable: 4805 ) // Support comparisons of s32 to bool. |  | ||||||
| #pragma warning( disable: 5246 ) // Support for initialization of subobject without braces. |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef Compiler_Clang |  | ||||||
| #pragma clang diagnostic push |  | ||||||
| #pragma clang diagnostic ignored "-Wunused-const-variable" |  | ||||||
| #pragma clang diagnostic ignored "-Wswitch" |  | ||||||
| #pragma clang diagnostic ignored "-Wunused-variable" |  | ||||||
| #pragma clang diagnostic ignored "-Wunused-local-typedef" |  | ||||||
| #pragma clang diagnostic ignored "-Wunknown-pragmas" |  | ||||||
| #pragma clang diagnostic ignored "-Wvarargs" |  | ||||||
| #pragma clang diagnostic ignored "-Wunused-function" |  | ||||||
| #pragma clang diagnostic ignored "-Wunused-but-set-variable" |  | ||||||
| #pragma clang diagnostic ignored "-Wmissing-braces" |  | ||||||
| #endif |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| // Platform OS detection |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #if defined( _WIN32 ) || defined( _WIN64 ) |  | ||||||
| #	ifndef System_Windows |  | ||||||
| #		define System_Windows 1 |  | ||||||
| #	endif |  | ||||||
| #elif defined( __APPLE__ ) && defined( __MACH__ ) |  | ||||||
| #	ifndef System_MacOS |  | ||||||
| #		define System_MacOS 1 |  | ||||||
| #	endif |  | ||||||
| #elif defined( __unix__ ) |  | ||||||
| #	if defined( __linux__ ) |  | ||||||
| #		ifndef System_Linux |  | ||||||
| #			define System_linux 1 |  | ||||||
| #		endif |  | ||||||
| #	else |  | ||||||
| #		error This UNIX operating system is not supported |  | ||||||
| #	endif |  | ||||||
| #else |  | ||||||
| #	error This operating system is not supported |  | ||||||
| #endif |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| #if INTELLISENSE_DIRECTIVES |  | ||||||
| #include "win32.hpp" |  | ||||||
| #include "raylib/include/raylib.h" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| int __stdcall WinMain( HINSTANCE instance, HINSTANCE prev_instance, char* commandline, int num_cmd_show) |  | ||||||
| { |  | ||||||
|     // Initialization |  | ||||||
|     //-------------------------------------------------------------------------------------- |  | ||||||
|     const int screenWidth = 800; |  | ||||||
|     const int screenHeight = 450; |  | ||||||
|  |  | ||||||
|     rl::init_window(screenWidth, screenHeight, "raylib [core] example - basic window"); |  | ||||||
|  |  | ||||||
|     rl::set_target_fps(60);               // Set our game to run at 60 frames-per-second |  | ||||||
|     //-------------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
|     // Main game loop |  | ||||||
|     while (!rl::window_should_close())    // Detect window close button or ESC key |  | ||||||
|     { |  | ||||||
|         // Update |  | ||||||
|         //---------------------------------------------------------------------------------- |  | ||||||
|         // TODO: Update your variables here |  | ||||||
|         //---------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
|         // Draw |  | ||||||
|         //---------------------------------------------------------------------------------- |  | ||||||
|         rl::begin_drawing(); |  | ||||||
|  |  | ||||||
|             rl::clear_background(RL_RAYWHITE); |  | ||||||
|  |  | ||||||
|             rl::draw_text("Congrats! You created your first window!", 190, 200, 20, RL_LIGHTGRAY); |  | ||||||
|  |  | ||||||
|         rl::end_drawing(); |  | ||||||
|         //---------------------------------------------------------------------------------- |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // De-Initialization |  | ||||||
|     //-------------------------------------------------------------------------------------- |  | ||||||
|     rl::close_window();        // Close window and OpenGL context |  | ||||||
|     //-------------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @@ -1,3 +0,0 @@ | |||||||
| #pragma once |  | ||||||
|  |  | ||||||
| using HINSTANCE = void*; |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| #include "platform/vendor/arch.hpp" |  | ||||||
| #include "platform/vendor/compiler.hpp" |  | ||||||
| #include "platform/vendor/compiler_ignores.hpp" |  | ||||||
| #include "platform/vendor/os.hpp" |  | ||||||
|  |  | ||||||
| #include "platform/macros.hpp" |  | ||||||
|  |  | ||||||
| #include "platform/win32/types.hpp" |  | ||||||
|  |  | ||||||
| #include "raylib/include/raylib.h" |  | ||||||
|  |  | ||||||
| #include "platform/win32/launch.cpp" |  | ||||||
| @@ -1,285 +0,0 @@ | |||||||
| /********************************************************************************************** |  | ||||||
| * |  | ||||||
| *   raylib configuration flags |  | ||||||
| * |  | ||||||
| *   This file defines all the configuration flags for the different raylib modules |  | ||||||
| * |  | ||||||
| *   LICENSE: zlib/libpng |  | ||||||
| * |  | ||||||
| *   Copyright (c) 2018-2023 Ahmad Fatoum & Ramon Santamaria (@raysan5) |  | ||||||
| * |  | ||||||
| *   This software is provided "as-is", without any express or implied warranty. In no event |  | ||||||
| *   will the authors be held liable for any damages arising from the use of this software. |  | ||||||
| * |  | ||||||
| *   Permission is granted to anyone to use this software for any purpose, including commercial |  | ||||||
| *   applications, and to alter it and redistribute it freely, subject to the following restrictions: |  | ||||||
| * |  | ||||||
| *     1. The origin of this software must not be misrepresented; you must not claim that you |  | ||||||
| *     wrote the original software. If you use this software in a product, an acknowledgment |  | ||||||
| *     in the product documentation would be appreciated but is not required. |  | ||||||
| * |  | ||||||
| *     2. Altered source versions must be plainly marked as such, and must not be misrepresented |  | ||||||
| *     as being the original software. |  | ||||||
| * |  | ||||||
| *     3. This notice may not be removed or altered from any source distribution. |  | ||||||
| * |  | ||||||
| **********************************************************************************************/ |  | ||||||
|  |  | ||||||
| #ifndef CONFIG_H |  | ||||||
| #define CONFIG_H |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module selection - Some modules could be avoided |  | ||||||
| // Mandatory modules: rcore, rlgl, utils |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_SUPPORT_MODULE_RSHAPES          1 |  | ||||||
| #define RL_SUPPORT_MODULE_RTEXTURES        1 |  | ||||||
| #define RL_SUPPORT_MODULE_RTEXT            1       // WARNING: It requires RL_SUPPORT_MODULE_RTEXTURES to load sprite font textures |  | ||||||
| #define RL_SUPPORT_MODULE_RMODELS          1 |  | ||||||
| #define RL_SUPPORT_MODULE_RAUDIO           1 |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rcore - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital |  | ||||||
| #define RL_SUPPORT_CAMERA_SYSTEM           1 |  | ||||||
| // Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag |  | ||||||
| #define RL_SUPPORT_GESTURES_SYSTEM         1 |  | ||||||
| // Include pseudo-random numbers generator (rprand.h), based on Xoshiro128** and SplitMix64 |  | ||||||
| #define RL_SUPPORT_RPRAND_GENERATOR        1 |  | ||||||
| // Mouse gestures are directly mapped like touches and processed by gestures system |  | ||||||
| #define RL_SUPPORT_MOUSE_GESTURES          1 |  | ||||||
| // Reconfigure standard input to receive key inputs, works with SSH connection. |  | ||||||
| #define RL_SUPPORT_SSH_KEYBOARD_RPI        1 |  | ||||||
| // Setting a higher resolution can improve the accuracy of time-out intervals in wait functions. |  | ||||||
| // However, it can also reduce overall system performance, because the thread scheduler switches tasks more often. |  | ||||||
| #define RL_SUPPORT_WINMM_HIGHRES_TIMER     1 |  | ||||||
| // Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used |  | ||||||
| //#define RL_SUPPORT_BUSY_WAIT_LOOP          1 |  | ||||||
| // Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy |  | ||||||
| #define RL_SUPPORT_PARTIALBUSY_WAIT_LOOP    1 |  | ||||||
| // Allow automatic screen capture of current screen pressing F12, defined in KeyCallback() |  | ||||||
| #define RL_SUPPORT_SCREEN_CAPTURE          1 |  | ||||||
| // Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback() |  | ||||||
| #define RL_SUPPORT_GIF_RECORDING           1 |  | ||||||
| // Support CompressData() and DecompressData() functions |  | ||||||
| #define RL_SUPPORT_COMPRESSION_API         1 |  | ||||||
| // Support automatic generated events, loading and recording of those events when required |  | ||||||
| #define RL_SUPPORT_AUTOMATION_EVENTS       1 |  | ||||||
| // Support custom frame control, only for advance users |  | ||||||
| // By default end_drawing() does this job: draws everything + swap_screen_buffer() + manage frame timing + poll_input_events() |  | ||||||
| // Enabling this flag allows manual control of the frame processes, use at your own risk |  | ||||||
| //#define RL_SUPPORT_CUSTOM_FRAME_CONTROL    1 |  | ||||||
|  |  | ||||||
| // rcore: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_MAX_FILEPATH_CAPACITY        8192       // Maximum file paths capacity |  | ||||||
| #define RL_MAX_FILEPATH_LENGTH          4096       // Maximum length for filepaths (Linux PATH_MAX default value) |  | ||||||
|  |  | ||||||
| #define RL_MAX_KEYBOARD_KEYS             512       // Maximum number of keyboard keys supported |  | ||||||
| #define RL_MAX_MOUSE_BUTTONS               8       // Maximum number of mouse buttons supported |  | ||||||
| #define RL_MAX_GAMEPADS                    4       // Maximum number of gamepads supported |  | ||||||
| #define RL_MAX_GAMEPAD_AXIS                8       // Maximum number of axis supported (per gamepad) |  | ||||||
| #define RL_MAX_GAMEPAD_BUTTONS            32       // Maximum number of buttons supported (per gamepad) |  | ||||||
| #define RL_MAX_TOUCH_POINTS                8       // Maximum number of touch points supported |  | ||||||
| #define RL_MAX_KEY_PRESSED_QUEUE          16       // Maximum number of keys in the key input queue |  | ||||||
| #define RL_MAX_CHAR_PRESSED_QUEUE         16       // Maximum number of characters in the char input queue |  | ||||||
|  |  | ||||||
| #define RL_MAX_DECOMPRESSION_SIZE         64       // Max size allocated for decompression in MB |  | ||||||
|  |  | ||||||
| #define RL_MAX_AUTOMATION_EVENTS       16384       // Maximum number of automation events to record |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rlgl - Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
|  |  | ||||||
| // Enable OpenGL Debug Context (only available on OpenGL 4.3) |  | ||||||
| //#define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT       1 |  | ||||||
|  |  | ||||||
| // Show OpenGL extensions and capabilities detailed logs on init |  | ||||||
| //#define RLGL_SHOW_GL_DETAILS_INFO              1 |  | ||||||
|  |  | ||||||
| //#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS    4096    // Default internal render batch elements limits |  | ||||||
| #define RL_DEFAULT_BATCH_BUFFERS               1      // Default number of batch buffers (multi-buffering) |  | ||||||
| #define RL_DEFAULT_BATCH_DRAWCALLS           256      // Default number of batch draw calls (by state changes: mode, texture) |  | ||||||
| #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS     4      // Maximum number of textures units that can be activated on batch drawing (set_shader_value_texture()) |  | ||||||
|  |  | ||||||
| #define RL_MAX_MATRIX_STACK_SIZE              32      // Maximum size of internal Matrix stack |  | ||||||
|  |  | ||||||
| #define RL_MAX_SHADER_LOCATIONS               32      // Maximum number of shader locations supported |  | ||||||
|  |  | ||||||
| #define RL_CULL_DISTANCE_NEAR               0.01      // Default projection matrix near cull distance |  | ||||||
| #define RL_CULL_DISTANCE_FAR              1000.0      // Default projection matrix far cull distance |  | ||||||
|  |  | ||||||
| // Default shader vertex attribute names to set location points |  | ||||||
| // NOTE: When a new shader is loaded, the following locations are tried to be set for convenience |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION     "vertexPosition"    // Bound by default to shader location: 0 |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD     "vertexTexCoord"    // Bound by default to shader location: 1 |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL       "vertexNormal"      // Bound by default to shader location: 2 |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR        "vertexColor"       // Bound by default to shader location: 3 |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT      "vertexTangent"     // Bound by default to shader location: 4 |  | ||||||
| #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2    "vertexTexCoord2"   // Bound by default to shader location: 5 |  | ||||||
|  |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP         "mvp"               // model-view-projection matrix |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW        "matView"           // view matrix |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION  "matProjection"     // projection matrix |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL       "matModel"          // model matrix |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL      "matNormal"         // normal matrix (transpose(inverse(matModelView)) |  | ||||||
| #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR       "colDiffuse"        // color diffuse (base tint color, multiplied by texture color) |  | ||||||
| #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0  "texture0"          // texture0 (texture slot active 0) |  | ||||||
| #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1  "texture1"          // texture1 (texture slot active 1) |  | ||||||
| #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2  "texture2"          // texture2 (texture slot active 2) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rshapes - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Use QUADS instead of TRIANGLES for drawing when possible |  | ||||||
| // Some lines-based shapes could still use lines |  | ||||||
| #define RL_SUPPORT_QUADS_DRAW_MODE         1 |  | ||||||
|  |  | ||||||
| // rshapes: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define SPLINE_SEGMENT_DIVISIONS       24       // Spline segments subdivisions |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rtextures - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Selecte desired fileformats to be supported for image data loading |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_PNG      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_BMP      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_TGA      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_JPG      1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_GIF      1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_QOI      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_PSD      1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_DDS      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_HDR      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_PIC          1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_KTX      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_ASTC     1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_PKM      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_PVR      1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_SVG      1 |  | ||||||
|  |  | ||||||
| // Support image export functionality (.png, .bmp, .tga, .jpg, .qoi) |  | ||||||
| #define RL_SUPPORT_IMAGE_EXPORT            1 |  | ||||||
| // Support procedural image generation functionality (gradient, spot, perlin-noise, cellular) |  | ||||||
| #define RL_SUPPORT_IMAGE_GENERATION        1 |  | ||||||
| // Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... |  | ||||||
| // If not defined, still some functions are supported: image_format(), image_crop(), image_to_pot() |  | ||||||
| #define RL_SUPPORT_IMAGE_MANIPULATION      1 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rtext - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Default font is loaded on window initialization to be available for the user to render simple text |  | ||||||
| // NOTE: If enabled, uses external module functions to load default raylib font |  | ||||||
| #define RL_SUPPORT_DEFAULT_FONT            1 |  | ||||||
| // Selected desired font fileformats to be supported for loading |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_FNT          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_TTF          1 |  | ||||||
|  |  | ||||||
| // Support text management functions |  | ||||||
| // If not defined, still some functions are supported: text_length(), TextFormat() |  | ||||||
| #define RL_SUPPORT_TEXT_MANIPULATION       1 |  | ||||||
|  |  | ||||||
| // On font atlas image generation [gen_image_font_atlas()], add a 3x3 pixels white rectangle |  | ||||||
| // at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow |  | ||||||
| // drawing text and shapes with a single draw call [set_shapes_texture()]. |  | ||||||
| #define RL_SUPPORT_FONT_ATLAS_WHITE_REC    1 |  | ||||||
|  |  | ||||||
| // rtext: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_MAX_TEXT_BUFFER_LENGTH       1024       // Size of internal static buffers used on some functions: |  | ||||||
|                                                 // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit() |  | ||||||
| #define RL_MAX_TEXTSPLIT_COUNT           128       // Maximum number of substrings to split: TextSplit() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: rmodels - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Selected desired model fileformats to be supported for loading |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_OBJ          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_MTL          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_IQM          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_GLTF         1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_VOX          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_M3D          1 |  | ||||||
| // Support procedural mesh generation functions, uses external par_shapes.h library |  | ||||||
| // NOTE: Some generated meshes DO NOT include generated texture coordinates |  | ||||||
| #define RL_SUPPORT_MESH_GENERATION         1 |  | ||||||
|  |  | ||||||
| // rmodels: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_MAX_MATERIAL_MAPS              12       // Maximum number of shader maps supported |  | ||||||
| #define RL_MAX_MESH_VERTEX_BUFFERS         7       // Maximum vertex buffers (VBO) per mesh |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: raudio - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Desired audio fileformats to be supported for loading |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_WAV          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_OGG          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_MP3          1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_QOA          1 |  | ||||||
| //#define RL_SUPPORT_FILEFORMAT_FLAC         1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_XM           1 |  | ||||||
| #define RL_SUPPORT_FILEFORMAT_MOD          1 |  | ||||||
|  |  | ||||||
| // raudio: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_AUDIO_DEVICE_FORMAT    ma_format_f32    // Device output format (miniaudio: float-32bit) |  | ||||||
| #define RL_AUDIO_DEVICE_CHANNELS              2    // Device output channels: stereo |  | ||||||
| #define RL_AUDIO_DEVICE_SAMPLE_RATE           0    // Device sample rate (device default) |  | ||||||
|  |  | ||||||
| #define RL_MAX_AUDIO_BUFFER_POOL_CHANNELS    16    // Maximum number of audio pool channels |  | ||||||
|  |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Module: utils - Configuration Flags |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| // Standard file io library (stdio.h) included |  | ||||||
| #define RL_SUPPORT_STANDARD_FILEIO         1 |  | ||||||
| // Show RL_TRACELOG() output messages |  | ||||||
| // NOTE: By default LOG_DEBUG traces not shown |  | ||||||
| #define RL_SUPPORT_TRACELOG                1 |  | ||||||
| //#define RL_SUPPORT_TRACELOG_DEBUG          1 |  | ||||||
|  |  | ||||||
| // utils: Configuration values |  | ||||||
| //------------------------------------------------------------------------------------ |  | ||||||
| #define RL_MAX_TRACELOG_MSG_LENGTH       256       // Max length of one trace-log message |  | ||||||
|  |  | ||||||
| #endif // CONFIG_H |  | ||||||
|  |  | ||||||
| // Indicates of raylib has been refactored |  | ||||||
| #ifndef RL_REFACTORED_CPP |  | ||||||
| #define RL_REFACTORED_CPP |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #define RL_USE_CPP_NAMESPACE 1 |  | ||||||
| #define RL_USE_CPP_MANGLING  1 |  | ||||||
|  |  | ||||||
| #if RL_USE_CPP_NAMESPACE && defined(__cplusplus) |  | ||||||
|     #pragma message("USING CPP NAMESPACE") |  | ||||||
|     #define RL_NS_BEGIN namespace rl { |  | ||||||
|     #define RL_NS_END } |  | ||||||
| #else |  | ||||||
|     #define RL_NS_BEGIN |  | ||||||
|     #define RL_NS_END |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if RL_USE_CPP_MANGLING && defined(__cplusplus) |  | ||||||
|     #pragma message("USING CPP MANGLING") |  | ||||||
|     #define RL_EXTERN_C_BEGIN |  | ||||||
|     #define RL_EXTERN_C_END |  | ||||||
| #else |  | ||||||
|     #ifdef __cplusplus |  | ||||||
|         #define RL_EXTERN_C_BEGIN extern "C" { |  | ||||||
|         #define RL_EXTERN_C_END   } |  | ||||||
|     #else |  | ||||||
|         #define RL_EXTERN_C_BEGIN |  | ||||||
|         #define RL_EXTERN_C_END |  | ||||||
|     #endif |  | ||||||
| #endif |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,562 +0,0 @@ | |||||||
| /******************************************************************************************* |  | ||||||
| * |  | ||||||
| *   rcamera - Basic camera system with support for multiple camera modes |  | ||||||
| * |  | ||||||
| *   CONFIGURATION: |  | ||||||
| *       #define RCAMERA_IMPLEMENTATION |  | ||||||
| *           Generates the implementation of the library into the included file. |  | ||||||
| *           If not defined, the library is in header only mode and can be included in other headers |  | ||||||
| *           or source files without problems. But only ONE file should hold the implementation. |  | ||||||
| * |  | ||||||
| *       #define RCAMERA_STANDALONE |  | ||||||
| *           If defined, the library can be used as standalone as a camera system but some |  | ||||||
| *           functions must be redefined to manage inputs accordingly. |  | ||||||
| * |  | ||||||
| *   CONTRIBUTORS: |  | ||||||
| *       Ramon Santamaria:   Supervision, review, update and maintenance |  | ||||||
| *       Christoph Wagner:   Complete redesign, using raymath (2022) |  | ||||||
| *       Marc Palau:         Initial implementation (2014) |  | ||||||
| * |  | ||||||
| * |  | ||||||
| *   LICENSE: zlib/libpng |  | ||||||
| * |  | ||||||
| *   Copyright (c) 2022-2023 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5) |  | ||||||
| * |  | ||||||
| *   This software is provided "as-is", without any express or implied warranty. In no event |  | ||||||
| *   will the authors be held liable for any damages arising from the use of this software. |  | ||||||
| * |  | ||||||
| *   Permission is granted to anyone to use this software for any purpose, including commercial |  | ||||||
| *   applications, and to alter it and redistribute it freely, subject to the following restrictions: |  | ||||||
| * |  | ||||||
| *     1. The origin of this software must not be misrepresented; you must not claim that you |  | ||||||
| *     wrote the original software. If you use this software in a product, an acknowledgment |  | ||||||
| *     in the product documentation would be appreciated but is not required. |  | ||||||
| * |  | ||||||
| *     2. Altered source versions must be plainly marked as such, and must not be misrepresented |  | ||||||
| *     as being the original software. |  | ||||||
| * |  | ||||||
| *     3. This notice may not be removed or altered from any source distribution. |  | ||||||
| * |  | ||||||
| **********************************************************************************************/ |  | ||||||
|  |  | ||||||
| #ifndef RCAMERA_H |  | ||||||
| #define RCAMERA_H |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Defines and Macros |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Function specifiers definition |  | ||||||
|  |  | ||||||
| // Function specifiers in case library is build/used as a shared library (Windows) |  | ||||||
| // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll |  | ||||||
| #if defined(_WIN32) |  | ||||||
| #if defined(RL_BUILD_LIBTYPE_SHARED) |  | ||||||
| #if defined(__TINYC__) |  | ||||||
| #define __declspec(x) __attribute__((x)) |  | ||||||
| #endif |  | ||||||
| #define RLAPI __declspec(dllexport)     // We are building the library as a Win32 shared library (.dll) |  | ||||||
| #elif defined(RL_USE_LIBTYPE_SHARED) |  | ||||||
| #define RLAPI __declspec(dllimport)     // We are using the library as a Win32 shared library (.dll) |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef RLAPI |  | ||||||
|     #define RLAPI       // Functions defined as 'extern' by default (implicit specifiers) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(RCAMERA_STANDALONE) |  | ||||||
|     #define RL_CAMERA_CULL_DISTANCE_NEAR      0.01 |  | ||||||
|     #define RL_CAMERA_CULL_DISTANCE_FAR    1000.0 |  | ||||||
| #else |  | ||||||
|     #define RL_CAMERA_CULL_DISTANCE_NEAR   RL_CULL_DISTANCE_NEAR |  | ||||||
|     #define RL_CAMERA_CULL_DISTANCE_FAR    RL_CULL_DISTANCE_FAR |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| RL_NS_BEGIN |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Types and Structures Definition |  | ||||||
| // NOTE: Below types are required for standalone usage |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #if defined(RCAMERA_STANDALONE) |  | ||||||
|     // Vector2, 2 components |  | ||||||
|     typedef struct Vector2 { |  | ||||||
|         float x;                // Vector x component |  | ||||||
|         float y;                // Vector y component |  | ||||||
|     } Vector2; |  | ||||||
|  |  | ||||||
|     // Vector3, 3 components |  | ||||||
|     typedef struct Vector3 { |  | ||||||
|         float x;                // Vector x component |  | ||||||
|         float y;                // Vector y component |  | ||||||
|         float z;                // Vector z component |  | ||||||
|     } Vector3; |  | ||||||
|  |  | ||||||
|     // Matrix, 4x4 components, column major, OpenGL style, right-handed |  | ||||||
|     typedef struct Matrix { |  | ||||||
|         float m0, m4, m8, m12;  // Matrix first row (4 components) |  | ||||||
|         float m1, m5, m9, m13;  // Matrix second row (4 components) |  | ||||||
|         float m2, m6, m10, m14; // Matrix third row (4 components) |  | ||||||
|         float m3, m7, m11, m15; // Matrix fourth row (4 components) |  | ||||||
|     } Matrix; |  | ||||||
|  |  | ||||||
|     // Camera type, defines a camera position/orientation in 3d space |  | ||||||
|     typedef struct Camera3D { |  | ||||||
|         Vector3 position;       // Camera position |  | ||||||
|         Vector3 target;         // Camera target it looks-at |  | ||||||
|         Vector3 up;             // Camera up vector (rotation over its axis) |  | ||||||
|         float fovy;             // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic |  | ||||||
|         int projection;         // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC |  | ||||||
|     } Camera3D; |  | ||||||
|  |  | ||||||
|     typedef Camera3D Camera;    // Camera type fallback, defaults to Camera3D |  | ||||||
|  |  | ||||||
|     // Camera projection |  | ||||||
|     typedef enum { |  | ||||||
|         CAMERA_PERSPECTIVE = 0, // Perspective projection |  | ||||||
|         CAMERA_ORTHOGRAPHIC     // Orthographic projection |  | ||||||
|     } CameraProjection; |  | ||||||
|  |  | ||||||
|     // Camera system modes |  | ||||||
|     typedef enum { |  | ||||||
|         CAMERA_CUSTOM = 0,      // Camera custom, controlled by user (update_camera() does nothing) |  | ||||||
|         CAMERA_FREE,            // Camera free mode |  | ||||||
|         CAMERA_ORBITAL,         // Camera orbital, around target, zoom supported |  | ||||||
|         CAMERA_FIRST_PERSON,    // Camera first person |  | ||||||
|         CAMERA_THIRD_PERSON     // Camera third person |  | ||||||
|     } CameraMode; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Global Variables Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module Functions Declaration |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| RL_EXTERN_C_BEGIN |  | ||||||
|  |  | ||||||
| RLAPI Vector3 get_camera_forward(Camera *camera); |  | ||||||
| RLAPI Vector3 get_camera_up(Camera *camera); |  | ||||||
| RLAPI Vector3 get_camera_right(Camera *camera); |  | ||||||
|  |  | ||||||
| // Camera movement |  | ||||||
| RLAPI void camera_move_forward(Camera *camera, float distance, bool moveInWorldPlane); |  | ||||||
| RLAPI void camera_move_up(Camera *camera, float distance); |  | ||||||
| RLAPI void camera_move_right(Camera *camera, float distance, bool moveInWorldPlane); |  | ||||||
| RLAPI void camera_move_to_target(Camera *camera, float delta); |  | ||||||
|  |  | ||||||
| // Camera rotation |  | ||||||
| RLAPI void camera_yaw(Camera *camera, float angle, bool rotateAroundTarget); |  | ||||||
| RLAPI void camera_pitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp); |  | ||||||
| RLAPI void camera_roll(Camera *camera, float angle); |  | ||||||
|  |  | ||||||
| RLAPI Matrix get_camera_view_matrix(Camera *camera); |  | ||||||
| RLAPI Matrix get_camera_projection_matrix(Camera* camera, float aspect); |  | ||||||
|  |  | ||||||
| RL_EXTERN_C_END |  | ||||||
|  |  | ||||||
| RL_NS_END |  | ||||||
|  |  | ||||||
| #endif // RCAMERA_H |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /*********************************************************************************** |  | ||||||
| * |  | ||||||
| *   CAMERA IMPLEMENTATION |  | ||||||
| * |  | ||||||
| ************************************************************************************/ |  | ||||||
|  |  | ||||||
| #if defined(RCAMERA_IMPLEMENTATION) |  | ||||||
|  |  | ||||||
| #include "raymath.h"        // Required for vector maths: |  | ||||||
|                             // vector3_add() |  | ||||||
|                             // vector3_subtract() |  | ||||||
|                             // vector3_scale() |  | ||||||
|                             // vector3_normalize() |  | ||||||
|                             // vector3_distance() |  | ||||||
|                             // vector3_cross_product() |  | ||||||
|                             // vector3_rotate_by_axis_angle() |  | ||||||
|                             // vector3_angle() |  | ||||||
|                             // vector3_negate() |  | ||||||
|                             // matrix_look_at() |  | ||||||
|                             // matrix_perspective() |  | ||||||
|                             // matrix_ortho() |  | ||||||
|                             // matrix_identity() |  | ||||||
|  |  | ||||||
| // raylib required functionality: |  | ||||||
|                             // get_mouse_delta() |  | ||||||
|                             // get_mouse_wheel_move() |  | ||||||
|                             // is_key_down() |  | ||||||
|                             // is_key_pressed() |  | ||||||
|                             // get_frame_time() |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Defines and Macros |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #define CAMERA_MOVE_SPEED                               0.09f |  | ||||||
| #define CAMERA_ROTATION_SPEED                           0.03f |  | ||||||
| #define CAMERA_PAN_SPEED                                0.2f |  | ||||||
|  |  | ||||||
| // Camera mouse movement sensitivity |  | ||||||
| #define CAMERA_MOUSE_MOVE_SENSITIVITY                   0.003f     // TODO: it should be independant of framerate |  | ||||||
| #define CAMERA_MOUSE_SCROLL_SENSITIVITY                 1.5f |  | ||||||
|  |  | ||||||
| #define CAMERA_ORBITAL_SPEED                            0.5f       // Radians per second |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER  8.0f |  | ||||||
| #define CAMERA_FIRST_PERSON_STEP_DIVIDER                30.0f |  | ||||||
| #define CAMERA_FIRST_PERSON_WAVING_DIVIDER              200.0f |  | ||||||
|  |  | ||||||
| // PLAYER (used by camera) |  | ||||||
| #define PLAYER_MOVEMENT_SENSITIVITY                     20.0f |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Types and Structures Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Global Variables Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module specific Functions Declaration |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| RL_NS_BEGIN |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module Functions Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Returns the cameras forward vector (normalized) |  | ||||||
| Vector3 get_camera_forward(Camera *camera) |  | ||||||
| { |  | ||||||
|     return vector3_normalize(vector3_subtract(camera->target, camera->position)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Returns the cameras up vector (normalized) |  | ||||||
| // Note: The up vector might not be perpendicular to the forward vector |  | ||||||
| Vector3 get_camera_up(Camera *camera) |  | ||||||
| { |  | ||||||
|     return vector3_normalize(camera->up); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Returns the cameras right vector (normalized) |  | ||||||
| Vector3 get_camera_right(Camera *camera) |  | ||||||
| { |  | ||||||
|     Vector3 forward = get_camera_forward(camera); |  | ||||||
|     Vector3 up = get_camera_up(camera); |  | ||||||
|  |  | ||||||
|     return vector3_cross_product(forward, up); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Moves the camera in its forward direction |  | ||||||
| void camera_move_forward(Camera *camera, float distance, bool moveInWorldPlane) |  | ||||||
| { |  | ||||||
|     Vector3 forward = get_camera_forward(camera); |  | ||||||
|  |  | ||||||
|     if (moveInWorldPlane) |  | ||||||
|     { |  | ||||||
|         // Project vector onto world plane |  | ||||||
|         forward.y = 0; |  | ||||||
|         forward = vector3_normalize(forward); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Scale by distance |  | ||||||
|     forward = vector3_scale(forward, distance); |  | ||||||
|  |  | ||||||
|     // Move position and target |  | ||||||
|     camera->position = vector3_add(camera->position, forward); |  | ||||||
|     camera->target = vector3_add(camera->target, forward); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Moves the camera in its up direction |  | ||||||
| void camera_move_up(Camera *camera, float distance) |  | ||||||
| { |  | ||||||
|     Vector3 up = get_camera_up(camera); |  | ||||||
|  |  | ||||||
|     // Scale by distance |  | ||||||
|     up = vector3_scale(up, distance); |  | ||||||
|  |  | ||||||
|     // Move position and target |  | ||||||
|     camera->position = vector3_add(camera->position, up); |  | ||||||
|     camera->target = vector3_add(camera->target, up); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Moves the camera target in its current right direction |  | ||||||
| void camera_move_right(Camera *camera, float distance, bool moveInWorldPlane) |  | ||||||
| { |  | ||||||
|     Vector3 right = get_camera_right(camera); |  | ||||||
|  |  | ||||||
|     if (moveInWorldPlane) |  | ||||||
|     { |  | ||||||
|         // Project vector onto world plane |  | ||||||
|         right.y = 0; |  | ||||||
|         right = vector3_normalize(right); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Scale by distance |  | ||||||
|     right = vector3_scale(right, distance); |  | ||||||
|  |  | ||||||
|     // Move position and target |  | ||||||
|     camera->position = vector3_add(camera->position, right); |  | ||||||
|     camera->target = vector3_add(camera->target, right); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Moves the camera position closer/farther to/from the camera target |  | ||||||
| void camera_move_to_target(Camera *camera, float delta) |  | ||||||
| { |  | ||||||
|     float distance = vector3_distance(camera->position, camera->target); |  | ||||||
|  |  | ||||||
|     // Apply delta |  | ||||||
|     distance += delta; |  | ||||||
|  |  | ||||||
|     // Distance must be greater than 0 |  | ||||||
|     if (distance <= 0) distance = 0.001f; |  | ||||||
|  |  | ||||||
|     // Set new distance by moving the position along the forward vector |  | ||||||
|     Vector3 forward = get_camera_forward(camera); |  | ||||||
|     camera->position = vector3_add(camera->target, vector3_scale(forward, -distance)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Rotates the camera around its up vector |  | ||||||
| // Yaw is "looking left and right" |  | ||||||
| // If rotateAroundTarget is false, the camera rotates around its position |  | ||||||
| // Note: angle must be provided in radians |  | ||||||
| void camera_yaw(Camera *camera, float angle, bool rotateAroundTarget) |  | ||||||
| { |  | ||||||
|     // Rotation axis |  | ||||||
|     Vector3 up = get_camera_up(camera); |  | ||||||
|  |  | ||||||
|     // View vector |  | ||||||
|     Vector3 targetPosition = vector3_subtract(camera->target, camera->position); |  | ||||||
|  |  | ||||||
|     // Rotate view vector around up axis |  | ||||||
|     targetPosition = vector3_rotate_by_axis_angle(targetPosition, up, angle); |  | ||||||
|  |  | ||||||
|     if (rotateAroundTarget) |  | ||||||
|     { |  | ||||||
|         // Move position relative to target |  | ||||||
|         camera->position = vector3_subtract(camera->target, targetPosition); |  | ||||||
|     } |  | ||||||
|     else // rotate around camera.position |  | ||||||
|     { |  | ||||||
|         // Move target relative to position |  | ||||||
|         camera->target = vector3_add(camera->position, targetPosition); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Rotates the camera around its right vector, pitch is "looking up and down" |  | ||||||
| //  - lockView prevents camera overrotation (aka "somersaults") |  | ||||||
| //  - rotateAroundTarget defines if rotation is around target or around its position |  | ||||||
| //  - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) |  | ||||||
| // NOTE: angle must be provided in radians |  | ||||||
| void camera_pitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp) |  | ||||||
| { |  | ||||||
|     // Up direction |  | ||||||
|     Vector3 up = get_camera_up(camera); |  | ||||||
|  |  | ||||||
|     // View vector |  | ||||||
|     Vector3 targetPosition = vector3_subtract(camera->target, camera->position); |  | ||||||
|  |  | ||||||
|     if (lockView) |  | ||||||
|     { |  | ||||||
|         // In these camera modes we clamp the Pitch angle |  | ||||||
|         // to allow only viewing straight up or down. |  | ||||||
|  |  | ||||||
|         // clamp view up |  | ||||||
|         float maxAngleUp = vector3_angle(up, targetPosition); |  | ||||||
|         maxAngleUp -= 0.001f; // avoid numerical errors |  | ||||||
|         if (angle > maxAngleUp) angle = maxAngleUp; |  | ||||||
|  |  | ||||||
|         // clamp view down |  | ||||||
|         float maxAngleDown = vector3_angle(vector3_negate(up), targetPosition); |  | ||||||
|         maxAngleDown *= -1.0f; // downwards angle is negative |  | ||||||
|         maxAngleDown += 0.001f; // avoid numerical errors |  | ||||||
|         if (angle < maxAngleDown) angle = maxAngleDown; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Rotation axis |  | ||||||
|     Vector3 right = get_camera_right(camera); |  | ||||||
|  |  | ||||||
|     // Rotate view vector around right axis |  | ||||||
|     targetPosition = vector3_rotate_by_axis_angle(targetPosition, right, angle); |  | ||||||
|  |  | ||||||
|     if (rotateAroundTarget) |  | ||||||
|     { |  | ||||||
|         // Move position relative to target |  | ||||||
|         camera->position = vector3_subtract(camera->target, targetPosition); |  | ||||||
|     } |  | ||||||
|     else // rotate around camera.position |  | ||||||
|     { |  | ||||||
|         // Move target relative to position |  | ||||||
|         camera->target = vector3_add(camera->position, targetPosition); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (rotateUp) |  | ||||||
|     { |  | ||||||
|         // Rotate up direction around right axis |  | ||||||
|         camera->up = vector3_rotate_by_axis_angle(camera->up, right, angle); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Rotates the camera around its forward vector |  | ||||||
| // Roll is "turning your head sideways to the left or right" |  | ||||||
| // Note: angle must be provided in radians |  | ||||||
| void camera_roll(Camera *camera, float angle) |  | ||||||
| { |  | ||||||
|     // Rotation axis |  | ||||||
|     Vector3 forward = get_camera_forward(camera); |  | ||||||
|  |  | ||||||
|     // Rotate up direction around forward axis |  | ||||||
|     camera->up = vector3_rotate_by_axis_angle(camera->up, forward, angle); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Returns the camera view matrix |  | ||||||
| Matrix get_camera_view_matrix(Camera *camera) |  | ||||||
| { |  | ||||||
|     return matrix_look_at(camera->position, camera->target, camera->up); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Returns the camera projection matrix |  | ||||||
| Matrix get_camera_projection_matrix(Camera *camera, float aspect) |  | ||||||
| { |  | ||||||
|     if (camera->projection == CAMERA_PERSPECTIVE) |  | ||||||
|     { |  | ||||||
|         return matrix_perspective(camera->fovy*RL_DEG2RAD, aspect, RL_CAMERA_CULL_DISTANCE_NEAR, RL_CAMERA_CULL_DISTANCE_FAR); |  | ||||||
|     } |  | ||||||
|     else if (camera->projection == CAMERA_ORTHOGRAPHIC) |  | ||||||
|     { |  | ||||||
|         double top = camera->fovy/2.0; |  | ||||||
|         double right = top*aspect; |  | ||||||
|  |  | ||||||
|         return matrix_ortho(-right, right, -top, top, RL_CAMERA_CULL_DISTANCE_NEAR, RL_CAMERA_CULL_DISTANCE_FAR); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return matrix_identity(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #if !defined(RCAMERA_STANDALONE) |  | ||||||
| // Update camera position for selected mode |  | ||||||
| // Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM |  | ||||||
| void update_camera(Camera *camera, int mode) |  | ||||||
| { |  | ||||||
|     Vector2 mousePositionDelta = get_mouse_delta(); |  | ||||||
|  |  | ||||||
|     bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)); |  | ||||||
|     bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); |  | ||||||
|     bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); |  | ||||||
|     bool rotateUp = false; |  | ||||||
|  |  | ||||||
|     if (mode == CAMERA_ORBITAL) |  | ||||||
|     { |  | ||||||
|         // Orbital can just orbit |  | ||||||
|         Matrix rotation = matrix_rotate(get_camera_up(camera), CAMERA_ORBITAL_SPEED*get_frame_time()); |  | ||||||
|         Vector3 view = vector3_subtract(camera->position, camera->target); |  | ||||||
|         view = vector3_transform(view, rotation); |  | ||||||
|         camera->position = vector3_add(camera->target, view); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // Camera rotation |  | ||||||
|         if (is_key_down(KEY_DOWN)) camera_pitch(camera, -CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); |  | ||||||
|         if (is_key_down(KEY_UP)) camera_pitch(camera, CAMERA_ROTATION_SPEED, lockView, rotateAroundTarget, rotateUp); |  | ||||||
|         if (is_key_down(KEY_RIGHT)) camera_yaw(camera, -CAMERA_ROTATION_SPEED, rotateAroundTarget); |  | ||||||
|         if (is_key_down(KEY_LEFT)) camera_yaw(camera, CAMERA_ROTATION_SPEED, rotateAroundTarget); |  | ||||||
|         if (is_key_down(KEY_Q)) camera_roll(camera, -CAMERA_ROTATION_SPEED); |  | ||||||
|         if (is_key_down(KEY_E)) camera_roll(camera, CAMERA_ROTATION_SPEED); |  | ||||||
|  |  | ||||||
|         // Camera movement |  | ||||||
|         if (!is_gamepad_available(0)) |  | ||||||
|         { |  | ||||||
|             // Camera pan (for CAMERA_FREE) |  | ||||||
|             if ((mode == CAMERA_FREE) && (is_mouse_button_down(MOUSE_BUTTON_MIDDLE))) |  | ||||||
|             { |  | ||||||
|                 const Vector2 mouseDelta = get_mouse_delta(); |  | ||||||
|                 if (mouseDelta.x > 0.0f) camera_move_right(camera, CAMERA_PAN_SPEED, moveInWorldPlane); |  | ||||||
|                 if (mouseDelta.x < 0.0f) camera_move_right(camera, -CAMERA_PAN_SPEED, moveInWorldPlane); |  | ||||||
|                 if (mouseDelta.y > 0.0f) camera_move_up(camera, -CAMERA_PAN_SPEED); |  | ||||||
|                 if (mouseDelta.y < 0.0f) camera_move_up(camera, CAMERA_PAN_SPEED); |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 // Mouse support |  | ||||||
|                 camera_yaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); |  | ||||||
|                 camera_pitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // Keyboard support |  | ||||||
|             if (is_key_down(KEY_W)) camera_move_forward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (is_key_down(KEY_A)) camera_move_right(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (is_key_down(KEY_S)) camera_move_forward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (is_key_down(KEY_D)) camera_move_right(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             // Gamepad controller support |  | ||||||
|             camera_yaw(camera, -(get_gamepad_axis_movement(0, GAMEPAD_AXIS_RIGHT_X) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); |  | ||||||
|             camera_pitch(camera, -(get_gamepad_axis_movement(0, GAMEPAD_AXIS_RIGHT_Y) * 2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); |  | ||||||
|  |  | ||||||
|             if (get_gamepad_axis_movement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) camera_move_forward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (get_gamepad_axis_movement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) camera_move_right(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (get_gamepad_axis_movement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) camera_move_forward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|             if (get_gamepad_axis_movement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) camera_move_right(camera, CAMERA_MOVE_SPEED, moveInWorldPlane); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (mode == CAMERA_FREE) |  | ||||||
|         { |  | ||||||
|             if (is_key_down(KEY_SPACE)) camera_move_up(camera, CAMERA_MOVE_SPEED); |  | ||||||
|             if (is_key_down(KEY_LEFT_CONTROL)) camera_move_up(camera, -CAMERA_MOVE_SPEED); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE)) |  | ||||||
|     { |  | ||||||
|         // Zoom target distance |  | ||||||
|         camera_move_to_target(camera, -get_mouse_wheel_move()); |  | ||||||
|         if (is_key_pressed(KEY_KP_SUBTRACT)) camera_move_to_target(camera, 2.0f); |  | ||||||
|         if (is_key_pressed(KEY_KP_ADD)) camera_move_to_target(camera, -2.0f); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| #endif // !RCAMERA_STANDALONE |  | ||||||
|  |  | ||||||
| // Update camera movement, movement/rotation values should be provided by user |  | ||||||
| void update_camera_pro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom) |  | ||||||
| { |  | ||||||
|     // Required values |  | ||||||
|     // movement.x - Move forward/backward |  | ||||||
|     // movement.y - Move right/left |  | ||||||
|     // movement.z - Move up/down |  | ||||||
|     // rotation.x - yaw |  | ||||||
|     // rotation.y - pitch |  | ||||||
|     // rotation.z - roll |  | ||||||
|     // zoom - Move towards target |  | ||||||
|  |  | ||||||
|     bool lockView = true; |  | ||||||
|     bool rotateAroundTarget = false; |  | ||||||
|     bool rotateUp = false; |  | ||||||
|     bool moveInWorldPlane = true; |  | ||||||
|  |  | ||||||
|     // Camera rotation |  | ||||||
|     camera_pitch(camera, -rotation.y*RL_DEG2RAD, lockView, rotateAroundTarget, rotateUp); |  | ||||||
|     camera_yaw(camera, -rotation.x*RL_DEG2RAD, rotateAroundTarget); |  | ||||||
|     camera_roll(camera, rotation.z*RL_DEG2RAD); |  | ||||||
|  |  | ||||||
|     // Camera movement |  | ||||||
|     camera_move_forward(camera, movement.x, moveInWorldPlane); |  | ||||||
|     camera_move_right(camera, movement.y, moveInWorldPlane); |  | ||||||
|     camera_move_up(camera, movement.z); |  | ||||||
|  |  | ||||||
|     // Zoom target distance |  | ||||||
|     camera_move_to_target(camera, zoom); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| RL_NS_END |  | ||||||
|  |  | ||||||
| #endif // RCAMERA_IMPLEMENTATION |  | ||||||
| @@ -1,579 +0,0 @@ | |||||||
| /********************************************************************************************** |  | ||||||
| * |  | ||||||
| *   rgestures - Gestures system, gestures processing based on input events (touch/mouse) |  | ||||||
| * |  | ||||||
| *   CONFIGURATION: |  | ||||||
| *       #define RGESTURES_IMPLEMENTATION |  | ||||||
| *           Generates the implementation of the library into the included file. |  | ||||||
| *           If not defined, the library is in header only mode and can be included in other headers |  | ||||||
| *           or source files without problems. But only ONE file should hold the implementation. |  | ||||||
| * |  | ||||||
| *       #define RGESTURES_STANDALONE |  | ||||||
| *           If defined, the library can be used as standalone to process gesture events with |  | ||||||
| *           no external dependencies. |  | ||||||
| * |  | ||||||
| *   CONTRIBUTORS: |  | ||||||
| *       Marc Palau:         Initial implementation (2014) |  | ||||||
| *       Albert Martos:      Complete redesign and testing (2015) |  | ||||||
| *       Ian Eito:           Complete redesign and testing (2015) |  | ||||||
| *       Ramon Santamaria:   Supervision, review, update and maintenance |  | ||||||
| * |  | ||||||
| * |  | ||||||
| *   LICENSE: zlib/libpng |  | ||||||
| * |  | ||||||
| *   Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) |  | ||||||
| * |  | ||||||
| *   This software is provided "as-is", without any express or implied warranty. In no event |  | ||||||
| *   will the authors be held liable for any damages arising from the use of this software. |  | ||||||
| * |  | ||||||
| *   Permission is granted to anyone to use this software for any purpose, including commercial |  | ||||||
| *   applications, and to alter it and redistribute it freely, subject to the following restrictions: |  | ||||||
| * |  | ||||||
| *     1. The origin of this software must not be misrepresented; you must not claim that you |  | ||||||
| *     wrote the original software. If you use this software in a product, an acknowledgment |  | ||||||
| *     in the product documentation would be appreciated but is not required. |  | ||||||
| * |  | ||||||
| *     2. Altered source versions must be plainly marked as such, and must not be misrepresented |  | ||||||
| *     as being the original software. |  | ||||||
| * |  | ||||||
| *     3. This notice may not be removed or altered from any source distribution. |  | ||||||
| * |  | ||||||
| **********************************************************************************************/ |  | ||||||
|  |  | ||||||
| #ifndef RGESTURES_H |  | ||||||
| #define RGESTURES_H |  | ||||||
|  |  | ||||||
| #ifndef RL_PI |  | ||||||
|     #define RL_PI 3.14159265358979323846 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Defines and Macros |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #ifndef RL_MAX_TOUCH_POINTS |  | ||||||
|     #define RL_MAX_TOUCH_POINTS        8        // Maximum number of touch points supported |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Types and Structures Definition |  | ||||||
| // NOTE: Below types are required for standalone usage |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Boolean type |  | ||||||
| #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) |  | ||||||
|     #include <stdbool.h> |  | ||||||
| #elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) |  | ||||||
|     typedef enum bool { false = 0, true = !false } bool; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include "config.h" |  | ||||||
|  |  | ||||||
| RL_NS_BEGIN |  | ||||||
|  |  | ||||||
| #if !defined(RL_VECTOR2_TYPE) |  | ||||||
| // Vector2 type |  | ||||||
| typedef struct Vector2 { |  | ||||||
|     float x; |  | ||||||
|     float y; |  | ||||||
| } Vector2; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(RGESTURES_STANDALONE) |  | ||||||
| // Gestures type |  | ||||||
| // NOTE: It could be used as flags to enable only some gestures |  | ||||||
| typedef enum { |  | ||||||
|     GESTURE_NONE        = 0, |  | ||||||
|     GESTURE_TAP         = 1, |  | ||||||
|     GESTURE_DOUBLETAP   = 2, |  | ||||||
|     GESTURE_HOLD        = 4, |  | ||||||
|     GESTURE_DRAG        = 8, |  | ||||||
|     GESTURE_SWIPE_RIGHT = 16, |  | ||||||
|     GESTURE_SWIPE_LEFT  = 32, |  | ||||||
|     GESTURE_SWIPE_UP    = 64, |  | ||||||
|     GESTURE_SWIPE_DOWN  = 128, |  | ||||||
|     GESTURE_PINCH_IN    = 256, |  | ||||||
|     GESTURE_PINCH_OUT   = 512 |  | ||||||
| } Gesture; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| typedef enum { |  | ||||||
|     TOUCH_ACTION_UP = 0, |  | ||||||
|     TOUCH_ACTION_DOWN, |  | ||||||
|     TOUCH_ACTION_MOVE, |  | ||||||
|     TOUCH_ACTION_CANCEL |  | ||||||
| } TouchAction; |  | ||||||
|  |  | ||||||
| // Gesture event |  | ||||||
| typedef struct { |  | ||||||
|     int touchAction; |  | ||||||
|     int pointCount; |  | ||||||
|     int pointId[RL_MAX_TOUCH_POINTS]; |  | ||||||
|     Vector2 position[RL_MAX_TOUCH_POINTS]; |  | ||||||
| } GestureEvent; |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Global Variables Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module Functions Declaration |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| RL_EXTERN_C_BEGIN |  | ||||||
|  |  | ||||||
| void process_gesture_event(GestureEvent event);           // Process gesture event and translate it into gestures |  | ||||||
| void update_gestures(void);                              // Update gestures detected (must be called every frame) |  | ||||||
|  |  | ||||||
| #if defined(RGESTURES_STANDALONE) |  | ||||||
| void set_gestures_enabled(unsigned int flags);            // Enable a set of gestures using flags |  | ||||||
| bool is_gesture_detected(int gesture);                    // Check if a gesture have been detected |  | ||||||
| int get_gesture_detected(void);                           // Get latest detected gesture |  | ||||||
|  |  | ||||||
| float get_gesture_hold_duration(void);                     // Get gesture hold time in seconds |  | ||||||
| Vector2 get_gesture_drag_vector(void);                     // Get gesture drag vector |  | ||||||
| float get_gesture_drag_angle(void);                        // Get gesture drag angle |  | ||||||
| Vector2 get_gesture_pinch_vector(void);                    // Get gesture pinch delta |  | ||||||
| float get_gesture_pinch_angle(void);                       // Get gesture pinch angle |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| RL_EXTERN_C_END |  | ||||||
|  |  | ||||||
| RL_NS_END |  | ||||||
|  |  | ||||||
| #endif // RGESTURES_H |  | ||||||
|  |  | ||||||
| /*********************************************************************************** |  | ||||||
| * |  | ||||||
| *   RGESTURES IMPLEMENTATION |  | ||||||
| * |  | ||||||
| ************************************************************************************/ |  | ||||||
|  |  | ||||||
| #if defined(RGESTURES_IMPLEMENTATION) |  | ||||||
|  |  | ||||||
| #if defined(RGESTURES_STANDALONE) |  | ||||||
| #if defined(_WIN32) |  | ||||||
|     #if defined(__cplusplus) |  | ||||||
|     extern "C" {        // Prevents name mangling of functions |  | ||||||
|     #endif |  | ||||||
|     // Functions required to query time on Windows |  | ||||||
|     int __stdcall query_performance_counter(unsigned long long int *lpPerformanceCount); |  | ||||||
|     int __stdcall query_performance_frequency(unsigned long long int *lpFrequency); |  | ||||||
|     #if defined(__cplusplus) |  | ||||||
|     } |  | ||||||
|     #endif |  | ||||||
| #elif defined(__linux__) |  | ||||||
|     #if _POSIX_C_SOURCE < 199309L |  | ||||||
|         #undef _POSIX_C_SOURCE |  | ||||||
|         #define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext. |  | ||||||
|     #endif |  | ||||||
|     #include <sys/time.h>               // Required for: timespec |  | ||||||
|     #include <time.h>                   // Required for: clock_gettime() |  | ||||||
|  |  | ||||||
|     #include <math.h>                   // Required for: sqrtf(), atan2f() |  | ||||||
| #endif |  | ||||||
| #if defined(__APPLE__)                  // macOS also defines __MACH__ |  | ||||||
|     #include <mach/clock.h>             // Required for: clock_get_time() |  | ||||||
|     #include <mach/mach.h>              // Required for: mach_timespec_t |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Defines and Macros |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #define RL_FORCE_TO_SWIPE      0.2f        // Swipe force, measured in normalized screen units/time |  | ||||||
| #define RL_MINIMUM_DRAG        0.015f      // Drag minimum force, measured in normalized screen units (0.0f to 1.0f) |  | ||||||
| #define RL_DRAG_TIMEOUT        0.3f        // Drag minimum time for web, measured in seconds |  | ||||||
| #define RL_MINIMUM_PINCH       0.005f      // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f) |  | ||||||
| #define RL_TAP_TIMEOUT         0.3f        // Tap minimum time, measured in seconds |  | ||||||
| #define RL_PINCH_TIMEOUT       0.3f        // Pinch minimum time, measured in seconds |  | ||||||
| #define RL_DOUBLETAP_RANGE     0.03f       // DoubleTap range, measured in normalized screen units (0.0f to 1.0f) |  | ||||||
|  |  | ||||||
| RL_NS_BEGIN |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Types and Structures Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| // Gestures module state context [136 bytes] |  | ||||||
| typedef struct { |  | ||||||
|     unsigned int current;               // Current detected gesture |  | ||||||
|     unsigned int enabledFlags;          // Enabled gestures flags |  | ||||||
|     struct { |  | ||||||
|         int firstId;                    // Touch id for first touch point |  | ||||||
|         int pointCount;                 // Touch points counter |  | ||||||
|         double eventTime;               // Time stamp when an event happened |  | ||||||
|         Vector2 upPosition;             // Touch up position |  | ||||||
|         Vector2 downPositionA;          // First touch down position |  | ||||||
|         Vector2 downPositionB;          // Second touch down position |  | ||||||
|         Vector2 downDragPosition;       // Touch drag position |  | ||||||
|         Vector2 moveDownPositionA;      // First touch down position on move |  | ||||||
|         Vector2 moveDownPositionB;      // Second touch down position on move |  | ||||||
|         Vector2 previousPositionA;      // Previous position A to compare for pinch gestures |  | ||||||
|         Vector2 previousPositionB;      // Previous position B to compare for pinch gestures |  | ||||||
|         int tapCounter;                 // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions) |  | ||||||
|     } Touch; |  | ||||||
|     struct { |  | ||||||
|         bool resetRequired;             // HOLD reset to get first touch point again |  | ||||||
|         double timeDuration;            // HOLD duration in seconds |  | ||||||
|     } Hold; |  | ||||||
|     struct { |  | ||||||
|         Vector2 vector;                 // DRAG vector (between initial and current position) |  | ||||||
|         float angle;                    // DRAG angle (relative to x-axis) |  | ||||||
|         float distance;                 // DRAG distance (from initial touch point to final) (normalized [0..1]) |  | ||||||
|         float intensity;                // DRAG intensity, how far why did the DRAG (pixels per frame) |  | ||||||
|     } Drag; |  | ||||||
|     struct { |  | ||||||
|         double startTime;               // SWIPE start time to calculate drag intensity |  | ||||||
|     } Swipe; |  | ||||||
|     struct { |  | ||||||
|         Vector2 vector;                 // PINCH vector (between first and second touch points) |  | ||||||
|         float angle;                    // PINCH angle (relative to x-axis) |  | ||||||
|         float distance;                 // PINCH displacement distance (normalized [0..1]) |  | ||||||
|     } Pinch; |  | ||||||
| } GesturesData; |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Global Variables Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| static GesturesData GESTURES = { |  | ||||||
| #ifdef __cplusplus |  | ||||||
|     (unsigned int)-1, |  | ||||||
|     GESTURE_NONE, |  | ||||||
|     0b0000001111111111 |  | ||||||
| #else |  | ||||||
|     .Touch.firstId = -1, |  | ||||||
|     .current = GESTURE_NONE,        // No current gesture detected |  | ||||||
|     .enabledFlags = 0b0000001111111111  // All gestures supported by default |  | ||||||
| #endif |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module specific Functions Declaration |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| static float rg_vector2_angle(Vector2 initialPosition, Vector2 finalPosition); |  | ||||||
| static float rg_vector2_distance(Vector2 v1, Vector2 v2); |  | ||||||
| static double rg_get_current_time(void); |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module Functions Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
|  |  | ||||||
| // Enable only desired gestures to be detected |  | ||||||
| void set_gestures_enabled(unsigned int flags) |  | ||||||
| { |  | ||||||
|     GESTURES.enabledFlags = flags; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Check if a gesture have been detected |  | ||||||
| bool is_gesture_detected(unsigned int gesture) |  | ||||||
| { |  | ||||||
|     if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true; |  | ||||||
|     else return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Process gesture event and translate it into gestures |  | ||||||
| void process_gesture_event(GestureEvent event) |  | ||||||
| { |  | ||||||
|     // Reset required variables |  | ||||||
|     GESTURES.Touch.pointCount = event.pointCount;      // Required on update_gestures() |  | ||||||
|  |  | ||||||
|     if (GESTURES.Touch.pointCount == 1)     // One touch point |  | ||||||
|     { |  | ||||||
|         if (event.touchAction == TOUCH_ACTION_DOWN) |  | ||||||
|         { |  | ||||||
|             GESTURES.Touch.tapCounter++;    // Tap counter |  | ||||||
|  |  | ||||||
|             // Detect GESTURE_DOUBLE_TAP |  | ||||||
|             if ((GESTURES.current == GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((rg_get_current_time() - GESTURES.Touch.eventTime) < RL_TAP_TIMEOUT) && (rg_vector2_distance(GESTURES.Touch.downPositionA, event.position[0]) < RL_DOUBLETAP_RANGE)) |  | ||||||
|             { |  | ||||||
|                 GESTURES.current = GESTURE_DOUBLETAP; |  | ||||||
|                 GESTURES.Touch.tapCounter = 0; |  | ||||||
|             } |  | ||||||
|             else    // Detect GESTURE_TAP |  | ||||||
|             { |  | ||||||
|                 GESTURES.Touch.tapCounter = 1; |  | ||||||
|                 GESTURES.current = GESTURE_TAP; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             GESTURES.Touch.downPositionA = event.position[0]; |  | ||||||
|             GESTURES.Touch.downDragPosition = event.position[0]; |  | ||||||
|  |  | ||||||
|             GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA; |  | ||||||
|             GESTURES.Touch.eventTime = rg_get_current_time(); |  | ||||||
|  |  | ||||||
|             GESTURES.Swipe.startTime = rg_get_current_time(); |  | ||||||
|  |  | ||||||
|         #ifdef __cplusplus |  | ||||||
|             GESTURES.Drag.vector = Vector2{ 0.0f, 0.0f }; |  | ||||||
|         #else |  | ||||||
|             GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f }; |  | ||||||
|         #endif |  | ||||||
|         } |  | ||||||
|         else if (event.touchAction == TOUCH_ACTION_UP) |  | ||||||
|         { |  | ||||||
|             // A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases |  | ||||||
|             if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0]; |  | ||||||
|  |  | ||||||
|             // NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen |  | ||||||
|             GESTURES.Drag.distance = rg_vector2_distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition); |  | ||||||
|             GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((rg_get_current_time() - GESTURES.Swipe.startTime)); |  | ||||||
|  |  | ||||||
|             // Detect GESTURE_SWIPE |  | ||||||
|             if ((GESTURES.Drag.intensity > RL_FORCE_TO_SWIPE) && (GESTURES.current != GESTURE_DRAG)) |  | ||||||
|             { |  | ||||||
|                 // NOTE: Angle should be inverted in Y |  | ||||||
|                 GESTURES.Drag.angle = 360.0f - rg_vector2_angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition); |  | ||||||
|  |  | ||||||
|                 if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT;          // Right |  | ||||||
|                 else if ((GESTURES.Drag.angle >= 30) && (GESTURES.Drag.angle <= 150)) GESTURES.current = GESTURE_SWIPE_UP;      // Up |  | ||||||
|                 else if ((GESTURES.Drag.angle > 150) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT;     // Left |  | ||||||
|                 else if ((GESTURES.Drag.angle >= 210) && (GESTURES.Drag.angle <= 330)) GESTURES.current = GESTURE_SWIPE_DOWN;   // Down |  | ||||||
|                 else GESTURES.current = GESTURE_NONE; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 GESTURES.Drag.distance = 0.0f; |  | ||||||
|                 GESTURES.Drag.intensity = 0.0f; |  | ||||||
|                 GESTURES.Drag.angle = 0.0f; |  | ||||||
|  |  | ||||||
|                 GESTURES.current = GESTURE_NONE; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         #if __cplusplus |  | ||||||
|             GESTURES.Touch.downDragPosition = Vector2{ 0.0f, 0.0f }; |  | ||||||
|         #else |  | ||||||
|             GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f }; |  | ||||||
|         #endif |  | ||||||
|             GESTURES.Touch.pointCount = 0; |  | ||||||
|         } |  | ||||||
|         else if (event.touchAction == TOUCH_ACTION_MOVE) |  | ||||||
|         { |  | ||||||
|             GESTURES.Touch.moveDownPositionA = event.position[0]; |  | ||||||
|  |  | ||||||
|             if (GESTURES.current == GESTURE_HOLD) |  | ||||||
|             { |  | ||||||
|                 if (GESTURES.Hold.resetRequired) GESTURES.Touch.downPositionA = event.position[0]; |  | ||||||
|  |  | ||||||
|                 GESTURES.Hold.resetRequired = false; |  | ||||||
|  |  | ||||||
|                 // Detect GESTURE_DRAG |  | ||||||
|                 if ((rg_get_current_time() - GESTURES.Touch.eventTime) > RL_DRAG_TIMEOUT) |  | ||||||
|                 { |  | ||||||
|                     GESTURES.Touch.eventTime = rg_get_current_time(); |  | ||||||
|                     GESTURES.current = GESTURE_DRAG; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x; |  | ||||||
|             GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     else if (GESTURES.Touch.pointCount == 2)    // Two touch points |  | ||||||
|     { |  | ||||||
|         if (event.touchAction == TOUCH_ACTION_DOWN) |  | ||||||
|         { |  | ||||||
|             GESTURES.Touch.downPositionA = event.position[0]; |  | ||||||
|             GESTURES.Touch.downPositionB = event.position[1]; |  | ||||||
|  |  | ||||||
|             GESTURES.Touch.previousPositionA = GESTURES.Touch.downPositionA; |  | ||||||
|             GESTURES.Touch.previousPositionB = GESTURES.Touch.downPositionB; |  | ||||||
|  |  | ||||||
|             //GESTURES.Pinch.distance = rg_vector2_distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB); |  | ||||||
|  |  | ||||||
|             GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x; |  | ||||||
|             GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y; |  | ||||||
|  |  | ||||||
|             GESTURES.current = GESTURE_HOLD; |  | ||||||
|             GESTURES.Hold.timeDuration = rg_get_current_time(); |  | ||||||
|         } |  | ||||||
|         else if (event.touchAction == TOUCH_ACTION_MOVE) |  | ||||||
|         { |  | ||||||
|             GESTURES.Pinch.distance = rg_vector2_distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB); |  | ||||||
|  |  | ||||||
|             GESTURES.Touch.moveDownPositionA = event.position[0]; |  | ||||||
|             GESTURES.Touch.moveDownPositionB = event.position[1]; |  | ||||||
|  |  | ||||||
|             GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x; |  | ||||||
|             GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y; |  | ||||||
|  |  | ||||||
|             if ((rg_vector2_distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.moveDownPositionA) >= RL_MINIMUM_PINCH) || (rg_vector2_distance(GESTURES.Touch.previousPositionB, GESTURES.Touch.moveDownPositionB) >= RL_MINIMUM_PINCH)) |  | ||||||
|             { |  | ||||||
|                 if ( rg_vector2_distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.previousPositionB) > rg_vector2_distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) ) GESTURES.current = GESTURE_PINCH_IN; |  | ||||||
|                 else GESTURES.current = GESTURE_PINCH_OUT; |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 GESTURES.current = GESTURE_HOLD; |  | ||||||
|                 GESTURES.Hold.timeDuration = rg_get_current_time(); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // NOTE: Angle should be inverted in Y |  | ||||||
|             GESTURES.Pinch.angle = 360.0f - rg_vector2_angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB); |  | ||||||
|         } |  | ||||||
|         else if (event.touchAction == TOUCH_ACTION_UP) |  | ||||||
|         { |  | ||||||
|             GESTURES.Pinch.distance = 0.0f; |  | ||||||
|             GESTURES.Pinch.angle = 0.0f; |  | ||||||
|         #if __cplusplus |  | ||||||
|             GESTURES.Pinch.vector = Vector2{ 0.0f, 0.0f }; |  | ||||||
|         #else |  | ||||||
|             GESTURES.Pinch.vector = (Vector2){ 0.0f, 0.0f }; |  | ||||||
|         #endif |  | ||||||
|             GESTURES.Touch.pointCount = 0; |  | ||||||
|  |  | ||||||
|             GESTURES.current = GESTURE_NONE; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     else if (GESTURES.Touch.pointCount > 2)     // More than two touch points |  | ||||||
|     { |  | ||||||
|         // TODO: Process gesture events for more than two points |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Update gestures detected (must be called every frame) |  | ||||||
| void update_gestures(void) |  | ||||||
| { |  | ||||||
|     // NOTE: Gestures are processed through system callbacks on touch events |  | ||||||
|  |  | ||||||
|     // Detect GESTURE_HOLD |  | ||||||
|     if (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2)) |  | ||||||
|     { |  | ||||||
|         GESTURES.current = GESTURE_HOLD; |  | ||||||
|         GESTURES.Hold.timeDuration = rg_get_current_time(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Detect GESTURE_NONE |  | ||||||
|     if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN)) |  | ||||||
|     { |  | ||||||
|         GESTURES.current = GESTURE_NONE; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get latest detected gesture |  | ||||||
| int get_gesture_detected(void) |  | ||||||
| { |  | ||||||
|     // Get current gesture only if enabled |  | ||||||
|     return (GESTURES.enabledFlags & GESTURES.current); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Hold time measured in ms |  | ||||||
| float get_gesture_hold_duration(void) |  | ||||||
| { |  | ||||||
|     // NOTE: time is calculated on current gesture HOLD |  | ||||||
|  |  | ||||||
|     double time = 0.0; |  | ||||||
|  |  | ||||||
|     if (GESTURES.current == GESTURE_HOLD) time = rg_get_current_time() - GESTURES.Hold.timeDuration; |  | ||||||
|  |  | ||||||
|     return (float)time; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get drag vector (between initial touch point to current) |  | ||||||
| Vector2 get_gesture_drag_vector(void) |  | ||||||
| { |  | ||||||
|     // NOTE: drag vector is calculated on one touch points TOUCH_ACTION_MOVE |  | ||||||
|  |  | ||||||
|     return GESTURES.Drag.vector; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get drag angle |  | ||||||
| // NOTE: Angle in degrees, horizontal-right is 0, counterclockwise |  | ||||||
| float get_gesture_drag_angle(void) |  | ||||||
| { |  | ||||||
|     // NOTE: drag angle is calculated on one touch points TOUCH_ACTION_UP |  | ||||||
|  |  | ||||||
|     return GESTURES.Drag.angle; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get distance between two pinch points |  | ||||||
| Vector2 get_gesture_pinch_vector(void) |  | ||||||
| { |  | ||||||
|     // NOTE: Pinch distance is calculated on two touch points TOUCH_ACTION_MOVE |  | ||||||
|  |  | ||||||
|     return GESTURES.Pinch.vector; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Get angle between two pinch points |  | ||||||
| // NOTE: Angle in degrees, horizontal-right is 0, counterclockwise |  | ||||||
| float get_gesture_pinch_angle(void) |  | ||||||
| { |  | ||||||
|     // NOTE: pinch angle is calculated on two touch points TOUCH_ACTION_MOVE |  | ||||||
|  |  | ||||||
|     return GESTURES.Pinch.angle; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module specific Functions Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Get angle from two-points vector with X-axis |  | ||||||
| static float rg_vector2_angle(Vector2 v1, Vector2 v2) |  | ||||||
| { |  | ||||||
|     float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/RL_PI); |  | ||||||
|  |  | ||||||
|     if (angle < 0) angle += 360.0f; |  | ||||||
|  |  | ||||||
|     return angle; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Calculate distance between two Vector2 |  | ||||||
| static float rg_vector2_distance(Vector2 v1, Vector2 v2) |  | ||||||
| { |  | ||||||
|     float result; |  | ||||||
|  |  | ||||||
|     float dx = v2.x - v1.x; |  | ||||||
|     float dy = v2.y - v1.y; |  | ||||||
|  |  | ||||||
|     result = (float)sqrt(dx*dx + dy*dy); |  | ||||||
|  |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Time measure returned are seconds |  | ||||||
| static double rg_get_current_time(void) |  | ||||||
| { |  | ||||||
|     double time = 0; |  | ||||||
|  |  | ||||||
| #if !defined(RGESTURES_STANDALONE) |  | ||||||
|     time = get_time(); |  | ||||||
| #else |  | ||||||
| #if defined(_WIN32) |  | ||||||
|     unsigned long long int clockFrequency, currentTime; |  | ||||||
|  |  | ||||||
|     query_performance_frequency(&clockFrequency);     // BE CAREFUL: Costly operation! |  | ||||||
|     query_performance_counter(¤tTime); |  | ||||||
|  |  | ||||||
|     time = (double)currentTime/clockFrequency;  // Time in seconds |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(__linux__) |  | ||||||
|     // NOTE: Only for Linux-based systems |  | ||||||
|     struct timespec now; |  | ||||||
|     clock_gettime(CLOCK_MONOTONIC, &now); |  | ||||||
|     unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;     // Time in nanoseconds |  | ||||||
|  |  | ||||||
|     time = ((double)nowTime*1e-9);     // Time in seconds |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(__APPLE__) |  | ||||||
|     //#define CLOCK_REALTIME  CALENDAR_CLOCK    // returns UTC time since 1970-01-01 |  | ||||||
|     //#define CLOCK_MONOTONIC SYSTEM_CLOCK      // returns the time since boot time |  | ||||||
|  |  | ||||||
|     clock_serv_t cclock; |  | ||||||
|     mach_timespec_t now; |  | ||||||
|     host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); |  | ||||||
|  |  | ||||||
|     // NOTE: OS X does not have clock_gettime(), using clock_get_time() |  | ||||||
|     clock_get_time(cclock, &now); |  | ||||||
|     mach_port_deallocate(mach_task_self(), cclock); |  | ||||||
|     unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec;     // Time in nanoseconds |  | ||||||
|  |  | ||||||
|     time = ((double)nowTime*1e-9);     // Time in seconds |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     return time; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| RL_NS_END |  | ||||||
|  |  | ||||||
| #endif // RGESTURES_IMPLEMENTATION |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,81 +0,0 @@ | |||||||
| /********************************************************************************************** |  | ||||||
| * |  | ||||||
| *   raylib.utils - Some common utility functions |  | ||||||
| * |  | ||||||
| * |  | ||||||
| *   LICENSE: zlib/libpng |  | ||||||
| * |  | ||||||
| *   Copyright (c) 2014-2023 Ramon Santamaria (@raysan5) |  | ||||||
| * |  | ||||||
| *   This software is provided "as-is", without any express or implied warranty. In no event |  | ||||||
| *   will the authors be held liable for any damages arising from the use of this software. |  | ||||||
| * |  | ||||||
| *   Permission is granted to anyone to use this software for any purpose, including commercial |  | ||||||
| *   applications, and to alter it and redistribute it freely, subject to the following restrictions: |  | ||||||
| * |  | ||||||
| *     1. The origin of this software must not be misrepresented; you must not claim that you |  | ||||||
| *     wrote the original software. If you use this software in a product, an acknowledgment |  | ||||||
| *     in the product documentation would be appreciated but is not required. |  | ||||||
| * |  | ||||||
| *     2. Altered source versions must be plainly marked as such, and must not be misrepresented |  | ||||||
| *     as being the original software. |  | ||||||
| * |  | ||||||
| *     3. This notice may not be removed or altered from any source distribution. |  | ||||||
| * |  | ||||||
| **********************************************************************************************/ |  | ||||||
|  |  | ||||||
| #ifndef UTILS_H |  | ||||||
| #define UTILS_H |  | ||||||
|  |  | ||||||
| #if defined(PLATFORM_ANDROID) |  | ||||||
|     #include <stdio.h>                      // Required for: FILE |  | ||||||
|     #include <android/asset_manager.h>      // Required for: AAssetManager |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(RL_SUPPORT_TRACELOG) |  | ||||||
|     #define RL_TRACELOG(level, ...) RL_NS(trace_log)(level, __VA_ARGS__) |  | ||||||
|  |  | ||||||
|     #if defined(RL_SUPPORT_TRACELOG_DEBUG) |  | ||||||
|         #define TRACELOGD(...) RL_NS(trace_log)(LOG_DEBUG, __VA_ARGS__) |  | ||||||
|     #else |  | ||||||
|         #define TRACELOGD(...) (void)0 |  | ||||||
|     #endif |  | ||||||
| #else |  | ||||||
|     #define RL_TRACELOG(level, ...) (void)0 |  | ||||||
|     #define TRACELOGD(...) (void)0 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Some basic Defines |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #if defined(PLATFORM_ANDROID) |  | ||||||
|     #define fopen(name, mode) android_fopen(name, mode) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Types and Structures Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| //... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Global Variables Definition |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Nop... |  | ||||||
|  |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| // Module Functions Declaration |  | ||||||
| //---------------------------------------------------------------------------------- |  | ||||||
| #if defined(__cplusplus) |  | ||||||
| extern "C" {            // Prevents name mangling of functions |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(PLATFORM_ANDROID) |  | ||||||
| void init_asset_manager(AAssetManager *manager, const char *dataPath);   // Initialize asset manager from android app |  | ||||||
| FILE *android_fopen(const char *fileName, const char *mode);           // Replacement for fopen() -> Read-only! |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if defined(__cplusplus) |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #endif // UTILS_H |  | ||||||
										
											Binary file not shown.
										
									
								
							| @@ -1,8 +0,0 @@ | |||||||
| #include "raudio.c" |  | ||||||
| #include "rcore.c" |  | ||||||
| #include "rglfw.c" |  | ||||||
| #include "rmodels.c" |  | ||||||
| #include "rshapes.c" |  | ||||||
| #include "rtext.c" |  | ||||||
| #include "rtextures.c" |  | ||||||
| #include "rutils.c" |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,242 +0,0 @@ | |||||||
| // rlgl.h |  | ||||||
|  |  | ||||||
| word RL_NOT_REFACTORED, RL_REFACTORED_CPP |  | ||||||
|  |  | ||||||
| namespace rl_, |  | ||||||
| namespace rl, |  | ||||||
| namespace rlgl, |  | ||||||
| not word  rl |  | ||||||
| not word  rlgl |  | ||||||
|  |  | ||||||
| namespace RL_LOG_,         LOG_ |  | ||||||
| namespace RL_PIXELFORMAT_, PIXELFORMAT_ |  | ||||||
| namespace RL_TEXTURE_,     TEXTURE_ |  | ||||||
| namespace RL_SHADER_,      SHADER_ |  | ||||||
| namespace RL_BLEND_,       BLEND_ |  | ||||||
| namespace RL_ATTACHMENT_,  ATTACHMENT_ |  | ||||||
| namespace RL_CULL_,        CULL_ |  | ||||||
|  |  | ||||||
| not include rlgl.h |  | ||||||
|  |  | ||||||
| word TRACELOG, RL_TRACELOG |  | ||||||
|  |  | ||||||
| word RLGL, GLOBAL_DATA |  | ||||||
|  |  | ||||||
| word Vector2,             Vector2 |  | ||||||
| word Vector3,             Vector3 |  | ||||||
| word Vector4,             Vector4 |  | ||||||
| word Quaternion,          Quaternion |  | ||||||
| word Matrix,              Matrix |  | ||||||
| word Color,               Color |  | ||||||
| word Rectangle,           Rectangle |  | ||||||
| word Image,               Image |  | ||||||
| word Texture,             Texture |  | ||||||
| word Texture2D,           Texture2d |  | ||||||
| word TextureCubemap,      Texture_Cubemap |  | ||||||
| word RenderTexture,       Render_Texture |  | ||||||
| word RenderTexture2D,     Render_Texture2D |  | ||||||
| word NPatchInfo,          N_Patch_Info |  | ||||||
| word GlyphInfo,           Glyph_Info |  | ||||||
| word Font,                Font |  | ||||||
| word Camera3D,            Camera3D |  | ||||||
| word Camera,              Camera |  | ||||||
| word Camera2D,            Camera2D |  | ||||||
| word Mesh,                Mesh |  | ||||||
| word Shader,              Shader |  | ||||||
| word MaterialMap,         Material_Map |  | ||||||
| word Material,            Material |  | ||||||
| word Transform,           Transform |  | ||||||
| word BoneInfo,            Bone_Info |  | ||||||
| word Model,               Model |  | ||||||
| word ModelAnimation,      Model_Animation |  | ||||||
| word Ray,                 Ray |  | ||||||
| word RayCollision,        Ray_Collision |  | ||||||
| word BoundingBox,         Bounding_box |  | ||||||
| word Wave,                Wave |  | ||||||
| word rAudioBuffer,        Audio_Buffer |  | ||||||
| word rAudioProcessor,     Audio_Processor |  | ||||||
| word AudioStream,         Audio_Stream |  | ||||||
| word Sound,               Sound |  | ||||||
| word Music,               Music |  | ||||||
| word VrDeviceInfo,        VR_Device_Info |  | ||||||
| word VrStereoConfig,      VR_Stereo_Config |  | ||||||
| word FilePathList,        File_Path_List |  | ||||||
| word AutomationEvent,     Automation_Event |  | ||||||
| word AutomationEventList, Automation_Event_List |  | ||||||
| word Matrix,              Matrix |  | ||||||
|  |  | ||||||
| word rlVertexBuffer,                 vertex_buffer |  | ||||||
| word rlDrawCall,                     draw_call |  | ||||||
| word rlRenderBatch,                  render_batch |  | ||||||
| word rlGlVersion,                    gl_version |  | ||||||
| word rlTraceLogLevel,                trace_log_level |  | ||||||
| word rlPixelFormat,                  pixel_format |  | ||||||
| word rlTextureFilter,                texture_filter |  | ||||||
| word rlShaderLocationIndex,          shader_location_index |  | ||||||
| word rlShaderUniformDataType,        shader_uniform_data_type |  | ||||||
| word rlShaderAttributeDataType,      shader_attribute_data_type |  | ||||||
| word rlBlendMode,                    blend_mode |  | ||||||
| word rlFramebufferAttachType,        framebuffer_attach_type |  | ||||||
| word rlFramebufferAttachTextureType, framebuffer_attach_texture_type |  | ||||||
| word rlCullMode,                     cull_mode |  | ||||||
|  |  | ||||||
| word get_pixel_data_size, gpu_get_pixel_data_size |  | ||||||
|  |  | ||||||
| word rlMatrixMode,                       matrix_mode |  | ||||||
| word rlPushMatrix,                       push_matrix |  | ||||||
| word rlPopMatrix,                        pop_matrix |  | ||||||
| word rlLoadIdentity,                     load_identity |  | ||||||
| word rlTranslatef,                       translatef |  | ||||||
| word rlRotatef,                          rotatef |  | ||||||
| word rlScalef,                           scalef |  | ||||||
| word rlMultMatrixf,                      mult_matrixf |  | ||||||
| word rlFrustum,                          frustum |  | ||||||
| word rlOrtho,                            ortho |  | ||||||
| word rlViewport,                         viewport |  | ||||||
| word rlBegin,                            begin |  | ||||||
| word rlEnd,                              end |  | ||||||
| word rlVertex2i,                         vertex2i |  | ||||||
| word rlVertex2f,                         vertex2f |  | ||||||
| word rlVertex3f,                         vertex3f |  | ||||||
| word rlTexCoord2f,                       tex_coord2f |  | ||||||
| word rlNormal3f,                         normal3f |  | ||||||
| word rlColor4ub,                         color4ub |  | ||||||
| word rlColor3f,                          color3f |  | ||||||
| word rlColor4f,                          color4f |  | ||||||
| word rlEnableVertexArray,                enable_vertex_array |  | ||||||
| word rlDisableVertexArray,               disable_vertex_array |  | ||||||
| word rlEnableVertexBuffer,               enable_vertex_buffer |  | ||||||
| word rlDisableVertexBuffer,              disable_vertex_buffer |  | ||||||
| word rlEnableVertexBufferElement,        enable_vertex_buffer_element |  | ||||||
| word rlDisableVertexBufferElement,       disable_vertex_buffer_element |  | ||||||
| word rlEnableVertexAttribute,            enable_vertex_attribute |  | ||||||
| word rlDisableVertexAttribute,           disable_vertex_attribute |  | ||||||
| word rlEnableStatePointer,               enable_state_pointer |  | ||||||
| word rlDisableStatePointer,              disable_state_pointer |  | ||||||
| word rlActiveTextureSlot,                active_texture_slot |  | ||||||
| word rlEnableTexture,                    enable_texture |  | ||||||
| word rlDisableTexture,                   disable_texture |  | ||||||
| word rlEnableTextureCubemap,             enable_texture_cubemap |  | ||||||
| word rlDisableTextureCubemap,            disable_texture_cubemap |  | ||||||
| word rlTextureParameters,                texture_parameters |  | ||||||
| word rlCubemapParameters,                cubemap_parameters |  | ||||||
| word rlEnableShader,                     enable_shader |  | ||||||
| word rlDisableShader,                    disable_shader |  | ||||||
| word rlEnableFramebuffer,                enable_framebuffer |  | ||||||
| word rlDisableFramebuffer,               disable_framebuffer |  | ||||||
| word rlActiveDrawBuffers,                active_draw_buffers |  | ||||||
| word rlBlitFramebuffer,                  blit_framebuffer |  | ||||||
| word rlEnableColorBlend,                 enable_color_blend |  | ||||||
| word rlDisableColorBlend,                disable_color_blend |  | ||||||
| word rlEnableDepthTest,                  enable_depth_test |  | ||||||
| word rlDisableDepthTest,                 disable_depth_test |  | ||||||
| word rlEnableDepthMask,                  enable_depth_mask |  | ||||||
| word rlDisableDepthMask,                 disable_depth_mask |  | ||||||
| word rlEnableBackfaceCulling,            enable_backface_culling |  | ||||||
| word rlDisableBackfaceCulling,           disable_backface_culling |  | ||||||
| word rlSetCullFace,                      set_cull_face |  | ||||||
| word rlEnableScissorTest,                enable_scissor_test |  | ||||||
| word rlDisableScissorTest,               disable_scissor_test |  | ||||||
| word rlScissor,                          scissor |  | ||||||
| word rlEnableWireMode,                   enable_wire_mode |  | ||||||
| word rlEnablePointMode,                  enable_point_mode |  | ||||||
| word rlDisableWireMode,                  disable_wire_mode |  | ||||||
| word rlSetLineWidth,                     set_line_width |  | ||||||
| word rlGetLineWidth,                     get_line_width |  | ||||||
| word rlEnableSmoothLines,                enable_smooth_lines |  | ||||||
| word rlDisableSmoothLines,               disable_smooth_lines |  | ||||||
| word rlEnableStereoRender,               enable_stereo_render |  | ||||||
| word rlDisableStereoRender,              disable_stereo_render |  | ||||||
| word rlIsStereoRenderEnabled,            is_stereo_render_enabled |  | ||||||
| word rlClearColor,                       clear_color |  | ||||||
| word rlClearScreenBuffers,               clear_screen_buffers |  | ||||||
| word rlCheckErrors,                      check_errors |  | ||||||
| word rlSetBlendMode,                     set_blend_mode |  | ||||||
| word rlSetBlendFactors,                  set_blend_factors |  | ||||||
| word rlSetBlendFactorsSeparate,          set_blend_factors_separate |  | ||||||
| word rlglInit,                           init |  | ||||||
| word rlglClose,                          close |  | ||||||
| word rlLoadExtensions,                   load_extensions |  | ||||||
| word rlGetVersion,                       get_version |  | ||||||
| word rlSetFramebufferWidth,              set_framebuffer_width |  | ||||||
| word rlGetFramebufferWidth,              get_framebuffer_width |  | ||||||
| word rlSetFramebufferHeight,             set_framebuffer_height |  | ||||||
| word rlGetFramebufferHeight,             get_framebuffer_height |  | ||||||
| word rlGetTextureIdDefault,              get_texture_id_default |  | ||||||
| word rlGetShaderIdDefault,               get_shader_id_default |  | ||||||
| word rlLoadRenderBatch,                  load_render_batch |  | ||||||
| word rlUnloadRenderBatch,                unload_render_batch |  | ||||||
| word rlDrawRenderBatch,                  draw_render_batch |  | ||||||
| word rlSetRenderBatchActive,             set_render_batch_active |  | ||||||
| word rlDrawRenderBatchActive,            draw_render_batch_active |  | ||||||
| word rlCheckRenderBatchLimit,            check_render_batch_limit |  | ||||||
| word rlSetTexture,                       set_texture |  | ||||||
| word rlLoadVertexArray,                  load_vertex_array |  | ||||||
| word rlLoadVertexBuffer,                 load_vertex_buffer |  | ||||||
| word rlLoadVertexBufferElement,          load_vertex_buffer_element |  | ||||||
| word rlUpdateVertexBuffer,               update_vertex_buffer |  | ||||||
| word rlUpdateVertexBufferElements,       update_vertex_buffer_elements |  | ||||||
| word rlUnloadVertexArray,                unload_vertex_array |  | ||||||
| word rlUnloadVertexBuffer,               unload_vertex_buffer |  | ||||||
| word rlSetVertexAttribute,               set_vertex_attribute |  | ||||||
| word rlSetVertexAttributeDivisor,        set_vertex_attribute_divisor |  | ||||||
| word rlSetVertexAttributeDefault,        set_vertex_attribute_default |  | ||||||
| word rlDrawVertexArray,                  draw_vertex_array |  | ||||||
| word rlDrawVertexArrayElements,          draw_vertex_array_elements |  | ||||||
| word rlDrawVertexArrayInstanced,         draw_vertex_array_instanced |  | ||||||
| word rlDrawVertexArrayElementsInstanced, draw_vertex_array_elements_instanced |  | ||||||
| word rlLoadTexture,                      load_texture |  | ||||||
| word rlLoadTextureDepth,                 load_texture_depth |  | ||||||
| word rlLoadTextureCubemap,               load_texture_cubemap |  | ||||||
| word rlUpdateTexture,                    update_texture |  | ||||||
| word rlGetGlTextureFormats,              get_gl_texture_formats |  | ||||||
| word rlUnloadTexture,                    unload_texture |  | ||||||
| word rlGenTextureMipmaps,                gen_texture_mipmaps |  | ||||||
| word rlLoadFramebuffer,                  load_framebuffer |  | ||||||
| word rlFramebufferAttach,                framebuffer_attach |  | ||||||
| word rlFramebufferComplete,              framebuffer_complete |  | ||||||
| word rlUnloadFramebuffer,                unload_framebuffer |  | ||||||
| word rlLoadShaderCode,                   load_shader_code |  | ||||||
| word rlCompileShader,                    compile_shader |  | ||||||
| word rlLoadShaderProgram,                load_shader_program |  | ||||||
| word rlUnloadShaderProgram,              unload_shader_program |  | ||||||
| word rlGetLocationUniform,               get_location_uniform |  | ||||||
| word rlGetLocationAttrib,                get_location_attrib |  | ||||||
| word rlSetUniform,                       set_uniform |  | ||||||
| word rlSetUniformMatrix,                 set_uniform_matrix |  | ||||||
| word rlSetUniformSampler,                set_uniform_sampler |  | ||||||
| word rlSetShader,                        set_shader |  | ||||||
| word rlLoadComputeShaderProgram,         load_compute_shader_program |  | ||||||
| word rlComputeShaderDispatch,            compute_shader_dispatch |  | ||||||
| word rlLoadShaderBuffer,                 load_shader_buffer |  | ||||||
| word rlUnloadShaderBuffer,               unload_shader_buffer |  | ||||||
| word rlUpdateShaderBuffer,               update_shader_buffer |  | ||||||
| word rlBindShaderBuffer,                 bind_shader_buffer |  | ||||||
| word rlReadShaderBuffer,                 read_shader_buffer |  | ||||||
| word rlCopyShaderBuffer,                 copy_shader_buffer |  | ||||||
| word rlGetShaderBufferSize,              get_shader_buffer_size |  | ||||||
| word rlBindImageTexture,                 bind_image_texture |  | ||||||
| word rlGetMatrixModelview,               get_matrix_modelview |  | ||||||
| word rlGetMatrixProjection,              get_matrix_projection |  | ||||||
| word rlGetMatrixTransform,               get_matrix_transform |  | ||||||
| word rlGetMatrixProjectionStereo,        get_matrix_projection_stereo |  | ||||||
| word rlGetMatrixViewOffsetStereo,        get_matrix_view_offset_stereo |  | ||||||
| word rlSetMatrixProjection,              set_matrix_projection |  | ||||||
| word rlSetMatrixModelview,               set_matrix_modelview |  | ||||||
| word rlSetMatrixProjectionStereo,        set_matrix_projection_stereo |  | ||||||
| word rlSetMatrixViewOffsetStereo,        set_matrix_view_offset_stereo |  | ||||||
| word rlLoadDrawCube,                     load_draw_cube |  | ||||||
| word rlLoadDrawQuad,                     load_draw_quad |  | ||||||
| word rlLoadShaderDefault,                load_shader_default |  | ||||||
| word rlUnloadShaderDefault,              unload_shader_default |  | ||||||
| word rlGetPixelDataSize,                 internal_get_pixel_data_size |  | ||||||
| word rlMatrixIdentity,                   internal_matrix_identity |  | ||||||
| word rlMatrixMultiply,                   internal_matrix_multiply |  | ||||||
| word rlCheckRenderBatchLimit,            check_render_batch_limit |  | ||||||
| word rlLoadShaderDefault,                load_shader_default |  | ||||||
| word rlSetMatrixProjection,              set_matrix_projection |  | ||||||
| word rlUnloadFramebuffer,                unload_framebuffer |  | ||||||
| word rlReadScreenPixels,                 read_screen_pixels |  | ||||||
| word rlReadTexturePixels,                read_texture_pixels |  | ||||||
| word rlGetShaderLocsDefault,             get_shader_locs_default |  | ||||||
| word rlGetPixelFormatName,               get_pixel_format_name |  | ||||||
| @@ -1,322 +0,0 @@ | |||||||
| #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS |  | ||||||
| #define GEN_BENCHMARK |  | ||||||
| #define GEN_ENFORCE_STRONG_CODE_TYPES |  | ||||||
| // #define GEN_IMPLEMENTATION |  | ||||||
| #include "gen.cpp" |  | ||||||
| #include "gen.builder.cpp" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| constexpr char const* path_config_h    = "config.h"; |  | ||||||
| constexpr char const* path_raylib_h    = "raylib.h"; |  | ||||||
| constexpr char const* path_raymath_h   = "raymath.h"; |  | ||||||
| constexpr char const* path_rcamera_h   = "rcamera.h"; |  | ||||||
| constexpr char const* path_rcore_h     = "rcore.h"; |  | ||||||
| constexpr char const* path_rgestures_h = "rgestures.h"; |  | ||||||
| constexpr char const* path_rgl_h       = "rgl.h"; |  | ||||||
| constexpr char const* path_rtext_h     = "rtext.h"; |  | ||||||
|  |  | ||||||
| constexpr char const* path_rcore_desktop_c = "rcore_desktop.c"; |  | ||||||
|  |  | ||||||
| constexpr char const* path_raudio_c    = "raudio.c"; |  | ||||||
| constexpr char const* path_rcore_c     = "rcore.c"; |  | ||||||
| constexpr char const* path_rglfw_c     = "rglfw.c"; |  | ||||||
| constexpr char const* path_rmodels_c   = "rmodels.c"; |  | ||||||
| constexpr char const* path_rtext_c     = "rtext.c"; |  | ||||||
| constexpr char const* path_rtextures_c = "rtextures.c"; |  | ||||||
| constexpr char const* path_rutils_c    = "rutils.c"; |  | ||||||
|  |  | ||||||
| using namespace gen; |  | ||||||
|  |  | ||||||
| StringCached upper_snake_to_mixed_snake(StringCached str) |  | ||||||
| { |  | ||||||
|     local_persist String scratch = String::make_reserve(GlobalAllocator, kilobytes(1)); |  | ||||||
|     scratch.clear(); |  | ||||||
|  |  | ||||||
|     bool capitalizeNext = true; |  | ||||||
|  |  | ||||||
|     for (s32 index = 0; index < str.length(); ++index) |  | ||||||
|     { |  | ||||||
|         char c = str[index]; |  | ||||||
|  |  | ||||||
|         if (c == '_') |  | ||||||
|         { |  | ||||||
|             scratch.append(c); |  | ||||||
|             capitalizeNext = true; |  | ||||||
|         } |  | ||||||
|         else if (capitalizeNext) |  | ||||||
|         { |  | ||||||
|             if (c >= 'a' && c <= 'z') |  | ||||||
|             { |  | ||||||
|                 scratch.append(c - 32); // Convert to uppercase |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 scratch.append(c); |  | ||||||
|             } |  | ||||||
|             capitalizeNext = false; |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             if (c >= 'A' && c <= 'Z') |  | ||||||
|             { |  | ||||||
|                 scratch.append(c + 32); // Convert to lowercase |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 scratch.append(c); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     StringCached result = get_cached_string(scratch); |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| StringCached pascal_to_lower_snake(StringCached str) |  | ||||||
| { |  | ||||||
|     local_persist String scratch = String::make_reserve(GlobalAllocator, kilobytes(1)); |  | ||||||
|     scratch.clear(); |  | ||||||
|  |  | ||||||
|     for (s32 index = 0; index < str.length(); ++index) |  | ||||||
|     { |  | ||||||
|         char c = str[index]; |  | ||||||
|         char next = (index + 1 < str.length()) ? str[index + 1] : '\0'; // Ensure we don't go out of bounds |  | ||||||
|  |  | ||||||
|         // Whitelist check for "2D" and "3D" |  | ||||||
|         if ((c == '2' || c == '3' | c == '4') && (next == 'D' || next == 'd')) |  | ||||||
|         { |  | ||||||
|             if (index > 0) // If it's not the start of the string, append an underscore |  | ||||||
|             { |  | ||||||
|                 char* prev = str.Data + index - 1; |  | ||||||
|                 if (*prev != '_') // Avoid double underscores |  | ||||||
|                 { |  | ||||||
|                     scratch.append('_'); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             scratch.append(c); |  | ||||||
|             scratch.append('d'); // Convert to lowercase |  | ||||||
|             index++; // Skip the next character since we've already processed it |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (c >= 'A' && c <= 'Z') |  | ||||||
|         { |  | ||||||
|             char* prev = (index > 0) ? str.Data + index - 1 : nullptr; |  | ||||||
|  |  | ||||||
|             if ((index > 0 && prev && *prev >= 'a' && *prev <= 'z') ||  |  | ||||||
|                 (prev && char_is_digit(*prev) && (next >= 'A' && next <= 'Z'))) |  | ||||||
|             { |  | ||||||
|                 scratch.append('_'); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             scratch.append(c + 32); |  | ||||||
|         } |  | ||||||
|         else if (char_is_digit(c) && (next >= 'A' && next <= 'Z')) // Check for a number followed by an uppercase letter |  | ||||||
|         { |  | ||||||
|             scratch.append(c); |  | ||||||
|             scratch.append('_'); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             scratch.append(c); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     StringCached result = get_cached_string(scratch); |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_define( CodeDefine& code ) |  | ||||||
| { |  | ||||||
| 	local_persist String name_scratch = String::make_reserve( GlobalAllocator, kilobytes(1) ); |  | ||||||
|  |  | ||||||
| 	if ( str_compare( elem->Name, txt("RL"), 2 ) == 0 || str_compare( elem->Name, txt("RAYLIB"), 6 ) == 0 ) |  | ||||||
| 		continue; |  | ||||||
|  |  | ||||||
| 	name_scratch.append_fmt( "%RL_%S", elem->Name ); |  | ||||||
| 	elem->Name = get_cached_string( name_scratch ); |  | ||||||
| 	name_scratch.clear(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_enum( CodeEnum& code ) |  | ||||||
| { |  | ||||||
| 	for ( Code elem : code->Body ) |  | ||||||
| 	{ |  | ||||||
| 		if ( elem->Type == ECode::Untyped ) |  | ||||||
| 		{ |  | ||||||
| 			elem->Content = upper_snake_to_mixed_snake( elem->Content ); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_typename( CodeType& type ) |  | ||||||
| { |  | ||||||
| 	local_persist CodeType t_unsigned_char      = parse_type( code(unsigned char) ); |  | ||||||
| 	local_persist CodeType t_unsigned_char_ptr  = parse_type( code(unsigned char*) ); |  | ||||||
| 	local_persist CodeType t_unsigned_short_ptr	= parse_type( code(unsigned short*) ); |  | ||||||
| 	local_persist CodeType t_int                = parse_type( code(int) ); |  | ||||||
| 	local_persist CodeType t_int_ptr 		    = parse_type( code(int*) ); |  | ||||||
| 	local_persist CodeType t_unsigned_int       = parse_type( code(unsigned int) ); |  | ||||||
| 	local_persist CodeType t_float 	            = parse_type( code(float) ); |  | ||||||
| 	local_persist CodeType t_float_ptr          = parse_type( code(float*) ); |  | ||||||
|  |  | ||||||
| 	local_persist CodeType t_f32_ptr = parse_type( code(f32*) ); |  | ||||||
| 	local_persist CodeType t_u8_ptr  = parse_type( code(u8*) ); |  | ||||||
| 	local_persist CodeType t_s32_ptr = parse_type( code(s32*) ); |  | ||||||
|  |  | ||||||
| 	String type_str = type.to_string(); |  | ||||||
|  |  | ||||||
| 	if ( str_compare( type_str, t_unsigned_char.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_u8.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_unsigned_char_ptr.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_u8_ptr.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_unsigned_short_ptr.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_u8_ptr.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_int.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_s32.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_int_ptr.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_s32_ptr.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_unsigned_int.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_u32.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_float.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_f32.ast; |  | ||||||
| 	} |  | ||||||
| 	if ( str_compare( type_str, t_float_ptr.to_string() ) == 0 ) |  | ||||||
| 	{ |  | ||||||
| 		type.ast = t_f32_ptr.ast; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_fn( CodeFn& fn ) |  | ||||||
| { |  | ||||||
| 	StringCached original_name = fn->Name; |  | ||||||
| 	fn->Name = pascal_to_lower_snake( fn->Name ); |  | ||||||
|  |  | ||||||
| 	log_fmt( "%S", "Proc ID: %S -> %S", original_name, fn->Name ); |  | ||||||
|  |  | ||||||
| 	for ( CodeParam param : fn->Params ) |  | ||||||
| 	{ |  | ||||||
| 		refactor_typename( param->ValueType ); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_struct( CodeStruct& code ) |  | ||||||
| { |  | ||||||
| 	for ( Code field : code->Body ) |  | ||||||
| 	{ |  | ||||||
| 		if ( field->Type == ECode::Variable ) |  | ||||||
| 		{ |  | ||||||
| 			CodeVar var = field.cast<CodeVar>(); |  | ||||||
| 			refactor_typename( var->ValueType ); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void refactor_file( char const* path ) |  | ||||||
| { |  | ||||||
| 	FileContents contents = file_read_contents( GlobalAllocator, true, path ); |  | ||||||
| 	CodeBody     code     = parse_global_body( { contents.size, rcast(char const*, contents.data) } ); |  | ||||||
|  |  | ||||||
| 	local_perist String name_scratch = String::make_reserve( GlobalAllocator, kilobytes(1) ); |  | ||||||
|  |  | ||||||
| 	// CodeBody includes |  | ||||||
| 	// CodeBody nspace_body = def_body( ECode::Namespace ); |  | ||||||
| 	CodeBody new_code = def_body( ECode::Global_Body ); |  | ||||||
|  |  | ||||||
| 	for ( Code elem : code ) |  | ||||||
| 	{ |  | ||||||
| 		if ( elem->Type == ECode::Preprocess_Define ) |  | ||||||
| 		{ |  | ||||||
| 			refactor_define( elem.cast<CodeDefine>() ); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( elem->Type == ECode::Enum ) |  | ||||||
| 		{ |  | ||||||
| 			refactor_enum( elem.cast<CodeEnum>() ); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( elem->Type == ECode::Typedef ) |  | ||||||
| 		{ |  | ||||||
| 			CodeTypedef td = elem.cast<CodeTypedef>(); |  | ||||||
| 			if ( td->UnderlyingType->Type == ECode::Enum ) |  | ||||||
| 			{ |  | ||||||
| 				CodeEnum code = td->UnderlyingType.cast<CodeEnum>(); |  | ||||||
| 				refactor_enum( code ); |  | ||||||
| 			} |  | ||||||
| 			if ( td->UnderlyingType->Type == ECode::Struct ) |  | ||||||
| 			{ |  | ||||||
| 				CodeStruct code = td->UnderlyingType.cast<CodeStruct>(); |  | ||||||
| 				refactor_struct( code ); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( elem->Type == ECode::Struct ) |  | ||||||
| 		{ |  | ||||||
| 			refactor_struct( elem.cast<CodeStruct>() ); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( elem->Type == ECode::Function || elem->Type == ECode::Function_Fwd ) |  | ||||||
| 		{ |  | ||||||
| 			refactor_fn( elem.cast<CodeFn>() ); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if ( elem->Type == ECode::Extern_Linkage ) |  | ||||||
| 		{ |  | ||||||
| 			CodeBody body = elem.cast<CodeExtern>()->Body; |  | ||||||
| 			for ( Code elem : body ) |  | ||||||
| 			{ |  | ||||||
| 				if ( elem->Type == ECode::Function || elem->Type == ECode::Function_Fwd ) |  | ||||||
| 				{ |  | ||||||
| 					refactor_fn( elem.cast<CodeFn>() ); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			Code nspace = def_namespace( txt("raylib"), def_namespace_body( args(elem) ) ); |  | ||||||
| 			elem = nspace; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		new_code.append( elem ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Builder builder = Builder::open( path ); |  | ||||||
| 	builder.print( new_code ); |  | ||||||
| 	builder.write(); |  | ||||||
|  |  | ||||||
| 	name_scratch.clear(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int gen_main() |  | ||||||
| { |  | ||||||
| 	gen::init(); |  | ||||||
|  |  | ||||||
| 	refactor_file( path_config_h ); |  | ||||||
| 	refactor_file( path_raylib_h ); |  | ||||||
| 	refactor_file( path_rcamera_h ); |  | ||||||
| 	refactor_file( path_raymath_h ); |  | ||||||
| 	refactor_file( path_rcore_h ); |  | ||||||
| 	refactor_file( path_rgl_h ); |  | ||||||
| 	refactor_file( path_rtext_h ); |  | ||||||
|  |  | ||||||
| 	refactor_file( path_rcore_desktop_c ); |  | ||||||
| 	refactor_file( path_raudio_c ); |  | ||||||
| 	refactor_file( path_rcore_c ); |  | ||||||
| 	refactor_file( path_rglfw_c ); |  | ||||||
| 	refactor_file( path_rmodels_c ); |  | ||||||
| 	refactor_file( path_rtext_c ); |  | ||||||
| 	refactor_file( path_rutils_c ); |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @@ -1,10 +0,0 @@ | |||||||
| # Vis AST |  | ||||||
|  |  | ||||||
| AST visualizer for gencpp |  | ||||||
|  |  | ||||||
| This is a early start to creating frontend tooling for c/c++ using gencpp as a core component.   |  | ||||||
| I'll be exploring creating an AST explorer for this library with raylib as the graphical & general platform vendor for dependencies that go beyond the scope of gencpp. |  | ||||||
|  |  | ||||||
| For now I'll have its build script in this file, however it will heavily rely on gencpp's helper scripts. |  | ||||||
|  |  | ||||||
| Whatever sort of UX tooling I setup for this will be reused for the other tools I'll be creating for gencpp. |  | ||||||
| @@ -1,256 +0,0 @@ | |||||||
| Clear-Host |  | ||||||
|  |  | ||||||
| $path_root     = git rev-parse --show-toplevel |  | ||||||
| $path_scripts  = Join-Path $path_root 'scripts' |  | ||||||
|  |  | ||||||
| $target_arch        = Join-Path $path_scripts 'helpers/target_arch.psm1' |  | ||||||
| $devshell           = Join-Path $path_scripts 'helpers/devshell.ps1' |  | ||||||
| $format_cpp	        = Join-Path $path_scripts 'helpers/format_cpp.psm1' |  | ||||||
| $incremental_checks = Join-Path $path_scripts 'helpers/incremental_checks.ps1' |  | ||||||
| $vendor_toolchain   = Join-Path $path_scripts 'helpers/vendor_toolchain.ps1' |  | ||||||
|  |  | ||||||
| $path_project  = Join-Path $path_root     'project' |  | ||||||
| $path_aux      = Join-Path $path_project  'auxillary' |  | ||||||
| $path_vis_root = Join-Path $path_aux      'vis_ast' |  | ||||||
| $path_binaries = Join-Path $path_vis_root 'binaries' |  | ||||||
|  |  | ||||||
| $path_deps = Join-Path $path_vis_root 'dependencies' |  | ||||||
| $path_temp = Join-Path $path_deps     'temp' |  | ||||||
|  |  | ||||||
| Import-Module $target_arch |  | ||||||
| Import-Module $format_cpp |  | ||||||
|  |  | ||||||
| #region Arguments |  | ||||||
| $vendor           = $null |  | ||||||
| $optimize         = $null |  | ||||||
| $debug 	          = $null |  | ||||||
| $analysis	      = $false |  | ||||||
| $dev              = $false |  | ||||||
| $verbose          = $null |  | ||||||
|  |  | ||||||
| [array] $vendors = @( "clang", "msvc" ) |  | ||||||
|  |  | ||||||
| # This is a really lazy way of parsing the args, could use actual params down the line... |  | ||||||
|  |  | ||||||
| if ( $args ) { $args | ForEach-Object { |  | ||||||
| switch ($_){ |  | ||||||
|  { $_ -in $vendors }   { $vendor    = $_; break } |  | ||||||
|  "optimize"            { $optimize  = $true } |  | ||||||
|  "debug"               { $debug     = $true } |  | ||||||
|  "analysis"            { $analysis  = $true } |  | ||||||
|  "dev"                 { $dev       = $true } |  | ||||||
|  "verbose"             { $verbose   = $true } |  | ||||||
| } |  | ||||||
| }} |  | ||||||
| #endregion Argument |  | ||||||
|  |  | ||||||
| # Load up toolchain configuraion |  | ||||||
| . $vendor_toolchain |  | ||||||
| . $incremental_checks |  | ||||||
|  |  | ||||||
| # Clear out the current content first |  | ||||||
| if ( test-path $path_temp) { |  | ||||||
| 	remove-item $path_temp -Recurse |  | ||||||
| } |  | ||||||
| New-Item -ItemType Directory -Path $path_temp |  | ||||||
|  |  | ||||||
| if ( -not (Test-Path $path_binaries) ) { |  | ||||||
| 	New-Item -ItemType Directory -Path $path_binaries |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function setup-raylib { |  | ||||||
| 	$path_raylib     = join-path $path_deps   'raylib' |  | ||||||
| 	$path_raylib_inc = join-path $path_raylib 'include' |  | ||||||
| 	$path_raylib_lib = join-path $path_raylib 'lib' |  | ||||||
| 	if ( test-path $path_raylib_inc ) { |  | ||||||
| 		remove-item $path_raylib_inc -recurse |  | ||||||
| 		remove-item $path_raylib_lib -recurse |  | ||||||
| 	} |  | ||||||
| 	new-item -path $path_raylib_inc -ItemType Directory |  | ||||||
| 	new-item -path $path_raylib_lib -ItemType Directory |  | ||||||
|  |  | ||||||
| 	$url_raylib_zip  = 'https://github.com/Ed94/raylib_refactored/archive/refs/heads/refactor-support.zip' |  | ||||||
| 	$path_raylib_zip = join-path $path_temp 'raylib.zip' |  | ||||||
|  |  | ||||||
| 	$path_raylib_master      = join-path $path_temp          'raylib_refactored-refactor-support' |  | ||||||
| 	$path_raylib_src         = join-path $path_raylib_master 'src' |  | ||||||
| 	$path_raylib_platforms   = join-path $path_raylib_src    'platforms' |  | ||||||
| 	$path_raylib_glfw_inc    = join-path $path_raylib_src    'external/glfw/include' |  | ||||||
| 	$path_raylib_gputex      = join-path $path_raylib_src    'external/rl_gputex.h' |  | ||||||
|  |  | ||||||
| 	if ( test-path $path_raylib_master ) { |  | ||||||
| 		remove-item $path_raylib_master -Recurse |  | ||||||
| 	} |  | ||||||
| 	invoke-webrequest -uri $url_raylib_zip   -outfile $path_raylib_zip |  | ||||||
| 	expand-archive    -path $path_raylib_zip -destinationpath $path_temp |  | ||||||
|  |  | ||||||
| 	write-host "Building raylib with $vendor" |  | ||||||
|  |  | ||||||
| 	$path_build = Join-Path $path_raylib 'build' |  | ||||||
| 	if ( (Test-Path $path_build) -eq $false ) { |  | ||||||
| 		New-Item $path_build -ItemType Directory |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	$raylib_headers  = Get-ChildItem -Path $path_raylib_src -Filter '*.h' -File |  | ||||||
| 	$raylib_modules  = get-childitem -path $path_raylib_src -filter '*.c' -file |  | ||||||
|  |  | ||||||
| 	# Refactor with refactor.exe |  | ||||||
| 	if ( $true ) { |  | ||||||
| 		$path_refactor      = join-path $path_raylib 'raylib_cpp.refactor' |  | ||||||
| 		$path_refactor_rlgl = join-path $path_raylib 'raylib_cpp_gl.refactor' |  | ||||||
|  |  | ||||||
| 		$files = @() |  | ||||||
| 		foreach ( $header in $raylib_headers ) { |  | ||||||
| 			$file_name = split-path $header -leaf |  | ||||||
|  |  | ||||||
| 			if ( -not $file_name.Equals('rlgl.h' ) ) { |  | ||||||
| 				$files += "$header" |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		foreach ( $module in $raylib_modules ) { |  | ||||||
| 			$files += "$module" |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		$files += "$path_raylib_gputex" |  | ||||||
|  |  | ||||||
| 		$platform_modules = @() |  | ||||||
| 		foreach ( $module in (get-childitem -path $path_raylib_platforms -filter '*.c' -file) ) { |  | ||||||
| 			$platform_modules += "$module" |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		$path_rlgl = join-path $path_raylib_src 'rlgl.h' |  | ||||||
|  |  | ||||||
| 		Push-Location $path_raylib_src |  | ||||||
| 			write-host "Beginning refactor...`n" |  | ||||||
| 			$refactors = @(@()) |  | ||||||
| 			$refactorParams = @( |  | ||||||
| 				# "-debug", |  | ||||||
| 				"-num=$($files.Count)" |  | ||||||
| 				"-src=$($files)", |  | ||||||
| 				"-spec=$($path_refactor)" |  | ||||||
| 			) |  | ||||||
| 			& refactor $refactorParams |  | ||||||
| 			Write-Host "`nRefactoring complete`n`n" |  | ||||||
| 		Pop-Location |  | ||||||
|  |  | ||||||
| 		Push-Location $path_raylib_platforms |  | ||||||
| 		write-host "Beginning refactor...`n" |  | ||||||
| 			$refactors = @(@()) |  | ||||||
| 			$refactorParams = @( |  | ||||||
| 				# "-debug", |  | ||||||
| 				"-num=$($platform_modules.Count)" |  | ||||||
| 				"-src=$($platform_modules)", |  | ||||||
| 				"-spec=$($path_refactor)" |  | ||||||
| 			) |  | ||||||
| 			& refactor $refactorParams |  | ||||||
| 			Write-Host "`nRefactoring complete`n`n" |  | ||||||
| 		Pop-Location |  | ||||||
|  |  | ||||||
| 		Push-Location $path_raylib_src |  | ||||||
| 			$gl_modules = @( "$path_rlgl", "$path_raylib_gputex" ) |  | ||||||
|  |  | ||||||
| 			write-host "Beginning refactor just for rlgl.h...`n" |  | ||||||
| 			$refactors = @(@()) |  | ||||||
| 			$refactorParams = @( |  | ||||||
| 				# "-debug", |  | ||||||
| 				"-num=$($gl_modules.Count)" |  | ||||||
| 				"-src=$($gl_modules)", |  | ||||||
| 				"-spec=$($path_refactor_rlgl)" |  | ||||||
| 			) |  | ||||||
| 			& refactor $refactorParams |  | ||||||
| 			Write-Host "`nRefactoring complete`n`n" |  | ||||||
| 		Pop-Location |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	# Refactor raylib with gencpp |  | ||||||
| 	if ( $false ) { |  | ||||||
| 	# if ( $false ) { |  | ||||||
| 		$path_gencpp = join-path $path_root 'project/gen' |  | ||||||
|  |  | ||||||
| 		$includes = @( |  | ||||||
| 			$path_gencpp |  | ||||||
| 		) |  | ||||||
|  |  | ||||||
| 		$compiler_args = @( |  | ||||||
| 			($flag_define + 'GEN_TIME') |  | ||||||
| 		) |  | ||||||
|  |  | ||||||
| 		$linker_args = @( |  | ||||||
|  |  | ||||||
| 		) |  | ||||||
|  |  | ||||||
| 		$unit       = join-path $path_raylib 'raylib_refactor.cpp' |  | ||||||
| 		$executable = join-path $path_build  'raylib_refactor.exe' |  | ||||||
|  |  | ||||||
| 		$build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable |  | ||||||
| 		Push-Location $path_raylib_src |  | ||||||
| 			if ( Test-Path( $executable ) ) { |  | ||||||
| 				Measure-Command { & $executable |  | ||||||
| 						| ForEach-Object { |  | ||||||
| 							write-host `t $_ -ForegroundColor Green |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 			} |  | ||||||
| 		Pop-Location |  | ||||||
|  |  | ||||||
| 		push-location $path_scripts |  | ||||||
| 		# Time to format |  | ||||||
| 		$fmt_includes = @() |  | ||||||
| 		foreach ( $header in $raylib_headers ) { |  | ||||||
| 			$fmt_includes +=  split-path $header -leaf |  | ||||||
| 		} |  | ||||||
| 		foreach ( $module in $raylib_modules ) { |  | ||||||
| 			$fmt_includes +=  split-path $module -leaf |  | ||||||
| 		} |  | ||||||
| 		format-cpp $path_raylib_src $fmt_includes $null |  | ||||||
| 		pop-location |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	# Build raylib |  | ||||||
| 	if ( $true ) { |  | ||||||
| 		# Microsoft |  | ||||||
| 		$lib_gdi32   = 'Gdi32.lib' |  | ||||||
| 		$lib_shell32 = 'Shell32.lib' |  | ||||||
| 		$lib_xinput  = 'Xinput.lib' |  | ||||||
| 		$lib_user32  = 'User32.lib' |  | ||||||
| 		$lib_winmm   = 'Winmm.lib' |  | ||||||
|  |  | ||||||
| 		$includes = @( |  | ||||||
| 			$path_raylib_src, |  | ||||||
| 			$path_raylib_glfw_inc |  | ||||||
| 		) |  | ||||||
| 		foreach ($include in $includes) { |  | ||||||
| 			write-host $include |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		$compiler_args = @( |  | ||||||
| 			($flag_define + 'PLATFORM_DESKTOP'), |  | ||||||
| 			($flag_define + 'RL_BUILD_LIBTYPE_SHARED'), |  | ||||||
| 			$flag_all_cpp |  | ||||||
| 		) |  | ||||||
| 		$linker_args   = @( |  | ||||||
| 			$flag_link_dll, |  | ||||||
|  |  | ||||||
| 			# $lib_xinput, |  | ||||||
| 			$lib_gdi32, |  | ||||||
| 			$lib_shell32, |  | ||||||
| 			$lib_user32, |  | ||||||
| 			$lib_winmm |  | ||||||
| 		) |  | ||||||
|  |  | ||||||
| 		# $unit = join-path $path_raylib     'raylib.c' |  | ||||||
| 		$dll  = join-path $path_raylib_lib 'raylib.dll' |  | ||||||
| 		# $build_result = build-simple $path_build $includes $compiler_args $linker_args $unit $dll |  | ||||||
|  |  | ||||||
| 		$build_result = build $path_build $includes $compiler_args $linker_args $raylib_modules $dll |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	# Move headers to used include |  | ||||||
| 	foreach ($header in $raylib_headers) { |  | ||||||
| 		Copy-Item -Path $header -Destination (join-path $path_raylib_inc (split-path $header -Leaf)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	# Don't want to remove as it hampers debugging. |  | ||||||
| 	# remove-item -path $path_temp -Recurse |  | ||||||
| } |  | ||||||
| setup-raylib |  | ||||||
| @@ -1,6 +1,7 @@ | |||||||
| #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_EXPOSE_BACKEND | ||||||
|  | #define GEN_SUPPORT_CPP_MEMBER_FEATURES 0 | ||||||
| #include "gen.cpp" | #include "gen.cpp" | ||||||
|  |  | ||||||
| #include "helpers/push_ignores.inline.hpp" | #include "helpers/push_ignores.inline.hpp" | ||||||
| @@ -20,6 +21,44 @@ constexpr char const* generation_notice = | |||||||
| "// This file was generated automatially by gencpp's bootstrap.cpp " | "// This file was generated automatially by gencpp's bootstrap.cpp " | ||||||
| "(See: https://github.com/Ed94/gencpp)\n\n"; | "(See: https://github.com/Ed94/gencpp)\n\n"; | ||||||
|  |  | ||||||
|  | #include <cstdlib>   // for system() | ||||||
|  |  | ||||||
|  | void format_file( char const* path ) | ||||||
|  | { | ||||||
|  | 	String resolved_path = string_make(GlobalAllocator, to_str(path)); | ||||||
|  |  | ||||||
|  | 	String style_arg = string_make(GlobalAllocator, txt("-style=file:")); | ||||||
|  | 	append( style_arg, "../scripts/.clang-format "); | ||||||
|  |  | ||||||
|  | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
|  | 	#define clang_format      "clang-format " | ||||||
|  | 	#define cf_format_inplace "-i " | ||||||
|  | 	#define cf_verbose        "-verbose " | ||||||
|  | 	String command = string_make( GlobalAllocator, clang_format ); | ||||||
|  | 	append( command, cf_format_inplace ); | ||||||
|  | 	append( command, cf_verbose ); | ||||||
|  | 	append( command, style_arg ); | ||||||
|  | 	append( command, resolved_path ); | ||||||
|  | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
|  | 		system( command ); | ||||||
|  | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
|  | 	#undef cf_cmd | ||||||
|  | 	#undef cf_format_inplace | ||||||
|  | 	#undef cf_style | ||||||
|  | 	#undef cf_verbse | ||||||
|  | } | ||||||
|  |  | ||||||
|  | Code dump_to_scratch_and_retireve( Code code ) | ||||||
|  | { | ||||||
|  | 	Builder ecode_file_temp = Builder::open("gen/scratch.hpp"); | ||||||
|  | 	ecode_file_temp.print(code); | ||||||
|  | 	ecode_file_temp.write(); | ||||||
|  | 	format_file("gen/scratch.hpp"); | ||||||
|  | 	Code result = scan_file( "gen/scratch.hpp" ); | ||||||
|  | 	remove("gen/scratch.hpp"); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
| int gen_main() | int gen_main() | ||||||
| { | { | ||||||
| 	gen::init(); | 	gen::init(); | ||||||
| @@ -29,7 +68,7 @@ int gen_main() | |||||||
|  |  | ||||||
| 	// gen_dep.hpp | 	// gen_dep.hpp | ||||||
| 	{ | 	{ | ||||||
| 		Code header_start = scan_file( "dependencies/header_start.hpp" ); | 		Code platform     = scan_file( "dependencies/platform.hpp" ); | ||||||
| 		Code macros 	  = scan_file( "dependencies/macros.hpp" ); | 		Code macros 	  = scan_file( "dependencies/macros.hpp" ); | ||||||
| 		Code basic_types  = scan_file( "dependencies/basic_types.hpp" ); | 		Code basic_types  = scan_file( "dependencies/basic_types.hpp" ); | ||||||
| 		Code debug        = scan_file( "dependencies/debug.hpp" ); | 		Code debug        = scan_file( "dependencies/debug.hpp" ); | ||||||
| @@ -45,8 +84,8 @@ int gen_main() | |||||||
| 		Builder | 		Builder | ||||||
| 		header = Builder::open("gen/gen.dep.hpp"); | 		header = Builder::open("gen/gen.dep.hpp"); | ||||||
| 		header.print_fmt( generation_notice ); | 		header.print_fmt( generation_notice ); | ||||||
| 		header.print_fmt( "// This file is intended to be included within gen.hpp (There is no pragma diagnostic ignores)\n\n" ); | 		header.print_fmt( "// This file is intended to be included within gen.hpp (There is no pragma diagnostic ignores)\n" ); | ||||||
| 		header.print( header_start ); | 		header.print( platform ); | ||||||
| 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
| 		header.print( macros ); | 		header.print( macros ); | ||||||
| @@ -80,7 +119,7 @@ int gen_main() | |||||||
| 		Builder | 		Builder | ||||||
| 		src = Builder::open( "gen/gen.dep.cpp" ); | 		src = Builder::open( "gen/gen.dep.cpp" ); | ||||||
| 		src.print_fmt( generation_notice ); | 		src.print_fmt( generation_notice ); | ||||||
| 		src.print_fmt( "// This file is intended to be included within gen.cpp (There is no pragma diagnostic ignores)\n\n" ); | 		src.print_fmt( "// This file is intended to be included within gen.cpp (There is no pragma diagnostic ignores)\n" ); | ||||||
| 		src.print( src_start ); | 		src.print( src_start ); | ||||||
| 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
|  |  | ||||||
| @@ -132,9 +171,13 @@ int gen_main() | |||||||
|  |  | ||||||
| 		header.print_fmt( "#pragma region Types\n" ); | 		header.print_fmt( "#pragma region Types\n" ); | ||||||
| 		header.print( types ); | 		header.print( types ); | ||||||
| 		header.print( ecode ); | 		header.print( fmt_newline); | ||||||
| 		header.print( eoperator ); | 		header.print( dump_to_scratch_and_retireve(ecode) ); | ||||||
| 		header.print( especifier ); | 		header.print( fmt_newline); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(eoperator) ); | ||||||
|  | 		header.print( fmt_newline); | ||||||
|  | 		header.print( dump_to_scratch_and_retireve(especifier) ); | ||||||
|  | 		header.print( fmt_newline); | ||||||
| 		header.print_fmt( "#pragma endregion Types\n\n" ); | 		header.print_fmt( "#pragma endregion Types\n\n" ); | ||||||
|  |  | ||||||
| 		header.print_fmt( "#pragma region AST\n" ); | 		header.print_fmt( "#pragma region AST\n" ); | ||||||
| @@ -148,7 +191,8 @@ int gen_main() | |||||||
| 		header.print_fmt( "\n#pragma region Inlines\n" ); | 		header.print_fmt( "\n#pragma region Inlines\n" ); | ||||||
| 		header.print( inlines ); | 		header.print( inlines ); | ||||||
| 		header.print( fmt_newline ); | 		header.print( fmt_newline ); | ||||||
| 		header.print( ast_inlines ); | 		header.print( dump_to_scratch_and_retireve(ast_inlines) ); | ||||||
|  | 		header.print( fmt_newline ); | ||||||
| 		header.print_fmt( "#pragma endregion Inlines\n" ); | 		header.print_fmt( "#pragma endregion Inlines\n" ); | ||||||
|  |  | ||||||
| 		header.print( header_end ); | 		header.print( header_end ); | ||||||
| @@ -203,7 +247,7 @@ int gen_main() | |||||||
| 		src.print_fmt( generation_notice ); | 		src.print_fmt( generation_notice ); | ||||||
| 		src.print( push_ignores ); | 		src.print( push_ignores ); | ||||||
| 		src.print( src_start ); | 		src.print( src_start ); | ||||||
| 		src.print_fmt( "GEN_NS_BEGIN\n"); | 		src.print_fmt( "\nGEN_NS_BEGIN\n"); | ||||||
|  |  | ||||||
| 		src.print( static_data ); | 		src.print( static_data ); | ||||||
|  |  | ||||||
| @@ -217,7 +261,7 @@ int gen_main() | |||||||
| 		src.print( interface ); | 		src.print( interface ); | ||||||
| 		src.print( upfront ); | 		src.print( upfront ); | ||||||
| 		src.print_fmt( "\n#pragma region Parsing\n\n" ); | 		src.print_fmt( "\n#pragma region Parsing\n\n" ); | ||||||
| 		src.print( nspaced_etoktype ); | 		src.print( dump_to_scratch_and_retireve(nspaced_etoktype) ); | ||||||
| 		src.print( lexer ); | 		src.print( lexer ); | ||||||
| 		src.print( parser ); | 		src.print( parser ); | ||||||
| 		src.print( parsing_interface ); | 		src.print( parsing_interface ); | ||||||
| @@ -278,7 +322,7 @@ int gen_main() | |||||||
| 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | 		header.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
| 		header.print( parsing ); | 		header.print( parsing ); | ||||||
| 		header.print( scanner ); | 		header.print( scanner ); | ||||||
| 		header.print_fmt( "GEN_NS_END\n" ); | 		header.print_fmt( "\nGEN_NS_END\n" ); | ||||||
| 		header.write(); | 		header.write(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -293,7 +337,7 @@ int gen_main() | |||||||
| 		src.print( def_include( txt("gen.scanner.hpp") ) ); | 		src.print( def_include( txt("gen.scanner.hpp") ) ); | ||||||
| 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | 		src.print_fmt( "\nGEN_NS_BEGIN\n" ); | ||||||
| 		src.print( parsing ); | 		src.print( parsing ); | ||||||
| 		src.print( scanner ); | 		// src.print( scanner ); | ||||||
| 		src.print_fmt( "GEN_NS_END\n" ); | 		src.print_fmt( "GEN_NS_END\n" ); | ||||||
| 		src.write(); | 		src.write(); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -9,16 +9,16 @@ Code Code::Invalid; | |||||||
| // This serializes all the data-members in a "debug" format, where each member is printed with its associated value. | // This serializes all the data-members in a "debug" format, where each member is printed with its associated value. | ||||||
| char const* AST::debug_str() | char const* AST::debug_str() | ||||||
| { | { | ||||||
| 	String result = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String result = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	if ( Parent ) | 	if ( Parent ) | ||||||
| 		result.append_fmt( "\n\tParent       : %S %S", Parent->type_str(), Name ? Name : "" ); | 		append_fmt( result, "\n\tParent       : %S %S", Parent->type_str(), Name ? Name : "" ); | ||||||
| 	else | 	else | ||||||
| 		result.append_fmt( "\n\tParent       : %S", "Null" ); | 		append_fmt( result, "\n\tParent       : %S", "Null" ); | ||||||
|  |  | ||||||
| 	result.append_fmt( "\n\tName         : %S", Name ? Name : "Null" ); | 	append_fmt( result, "\n\tName         : %S", Name ? Name : "Null" ); | ||||||
| 	result.append_fmt( "\n\tType         : %S", type_str() ); | 	append_fmt( result, "\n\tType         : %S", type_str() ); | ||||||
| 	result.append_fmt( "\n\tModule Flags : %S", to_str( ModuleFlags ) ); | 	append_fmt( result, "\n\tModule Flags : %S", to_str( ModuleFlags ) ); | ||||||
|  |  | ||||||
| 	switch ( Type ) | 	switch ( Type ) | ||||||
| 	{ | 	{ | ||||||
| @@ -30,9 +30,9 @@ char const* AST::debug_str() | |||||||
| 		case Access_Protected: | 		case Access_Protected: | ||||||
| 		case Access_Public: | 		case Access_Public: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Untyped: | 		case Untyped: | ||||||
| @@ -48,74 +48,74 @@ char const* AST::debug_str() | |||||||
| 		case Preprocess_IfDef: | 		case Preprocess_IfDef: | ||||||
| 		case Preprocess_IfNotDef: | 		case Preprocess_IfNotDef: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tContent: %S", Content ); | 			append_fmt( result, "\n\tContent: %S", Content ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Class: | 		case Class: | ||||||
| 		case Struct: | 		case Struct: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmd   : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmd   : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes  : %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes  : %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess )  : "No Parent" ); | 			append_fmt( result, "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess )  : "No Parent" ); | ||||||
| 			result.append_fmt( "\n\tParentType  : %s", ParentType ? ParentType->type_str()  : "Null" ); | 			append_fmt( result, "\n\tParentType  : %s", ParentType ? ParentType->type_str()  : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody        : %S", Body       ? Body->debug_str()       : "Null" ); | 			append_fmt( result, "\n\tBody        : %S", Body       ? Body->debug_str()       : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Class_Fwd: | 		case Class_Fwd: | ||||||
| 		case Struct_Fwd: | 		case Struct_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmd   : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmd   : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes  : %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes  : %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess )  : "No Parent" ); | 			append_fmt( result, "\n\tParentAccess: %s", ParentType ? to_str( ParentAccess )  : "No Parent" ); | ||||||
| 			result.append_fmt( "\n\tParentType  : %s", ParentType ? ParentType->type_str()  : "Null" ); | 			append_fmt( result, "\n\tParentType  : %s", ParentType ? ParentType->type_str()  : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Constructor: | 		case Constructor: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt      : %S", InlineCmt       ? InlineCmt->Content           : "Null" ); | 			append_fmt( result, "\n\tInlineCmt      : %S", InlineCmt       ? InlineCmt->Content           : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs          : %S", Specs           ? Specs->to_string()           : "Null" ); | 			append_fmt( result, "\n\tSpecs          : %S", Specs           ? Specs->to_string()           : "Null" ); | ||||||
| 			result.append_fmt( "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); | 			append_fmt( result, "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams         : %S", Params          ? Params->to_string()          : "Null" ); | 			append_fmt( result, "\n\tParams         : %S", Params          ? Params->to_string()          : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody           : %S", Body            ? Body->debug_str()            : "Null" ); | 			append_fmt( result, "\n\tBody           : %S", Body            ? Body->debug_str()            : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Constructor_Fwd: | 		case Constructor_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt      : %S", InlineCmt       ? InlineCmt->Content           : "Null" ); | 			append_fmt( result, "\n\tInlineCmt      : %S", InlineCmt       ? InlineCmt->Content           : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs          : %S", Specs           ? Specs->to_string()           : "Null" ); | 			append_fmt( result, "\n\tSpecs          : %S", Specs           ? Specs->to_string()           : "Null" ); | ||||||
| 			result.append_fmt( "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); | 			append_fmt( result, "\n\tInitializerList: %S", InitializerList ? InitializerList->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams         : %S", Params          ? Params->to_string()          : "Null" ); | 			append_fmt( result, "\n\tParams         : %S", Params          ? Params->to_string()          : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Destructor: | 		case Destructor: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt      : %S", InlineCmt ? InlineCmt->Content : "Null" ); | 			append_fmt( result, "\n\tInlineCmt      : %S", InlineCmt ? InlineCmt->Content : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs          : %S", Specs     ? Specs->to_string() : "Null" ); | 			append_fmt( result, "\n\tSpecs          : %S", Specs     ? Specs->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody           : %S", Body      ? Body->debug_str()  : "Null" ); | 			append_fmt( result, "\n\tBody           : %S", Body      ? Body->debug_str()  : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Destructor_Fwd: | 		case Destructor_Fwd: | ||||||
| @@ -124,208 +124,208 @@ char const* AST::debug_str() | |||||||
| 		case Enum: | 		case Enum: | ||||||
| 		case Enum_Class: | 		case Enum_Class: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt       : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | 			append_fmt( result, "\n\tInlineCmt       : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes      : %S", Attributes     ? Attributes->to_string()     : "Null" ); | 			append_fmt( result, "\n\tAttributes      : %S", Attributes     ? Attributes->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | 			append_fmt( result, "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody            : %S", Body           ? Body->debug_str()           : "Null" ); | 			append_fmt( result, "\n\tBody            : %S", Body           ? Body->debug_str()           : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Enum_Fwd: | 		case Enum_Fwd: | ||||||
| 		case Enum_Class_Fwd: | 		case Enum_Class_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt       : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | 			append_fmt( result, "\n\tInlineCmt       : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes      : %S", Attributes     ? Attributes->to_string()     : "Null" ); | 			append_fmt( result, "\n\tAttributes      : %S", Attributes     ? Attributes->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | 			append_fmt( result, "\n\tUnderlying Type : %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Extern_Linkage: | 		case Extern_Linkage: | ||||||
| 		case Namespace: | 		case Namespace: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tBody: %S", Body ? Body->debug_str() : "Null" ); | 			append_fmt( result, "\n\tBody: %S", Body ? Body->debug_str() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Friend: | 		case Friend: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt  : %S", InlineCmt   ? InlineCmt->Content       : "Null" ); | 			append_fmt( result, "\n\tInlineCmt  : %S", InlineCmt   ? InlineCmt->Content       : "Null" ); | ||||||
| 			result.append_fmt( "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); | 			append_fmt( result, "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Function: | 		case Function: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | 			append_fmt( result, "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | 			append_fmt( result, "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | 			append_fmt( result, "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Function_Fwd: | 		case Function_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | 			append_fmt( result, "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | 			append_fmt( result, "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Module: | 		case Module: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Operator: | 		case Operator: | ||||||
| 		case Operator_Member: | 		case Operator_Member: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | 			append_fmt( result, "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | 			append_fmt( result, "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | 			append_fmt( result, "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | ||||||
| 			result.append_fmt( "\n\tOp        : %S", to_str( Op ) ); | 			append_fmt( result, "\n\tOp        : %S", to_str( Op ) ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Operator_Fwd: | 		case Operator_Fwd: | ||||||
| 		case Operator_Member_Fwd: | 		case Operator_Member_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | 			append_fmt( result, "\n\tReturnType: %S", ReturnType ? ReturnType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | 			append_fmt( result, "\n\tParams    : %S", Params     ? Params->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tOp        : %S", to_str( Op ) ); | 			append_fmt( result, "\n\tOp        : %S", to_str( Op ) ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Operator_Cast: | 		case Operator_Cast: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content     : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()     : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tValueType : %S", ValueType  ? ValueType->to_string() : "Null" ); | 			append_fmt( result, "\n\tValueType : %S", ValueType  ? ValueType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody      : %S", Body       ? Body->debug_str()      : "Null" ); | 			append_fmt( result, "\n\tBody      : %S", Body       ? Body->debug_str()      : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Operator_Cast_Fwd: | 		case Operator_Cast_Fwd: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content     : "Null" ); | 			append_fmt( result, "\n\tInlineCmt : %S", InlineCmt  ? InlineCmt->Content     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs     : %S", Specs      ? Specs->to_string()     : "Null" ); | 			append_fmt( result, "\n\tSpecs     : %S", Specs      ? Specs->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tValueType : %S", ValueType  ? ValueType->to_string() : "Null" ); | 			append_fmt( result, "\n\tValueType : %S", ValueType  ? ValueType->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Parameters: | 		case Parameters: | ||||||
| 			result.append_fmt( "\n\tNumEntries: %d", NumEntries ); | 			append_fmt( result, "\n\tNumEntries: %d", NumEntries ); | ||||||
| 			result.append_fmt( "\n\tLast      : %S", Last->Name ); | 			append_fmt( result, "\n\tLast      : %S", Last->Name ); | ||||||
| 			result.append_fmt( "\n\tNext      : %S", Next->Name ); | 			append_fmt( result, "\n\tNext      : %S", Next->Name ); | ||||||
| 			result.append_fmt( "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); | 			append_fmt( result, "\n\tValueType : %S", ValueType ? ValueType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tValue     : %S", Value     ? Value->to_string()     : "Null" ); | 			append_fmt( result, "\n\tValue     : %S", Value     ? Value->to_string()     : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Specifiers: | 		case Specifiers: | ||||||
| 		{ | 		{ | ||||||
| 			result.append_fmt( "\n\tNumEntries: %d", NumEntries ); | 			append_fmt( result, "\n\tNumEntries: %d", NumEntries ); | ||||||
| 			result.append( "\n\tArrSpecs: " ); | 			GEN_NS append( result, "\n\tArrSpecs: " ); | ||||||
|  |  | ||||||
| 			s32 idx  = 0; | 			s32 idx  = 0; | ||||||
| 			s32 left = NumEntries; | 			s32 left = NumEntries; | ||||||
| 			while ( left-- ) | 			while ( left-- ) | ||||||
| 			{ | 			{ | ||||||
| 				StrC spec = ESpecifier::to_str( ArrSpecs[idx] ); | 				StrC spec = ESpecifier::to_str( ArrSpecs[idx] ); | ||||||
| 				result.append_fmt( "%.*s, ", spec.Len, spec.Ptr ); | 				append_fmt( result, "%.*s, ", spec.Len, spec.Ptr ); | ||||||
| 				idx++; | 				idx++; | ||||||
| 			} | 			} | ||||||
| 			result.append_fmt( "\n\tNextSpecs: %S", NextSpecs ? NextSpecs->debug_str() : "Null" ); | 			append_fmt( result, "\n\tNextSpecs: %S", NextSpecs ? NextSpecs->debug_str() : "Null" ); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Template: | 		case Template: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tParams     : %S", Params      ? Params->to_string()      : "Null" ); | 			append_fmt( result, "\n\tParams     : %S", Params      ? Params->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); | 			append_fmt( result, "\n\tDeclaration: %S", Declaration ? Declaration->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Typedef: | 		case Typedef: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt     : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | 			append_fmt( result, "\n\tInlineCmt     : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | ||||||
| 			result.append_fmt( "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | 			append_fmt( result, "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Typename: | 		case Typename: | ||||||
| 			result.append_fmt( "\n\tAttributes     : %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes     : %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs          : %S", Specs      ? Specs->to_string()      : "Null" ); | 			append_fmt( result, "\n\tSpecs          : %S", Specs      ? Specs->to_string()      : "Null" ); | ||||||
| 			result.append_fmt( "\n\tReturnType     : %S", ReturnType ? ReturnType->to_string() : "Null" ); | 			append_fmt( result, "\n\tReturnType     : %S", ReturnType ? ReturnType->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tParams         : %S", Params     ? Params->to_string()     : "Null" ); | 			append_fmt( result, "\n\tParams         : %S", Params     ? Params->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tArrExpr        : %S", ArrExpr    ? ArrExpr->to_string()    : "Null" ); | 			append_fmt( result, "\n\tArrExpr        : %S", ArrExpr    ? ArrExpr->to_string()    : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Union: | 		case Union: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | 			append_fmt( result, "\n\tAttributes: %S", Attributes ? Attributes->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | 			append_fmt( result, "\n\tBody      : %S", Body       ? Body->debug_str()       : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Using: | 		case Using: | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt     : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | 			append_fmt( result, "\n\tInlineCmt     : %S", InlineCmt      ? InlineCmt->Content          : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes    : %S", Attributes     ? Attributes->to_string()     : "Null" ); | 			append_fmt( result, "\n\tAttributes    : %S", Attributes     ? Attributes->to_string()     : "Null" ); | ||||||
| 			result.append_fmt( "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | 			append_fmt( result, "\n\tUnderlyingType: %S", UnderlyingType ? UnderlyingType->to_string() : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Variable: | 		case Variable: | ||||||
| @@ -333,25 +333,25 @@ char const* AST::debug_str() | |||||||
| 			if ( Parent && Parent->Type == Variable ) | 			if ( Parent && Parent->Type == Variable ) | ||||||
| 			{ | 			{ | ||||||
| 				// Its a NextVar | 				// Its a NextVar | ||||||
| 				result.append_fmt( "\n\tSpecs       : %S", Specs        ? Specs->to_string()        : "Null" ); | 				append_fmt( result, "\n\tSpecs       : %S", Specs        ? Specs->to_string()        : "Null" ); | ||||||
| 				result.append_fmt( "\n\tValue       : %S", Value        ? Value->to_string()        : "Null" ); | 				append_fmt( result, "\n\tValue       : %S", Value        ? Value->to_string()        : "Null" ); | ||||||
| 				result.append_fmt( "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); | 				append_fmt( result, "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); | ||||||
| 				result.append_fmt( "\n\tNextVar     : %S", NextVar      ? NextVar->debug_str()      : "Null" ); | 				append_fmt( result, "\n\tNextVar     : %S", NextVar      ? NextVar->debug_str()      : "Null" ); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if ( Prev ) | 			if ( Prev ) | ||||||
| 				result.append_fmt( "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tPrev: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
| 			if ( Next ) | 			if ( Next ) | ||||||
| 				result.append_fmt( "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | 				append_fmt( result, "\n\tNext: %S %S", Prev->type_str(), Prev->Name ? Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			result.append_fmt( "\n\tInlineCmt   : %S", InlineCmt    ? InlineCmt->Content        : "Null" ); | 			append_fmt( result, "\n\tInlineCmt   : %S", InlineCmt    ? InlineCmt->Content        : "Null" ); | ||||||
| 			result.append_fmt( "\n\tAttributes  : %S", Attributes   ? Attributes->to_string()   : "Null" ); | 			append_fmt( result, "\n\tAttributes  : %S", Attributes   ? Attributes->to_string()   : "Null" ); | ||||||
| 			result.append_fmt( "\n\tSpecs       : %S", Specs        ? Specs->to_string()        : "Null" ); | 			append_fmt( result, "\n\tSpecs       : %S", Specs        ? Specs->to_string()        : "Null" ); | ||||||
| 			result.append_fmt( "\n\tValueType   : %S", ValueType    ? ValueType->to_string()    : "Null" ); | 			append_fmt( result, "\n\tValueType   : %S", ValueType    ? ValueType->to_string()    : "Null" ); | ||||||
| 			result.append_fmt( "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); | 			append_fmt( result, "\n\tBitfieldSize: %S", BitfieldSize ? BitfieldSize->to_string() : "Null" ); | ||||||
| 			result.append_fmt( "\n\tValue       : %S", Value        ? Value->to_string()        : "Null" ); | 			append_fmt( result, "\n\tValue       : %S", Value        ? Value->to_string()        : "Null" ); | ||||||
| 			result.append_fmt( "\n\tNextVar     : %S", NextVar      ? NextVar->debug_str()      : "Null" ); | 			append_fmt( result, "\n\tNextVar     : %S", NextVar      ? NextVar->debug_str()      : "Null" ); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -372,7 +372,7 @@ AST* AST::duplicate() | |||||||
|  |  | ||||||
| String AST::to_string() | String AST::to_string() | ||||||
| { | { | ||||||
| 	String result = String::make( GlobalAllocator, "" ); | 	String result = string_make( GlobalAllocator, "" ); | ||||||
| 	to_string( result ); | 	to_string( result ); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -390,25 +390,25 @@ void AST::to_string( String& result ) | |||||||
| 		#ifdef GEN_DONT_ALLOW_INVALID_CODE | 		#ifdef GEN_DONT_ALLOW_INVALID_CODE | ||||||
| 			log_failure("Attempted to serialize invalid code! - %S", Parent ? Parent->debug_str() : Name ); | 			log_failure("Attempted to serialize invalid code! - %S", Parent ? Parent->debug_str() : Name ); | ||||||
| 		#else | 		#else | ||||||
| 			result.append_fmt( "Invalid Code!" ); | 			append_fmt( result, "Invalid Code!" ); | ||||||
| 		#endif | 		#endif | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case NewLine: | 		case NewLine: | ||||||
| 			result.append("\n"); | 			GEN_NS append( result,"\n"); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Untyped: | 		case Untyped: | ||||||
| 		case Execution: | 		case Execution: | ||||||
| 		case Comment: | 		case Comment: | ||||||
| 		case PlatformAttributes: | 		case PlatformAttributes: | ||||||
| 			result.append( Content ); | 			GEN_NS append( result, Content ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Access_Private: | 		case Access_Private: | ||||||
| 		case Access_Protected: | 		case Access_Protected: | ||||||
| 		case Access_Public: | 		case Access_Public: | ||||||
| 			result.append( Name ); | 			GEN_NS append( result, Name ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case Class: | 		case Class: | ||||||
| @@ -659,8 +659,8 @@ bool AST::is_equal( AST* other ) | |||||||
| 			"so it must be verified by eye for now\n"                     \ | 			"so it must be verified by eye for now\n"                     \ | ||||||
| 			"AST   Content:\n%S\n"                                        \ | 			"AST   Content:\n%S\n"                                        \ | ||||||
| 			"Other Content:\n%S\n"                                        \ | 			"Other Content:\n%S\n"                                        \ | ||||||
| 			, content.visualize_whitespace()                              \ | 			, visualize_whitespace(content)                               \ | ||||||
| 			, other->content.visualize_whitespace()                       \ | 			, visualize_whitespace(other->content)                        \ | ||||||
| 		);                                                                \ | 		);                                                                \ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -165,6 +165,7 @@ struct Code | |||||||
| 	char const* debug_str();               \ | 	char const* debug_str();               \ | ||||||
| 	Code        duplicate();			   \ | 	Code        duplicate();			   \ | ||||||
| 	bool        is_equal( Code other );    \ | 	bool        is_equal( Code other );    \ | ||||||
|  | 	bool        is_body();                 \ | ||||||
| 	bool        is_valid();                \ | 	bool        is_valid();                \ | ||||||
| 	void        set_global();              \ | 	void        set_global();              \ | ||||||
| 	String      to_string();               \ | 	String      to_string();               \ | ||||||
| @@ -259,6 +260,7 @@ struct AST | |||||||
| 	Code&       entry      ( u32 idx ); | 	Code&       entry      ( u32 idx ); | ||||||
| 	bool        has_entries(); | 	bool        has_entries(); | ||||||
| 	bool        is_equal   ( AST* other ); | 	bool        is_equal   ( AST* other ); | ||||||
|  | 	bool        is_body(); | ||||||
| 	char const* type_str(); | 	char const* type_str(); | ||||||
| 	bool        validate_body(); | 	bool        validate_body(); | ||||||
|  |  | ||||||
| @@ -339,13 +341,14 @@ struct AST | |||||||
| 			}; | 			}; | ||||||
| 			union { | 			union { | ||||||
| 				AST*  ArrExpr;          // Typename | 				AST*  ArrExpr;          // Typename | ||||||
| 				AST*  Body;             // Class, Constructr, Destructor, Enum, Friend, Function, Namespace, Struct, Union | 				AST*  Body;             // Class, Constructor, Destructor, Enum, Friend, Function, Namespace, Struct, Union | ||||||
| 				AST*  Declaration;      // Friend, Template | 				AST*  Declaration;      // Friend, Template | ||||||
| 				AST*  Value;            // Parameter, Variable | 				AST*  Value;            // Parameter, Variable | ||||||
| 			}; | 			}; | ||||||
| 			union { | 			union { | ||||||
| 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | ||||||
| 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | ||||||
|  | 				AST*  PostNameMacro;     // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 		StringCached  Content;          // Attributes, Comment, Execution, Include | 		StringCached  Content;          // Attributes, Comment, Execution, Include | ||||||
| @@ -375,6 +378,8 @@ struct AST | |||||||
| 		OperatorT     Op; | 		OperatorT     Op; | ||||||
| 		AccessSpec    ParentAccess; | 		AccessSpec    ParentAccess; | ||||||
| 		s32           NumEntries; | 		s32           NumEntries; | ||||||
|  | 		s32           VarConstructorInit;  // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. | ||||||
|  | 		b32           EnumUnderlyingMacro; // Used by enums incase the user wants to wrap underlying type specification in a macro | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -407,6 +412,7 @@ struct AST_POD | |||||||
| 			union { | 			union { | ||||||
| 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | 				AST*  NextVar;          // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) | ||||||
| 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | 				AST*  SuffixSpecs;      // Only used with typenames, to store the function suffix if typename is function signature. ( May not be needed ) | ||||||
|  | 				AST*  PostNameMacro;    // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 		StringCached  Content;          // Attributes, Comment, Execution, Include | 		StringCached  Content;          // Attributes, Comment, Execution, Include | ||||||
| @@ -436,6 +442,7 @@ struct AST_POD | |||||||
| 		OperatorT     Op; | 		OperatorT     Op; | ||||||
| 		AccessSpec    ParentAccess; | 		AccessSpec    ParentAccess; | ||||||
| 		s32           NumEntries; | 		s32           NumEntries; | ||||||
|  | 		s32           VarConstructorInit; // Used by variables to know that initialization is using a constructor expression instead of an assignment expression. | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -174,7 +174,7 @@ struct AST_Enum | |||||||
| 			CodeAttributes Attributes; | 			CodeAttributes Attributes; | ||||||
| 			char           _PAD_SPEC_  [ sizeof(AST*) ]; | 			char           _PAD_SPEC_  [ sizeof(AST*) ]; | ||||||
| 			CodeType       UnderlyingType; | 			CodeType       UnderlyingType; | ||||||
| 			char	       _PAD_PARAMS_[ sizeof(AST*) ]; | 			Code           UnderlyingTypeMacro; | ||||||
| 			CodeBody       Body; | 			CodeBody       Body; | ||||||
| 			char 	       _PAD_PROPERTIES_2_[ sizeof(AST*) ]; | 			char 	       _PAD_PROPERTIES_2_[ sizeof(AST*) ]; | ||||||
| 		}; | 		}; | ||||||
| @@ -186,7 +186,7 @@ struct AST_Enum | |||||||
| 	StringCached           Name; | 	StringCached           Name; | ||||||
| 	CodeT                  Type; | 	CodeT                  Type; | ||||||
| 	ModuleFlag             ModuleFlags; | 	ModuleFlag             ModuleFlags; | ||||||
| 	char 			       _PAD_UNUSED_[ sizeof(u32) ]; | 	b32                    EnumUnderlyingMacro; | ||||||
| }; | }; | ||||||
| static_assert( sizeof(AST_Enum) == sizeof(AST), "ERROR: AST_Enum is not the same size as AST"); | static_assert( sizeof(AST_Enum) == sizeof(AST), "ERROR: AST_Enum is not the same size as AST"); | ||||||
|  |  | ||||||
| @@ -211,7 +211,7 @@ struct AST_Expr | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -226,7 +226,7 @@ struct AST_Expr_Assign | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -241,7 +241,7 @@ struct AST_Expr_Alignof | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -256,7 +256,7 @@ struct AST_Expr_Binary | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -271,7 +271,7 @@ struct AST_Expr_CStyleCast | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -286,7 +286,7 @@ struct AST_Expr_FunctionalCast | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -301,7 +301,7 @@ struct AST_Expr_CppCast | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -316,7 +316,7 @@ struct AST_Expr_ProcCall | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -331,7 +331,7 @@ struct AST_Expr_Decltype | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -346,7 +346,7 @@ struct AST_Expr_Comma | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -361,7 +361,7 @@ struct AST_Expr_AMS | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -376,7 +376,7 @@ struct AST_Expr_Sizeof | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -391,7 +391,7 @@ struct AST_Expr_Subscript | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -406,7 +406,7 @@ struct AST_Expr_Ternary | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -421,7 +421,7 @@ struct AST_Expr_UnaryPrefix | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -436,7 +436,7 @@ struct AST_Expr_UnaryPostfix | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -451,7 +451,7 @@ struct AST_Expr_Element | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -644,7 +644,8 @@ struct AST_Param | |||||||
| 			CodeType  ValueType; | 			CodeType  ValueType; | ||||||
| 			Code      Macro; | 			Code      Macro; | ||||||
| 			Code      Value; | 			Code      Value; | ||||||
| 			char 	  _PAD_PROPERTIES_3_[ sizeof(AST*) ]; | 			Code     PostNameMacro; // Thanks Unreal | ||||||
|  | 			// char     _PAD_PROPERTIES_3_[sizeof( AST* )]; | ||||||
| 		}; | 		}; | ||||||
| 	}; | 	}; | ||||||
| 	CodeParam         Last; | 	CodeParam         Last; | ||||||
| @@ -710,7 +711,7 @@ struct AST_Stmt | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -725,7 +726,7 @@ struct AST_Stmt_Break | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -740,7 +741,7 @@ struct AST_Stmt_Case | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -755,7 +756,7 @@ struct AST_Stmt_Continue | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -770,7 +771,7 @@ struct AST_Stmt_Decl | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -785,7 +786,7 @@ struct AST_Stmt_Do | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -800,7 +801,7 @@ struct AST_Stmt_Expr | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -815,7 +816,7 @@ struct AST_Stmt_Else | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -830,7 +831,7 @@ struct AST_Stmt_If | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -845,7 +846,7 @@ struct AST_Stmt_For | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -860,7 +861,7 @@ struct AST_Stmt_Goto | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -875,7 +876,7 @@ struct AST_Stmt_Label | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -890,7 +891,7 @@ struct AST_Stmt_Switch | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -905,7 +906,7 @@ struct AST_Stmt_While | |||||||
| { | { | ||||||
| 	union { | 	union { | ||||||
| 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | 		char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap + sizeof(AST*) ]; | ||||||
| 	} | 	}; | ||||||
| 	CodeExpr       Prev; | 	CodeExpr       Prev; | ||||||
| 	CodeExpr       Next; | 	CodeExpr       Next; | ||||||
| 	parser::Token* Tok; | 	parser::Token* Tok; | ||||||
| @@ -1115,7 +1116,7 @@ struct AST_Var | |||||||
| 	StringCached           Name; | 	StringCached           Name; | ||||||
| 	CodeT                  Type; | 	CodeT                  Type; | ||||||
| 	ModuleFlag             ModuleFlags; | 	ModuleFlag             ModuleFlags; | ||||||
| 	char 			       _PAD_UNUSED_[ sizeof(u32) ]; | 	s32                    VarConstructorInit; | ||||||
| }; | }; | ||||||
| static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST"); | static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST"); | ||||||
|  |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -11,6 +11,10 @@ struct CodeBody | |||||||
|  |  | ||||||
| 	void append( Code other ) | 	void append( Code other ) | ||||||
| 	{ | 	{ | ||||||
|  | 		if (other.is_body()) | ||||||
|  | 		{ | ||||||
|  | 			append( other.cast<CodeBody>() ); | ||||||
|  | 		} | ||||||
| 		raw()->append( other.ast ); | 		raw()->append( other.ast ); | ||||||
| 	} | 	} | ||||||
| 	void append( CodeBody body ) | 	void append( CodeBody body ) | ||||||
| @@ -165,6 +169,46 @@ struct CodeSpecifiers | |||||||
|  |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  | 	s32 remove( SpecifierT to_remove ) | ||||||
|  | 	{ | ||||||
|  | 		if ( ast == nullptr ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( raw()->NumEntries == AST::ArrSpecs_Cap ) | ||||||
|  | 		{ | ||||||
|  | 			log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST::ArrSpecs_Cap ); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		s32 result = -1; | ||||||
|  |  | ||||||
|  | 		s32 curr = 0; | ||||||
|  | 		s32 next = 0; | ||||||
|  | 		for(; next < raw()->NumEntries; ++ curr, ++ next) | ||||||
|  | 		{ | ||||||
|  | 			SpecifierT spec = raw()->ArrSpecs[next]; | ||||||
|  | 			if (spec == to_remove) | ||||||
|  | 			{ | ||||||
|  | 				result = next; | ||||||
|  |  | ||||||
|  | 				next ++; | ||||||
|  | 				if (next >= raw()->NumEntries) | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				spec = raw()->ArrSpecs[next]; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			raw()->ArrSpecs[ curr ] = spec; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (result > -1) { | ||||||
|  | 			raw()->NumEntries --; | ||||||
|  | 		} | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
| 	void to_string( String& result ); | 	void to_string( String& result ); | ||||||
| 	AST* raw() | 	AST* raw() | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -72,7 +72,7 @@ namespace ECode | |||||||
| 		NumTypes | 		NumTypes | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	StrC to_str( Type type ) | 	inline StrC to_str( Type type ) | ||||||
| 	{ | 	{ | ||||||
| 		local_persist StrC lookup[] { | 		local_persist StrC lookup[] { | ||||||
| 			{ sizeof( "Invalid" ),             "Invalid"             }, | 			{ sizeof( "Invalid" ),             "Invalid"             }, | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ namespace EOperator | |||||||
| 		NumOps | 		NumOps | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	StrC to_str( Type op ) | 	inline StrC to_str( Type op ) | ||||||
| 	{ | 	{ | ||||||
| 		local_persist StrC lookup[] { | 		local_persist StrC lookup[] { | ||||||
| 			{ sizeof( "INVALID" ),  "INVALID"  }, | 			{ sizeof( "INVALID" ),  "INVALID"  }, | ||||||
|   | |||||||
| @@ -38,12 +38,12 @@ namespace ESpecifier | |||||||
| 		NumSpecifiers | 		NumSpecifiers | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	bool is_trailing( Type specifier ) | 	inline bool is_trailing( Type specifier ) | ||||||
| 	{ | 	{ | ||||||
| 		return specifier > Virtual; | 		return specifier > Virtual; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	StrC to_str( Type type ) | 	inline StrC to_str( Type type ) | ||||||
| 	{ | 	{ | ||||||
| 		local_persist StrC lookup[] { | 		local_persist StrC lookup[] { | ||||||
| 			{ sizeof( "INVALID" ),       "INVALID"       }, | 			{ sizeof( "INVALID" ),       "INVALID"       }, | ||||||
| @@ -76,7 +76,7 @@ namespace ESpecifier | |||||||
| 		return lookup[type]; | 		return lookup[type]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Type to_type( StrC str ) | 	inline Type to_type( StrC str ) | ||||||
| 	{ | 	{ | ||||||
| 		local_persist u32 keymap[NumSpecifiers]; | 		local_persist u32 keymap[NumSpecifiers]; | ||||||
| 		do_once_start for ( u32 index = 0; index < NumSpecifiers; index++ ) | 		do_once_start for ( u32 index = 0; index < NumSpecifiers; index++ ) | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ namespace parser | |||||||
| 			NumTokens | 			NumTokens | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		StrC to_str( Type type ) | 		inline StrC to_str( Type type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist StrC lookup[] { | 			local_persist StrC lookup[] { | ||||||
| 				{ sizeof( "__invalid__" ),         "__invalid__"         }, | 				{ sizeof( "__invalid__" ),         "__invalid__"         }, | ||||||
| @@ -217,7 +217,7 @@ namespace parser | |||||||
| 			return lookup[type]; | 			return lookup[type]; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		Type to_type( StrC str ) | 		inline Type to_type( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist u32 keymap[NumTokens]; | 			local_persist u32 keymap[NumTokens]; | ||||||
| 			do_once_start for ( u32 index = 0; index < NumTokens; index++ ) | 			do_once_start for ( u32 index = 0; index < NumTokens; index++ ) | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ constexpr s32 InitSize_DataArrays = 16; | |||||||
|  |  | ||||||
| // NOTE: This limits the maximum size of an allocation | // NOTE: This limits the maximum size of an allocation | ||||||
| // If you are generating a string larger than this, increase the size of the bucket here. | // If you are generating a string larger than this, increase the size of the bucket here. | ||||||
| constexpr uw  Global_BucketSize         = GEN_GLOBAL_BUCKET_SIZE; | constexpr usize  Global_BucketSize         = GEN_GLOBAL_BUCKET_SIZE; | ||||||
| constexpr s32 CodePool_NumBlocks        = GEN_CODEPOOL_NUM_BLOCKS; | constexpr s32 CodePool_NumBlocks        = GEN_CODEPOOL_NUM_BLOCKS; | ||||||
| constexpr s32 SizePer_StringArena       = GEN_SIZE_PER_STRING_ARENA; | constexpr s32 SizePer_StringArena       = GEN_SIZE_PER_STRING_ARENA; | ||||||
|  |  | ||||||
| @@ -63,7 +63,6 @@ extern CodeAttributes attrib_api_import; | |||||||
| extern Code module_global_fragment; | extern Code module_global_fragment; | ||||||
| extern Code module_private_fragment; | extern Code module_private_fragment; | ||||||
|  |  | ||||||
| // Exposed, but this is really used for parsing. |  | ||||||
| extern Code fmt_newline; | extern Code fmt_newline; | ||||||
|  |  | ||||||
| extern CodePragma pragma_once; | extern CodePragma pragma_once; | ||||||
| @@ -123,8 +122,8 @@ extern CodeType t_typename; | |||||||
| 	extern CodeType t_u32; | 	extern CodeType t_u32; | ||||||
| 	extern CodeType t_u64; | 	extern CodeType t_u64; | ||||||
|  |  | ||||||
| 	extern CodeType t_sw; | 	extern CodeType t_ssize; | ||||||
| 	extern CodeType t_uw; | 	extern CodeType t_usize; | ||||||
|  |  | ||||||
| 	extern CodeType t_f32; | 	extern CodeType t_f32; | ||||||
| 	extern CodeType t_f64; | 	extern CodeType t_f64; | ||||||
| @@ -134,6 +133,7 @@ extern CodeType t_typename; | |||||||
|  |  | ||||||
| #pragma region Macros | #pragma region Macros | ||||||
|  |  | ||||||
|  | #ifndef token_fmt | ||||||
| #	define gen_main main | #	define gen_main main | ||||||
|  |  | ||||||
| #	define __ NoCode | #	define __ NoCode | ||||||
| @@ -152,6 +152,7 @@ extern CodeType t_typename; | |||||||
|  |  | ||||||
| 	// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string. | 	// Takes a format string (char const*) and a list of tokens (StrC) and returns a StrC of the formatted string. | ||||||
| #	define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) | #	define token_fmt( ... ) GEN_NS token_fmt_impl( (num_args( __VA_ARGS__ ) + 1) / 2, __VA_ARGS__ ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Macros | #pragma endregion Macros | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ | |||||||
| #include "interface.hpp" | #include "interface.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | inline | ||||||
| void AST::append( AST* other ) | void AST::append( AST* other ) | ||||||
| { | { | ||||||
| 	if ( other->Parent ) | 	if ( other->Parent ) | ||||||
| @@ -20,13 +21,14 @@ void AST::append( AST* other ) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	AST* | 	AST* | ||||||
| 		Current       = Back; | 	Current       = Back; | ||||||
| 	Current->Next = other; | 	Current->Next = other; | ||||||
| 	other->Prev   = Current; | 	other->Prev   = Current; | ||||||
| 	Back          = other; | 	Back          = other; | ||||||
| 	NumEntries++; | 	NumEntries++; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| Code& AST::entry( u32 idx ) | Code& AST::entry( u32 idx ) | ||||||
| { | { | ||||||
| 	AST** current = & Front; | 	AST** current = & Front; | ||||||
| @@ -42,21 +44,44 @@ Code& AST::entry( u32 idx ) | |||||||
| 	return * rcast( Code*, current); | 	return * rcast( Code*, current); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| bool AST::has_entries() | bool AST::has_entries() | ||||||
| { | { | ||||||
| 	return NumEntries; | 	return NumEntries > 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool AST::is_body() | ||||||
|  | { | ||||||
|  | 	switch (Type) | ||||||
|  | 	{ | ||||||
|  | 		case ECode::Enum_Body: | ||||||
|  | 		case ECode::Class_Body: | ||||||
|  | 		case ECode::Union_Body: | ||||||
|  | 		case ECode::Export_Body: | ||||||
|  | 		case ECode::Global_Body: | ||||||
|  | 		case ECode::Struct_Body: | ||||||
|  | 		case ECode::Function_Body: | ||||||
|  | 		case ECode::Namespace_Body: | ||||||
|  | 		case ECode::Extern_Linkage_Body: | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| char const* AST::type_str() | char const* AST::type_str() | ||||||
| { | { | ||||||
| 	return ECode::to_str( Type ); | 	return ECode::to_str( Type ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| AST::operator Code() | AST::operator Code() | ||||||
| { | { | ||||||
| 	return { this }; | 	return { this }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| Code& Code::operator ++() | Code& Code::operator ++() | ||||||
| { | { | ||||||
| 	if ( ast ) | 	if ( ast ) | ||||||
| @@ -65,13 +90,14 @@ Code& Code::operator ++() | |||||||
| 	return *this; | 	return *this; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| void CodeClass::add_interface( CodeType type ) | void CodeClass::add_interface( CodeType type ) | ||||||
| { | { | ||||||
| 	CodeType possible_slot = ast->ParentType; | 	CodeType possible_slot = ast->ParentType; | ||||||
| 	if ( possible_slot.ast ) | 	if ( possible_slot.ast ) | ||||||
| 	{ | 	{ | ||||||
| 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | ||||||
| 		ast->ParentAccess = AccessSpec::Public; | 		ast->ParentAccess = AccessSpec_Public; | ||||||
| 		// If your planning on adding a proper parent, | 		// If your planning on adding a proper parent, | ||||||
| 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | ||||||
| 	} | 	} | ||||||
| @@ -84,6 +110,7 @@ void CodeClass::add_interface( CodeType type ) | |||||||
| 	possible_slot.ast = type.ast; | 	possible_slot.ast = type.ast; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| void CodeParam::append( CodeParam other ) | void CodeParam::append( CodeParam other ) | ||||||
| { | { | ||||||
| 	AST* self  = (AST*) ast; | 	AST* self  = (AST*) ast; | ||||||
| @@ -107,6 +134,7 @@ void CodeParam::append( CodeParam other ) | |||||||
| 	self->NumEntries++; | 	self->NumEntries++; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| CodeParam CodeParam::get( s32 idx ) | CodeParam CodeParam::get( s32 idx ) | ||||||
| { | { | ||||||
| 	CodeParam param = *this; | 	CodeParam param = *this; | ||||||
| @@ -115,31 +143,34 @@ CodeParam CodeParam::get( s32 idx ) | |||||||
| 		if ( ! ++ param ) | 		if ( ! ++ param ) | ||||||
| 			return { nullptr }; | 			return { nullptr }; | ||||||
|  |  | ||||||
| 		return { (AST_Param*) param.raw()->Next }; | 		param = { (AST_Param*) param.raw()->Next }; | ||||||
| 	} | 	} | ||||||
| 	while ( --idx ); | 	while ( --idx ); | ||||||
|  |  | ||||||
| 	return { nullptr }; | 	return param; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| bool CodeParam::has_entries() | bool CodeParam::has_entries() | ||||||
| { | { | ||||||
| 	return ast->NumEntries > 0; | 	return ast->NumEntries > 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| CodeParam& CodeParam::operator ++() | CodeParam& CodeParam::operator ++() | ||||||
| { | { | ||||||
| 	ast = ast->Next.ast; | 	ast = ast->Next.ast; | ||||||
| 	return * this; | 	return * this; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| void CodeStruct::add_interface( CodeType type ) | void CodeStruct::add_interface( CodeType type ) | ||||||
| { | { | ||||||
| 	CodeType possible_slot = ast->ParentType; | 	CodeType possible_slot = ast->ParentType; | ||||||
| 	if ( possible_slot.ast ) | 	if ( possible_slot.ast ) | ||||||
| 	{ | 	{ | ||||||
| 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | 		// Were adding an interface to parent type, so we need to make sure the parent type is public. | ||||||
| 		ast->ParentAccess = AccessSpec::Public; | 		ast->ParentAccess = AccessSpec_Public; | ||||||
| 		// If your planning on adding a proper parent, | 		// If your planning on adding a proper parent, | ||||||
| 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | 		// then you'll need to move this over to ParentType->next and update ParentAccess accordingly. | ||||||
| 	} | 	} | ||||||
| @@ -152,6 +183,7 @@ void CodeStruct::add_interface( CodeType type ) | |||||||
| 	possible_slot.ast = type.ast; | 	possible_slot.ast = type.ast; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| CodeBody def_body( CodeT type ) | CodeBody def_body( CodeT type ) | ||||||
| { | { | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| @@ -179,7 +211,8 @@ CodeBody def_body( CodeT type ) | |||||||
| 	return (CodeBody)result; | 	return (CodeBody)result; | ||||||
| } | } | ||||||
|  |  | ||||||
| StrC token_fmt_impl( sw num, ... ) | inline | ||||||
|  | StrC token_fmt_impl( ssize num, ... ) | ||||||
| { | { | ||||||
| 	local_persist thread_local | 	local_persist thread_local | ||||||
| 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
| @@ -187,7 +220,7 @@ StrC token_fmt_impl( sw num, ... ) | |||||||
|  |  | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start(va, num ); | 	va_start(va, num ); | ||||||
| 	sw result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va); | 	ssize result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	return { result, buf }; | 	return { result, buf }; | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ internal void deinit(); | |||||||
| } | } | ||||||
|  |  | ||||||
| internal | internal | ||||||
| void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) | void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Arena* last = & Global_AllocatorBuckets.back(); | 	Arena* last = & back(Global_AllocatorBuckets); | ||||||
|  |  | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| 	{ | 	{ | ||||||
| @@ -19,18 +19,18 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw a | |||||||
| 		{ | 		{ | ||||||
| 			if ( ( last->TotalUsed + size ) > last->TotalSize ) | 			if ( ( last->TotalUsed + size ) > last->TotalSize ) | ||||||
| 			{ | 			{ | ||||||
| 				Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 				Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 				if ( bucket.PhysicalStart == nullptr ) | 				if ( bucket.PhysicalStart == nullptr ) | ||||||
| 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				if ( ! Global_AllocatorBuckets.append( bucket ) ) | 				if ( ! append( Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = & Global_AllocatorBuckets.back(); | 				last = & back(Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return alloc_align( * last, size, alignment ); | 			return alloc_align( allocator_info(* last), size, alignment ); | ||||||
| 		} | 		} | ||||||
| 		case EAllocation_FREE: | 		case EAllocation_FREE: | ||||||
| 		{ | 		{ | ||||||
| @@ -46,15 +46,15 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw a | |||||||
| 		{ | 		{ | ||||||
| 			if ( last->TotalUsed + size > last->TotalSize ) | 			if ( last->TotalUsed + size > last->TotalSize ) | ||||||
| 			{ | 			{ | ||||||
| 				Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 				Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 				if ( bucket.PhysicalStart == nullptr ) | 				if ( bucket.PhysicalStart == nullptr ) | ||||||
| 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to create bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				if ( ! Global_AllocatorBuckets.append( bucket ) ) | 				if ( ! append( Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = & Global_AllocatorBuckets.back(); | 				last = & back(Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			void* result = alloc_align( last->Backing, size, alignment ); | 			void* result = alloc_align( last->Backing, size, alignment ); | ||||||
| @@ -74,31 +74,31 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, sw size, sw a | |||||||
| internal | internal | ||||||
| void define_constants() | void define_constants() | ||||||
| { | { | ||||||
| 	Code::Global          = make_code(); | 	Code::Global                         = make_code(); | ||||||
| 	Code::Global->Name    = get_cached_string( txt("Global Code") ); | 	scast(String, Code::Global->Name)    = get_cached_string( txt("Global Code") ); | ||||||
| 	Code::Global->Content = Code::Global->Name; | 	scast(String, Code::Global->Content) = Code::Global->Name; | ||||||
|  |  | ||||||
| 	Code::Invalid = make_code(); | 	Code::Invalid = make_code(); | ||||||
| 	Code::Invalid.set_global(); | 	Code::Invalid.set_global(); | ||||||
|  |  | ||||||
| 	t_empty          = (CodeType) make_code(); | 	t_empty       = (CodeType) make_code(); | ||||||
| 	t_empty->Type    = ECode::Typename; | 	t_empty->Type = ECode::Typename; | ||||||
| 	t_empty->Name    = get_cached_string( txt("") ); | 	t_empty->Name = get_cached_string( txt("") ); | ||||||
| 	t_empty.set_global(); | 	t_empty.set_global(); | ||||||
|  |  | ||||||
| 	access_private       = make_code(); | 	access_private       = make_code(); | ||||||
| 	access_private->Type = ECode::Access_Private; | 	access_private->Type = ECode::Access_Private; | ||||||
| 	access_private->Name = get_cached_string( txt("private:") ); | 	access_private->Name = get_cached_string( txt("private:\n") ); | ||||||
| 	access_private.set_global(); | 	access_private.set_global(); | ||||||
|  |  | ||||||
| 	access_protected       = make_code(); | 	access_protected       = make_code(); | ||||||
| 	access_protected->Type = ECode::Access_Protected; | 	access_protected->Type = ECode::Access_Protected; | ||||||
| 	access_protected->Name = get_cached_string( txt("protected:") ); | 	access_protected->Name = get_cached_string( txt("protected:\n") ); | ||||||
| 	access_protected.set_global(); | 	access_protected.set_global(); | ||||||
|  |  | ||||||
| 	access_public       = make_code(); | 	access_public       = make_code(); | ||||||
| 	access_public->Type = ECode::Access_Public; | 	access_public->Type = ECode::Access_Public; | ||||||
| 	access_public->Name = get_cached_string( txt("public:") ); | 	access_public->Name = get_cached_string( txt("public:\n") ); | ||||||
| 	access_public.set_global(); | 	access_public.set_global(); | ||||||
|  |  | ||||||
| 	attrib_api_export = def_attributes( code(GEN_API_Export_Code)); | 	attrib_api_export = def_attributes( code(GEN_API_Export_Code)); | ||||||
| @@ -169,8 +169,8 @@ void define_constants() | |||||||
| 	def_constant_code_type( u32 ); | 	def_constant_code_type( u32 ); | ||||||
| 	def_constant_code_type( u64 ); | 	def_constant_code_type( u64 ); | ||||||
|  |  | ||||||
| 	def_constant_code_type( sw ); | 	def_constant_code_type( ssize ); | ||||||
| 	def_constant_code_type( uw ); | 	def_constant_code_type( usize ); | ||||||
|  |  | ||||||
| 	def_constant_code_type( f32 ); | 	def_constant_code_type( f32 ); | ||||||
| 	def_constant_code_type( f64 ); | 	def_constant_code_type( f64 ); | ||||||
| @@ -226,6 +226,10 @@ void define_constants() | |||||||
| #	pragma pop_macro("local_persist") | #	pragma pop_macro("local_persist") | ||||||
| #	pragma pop_macro("neverinline") | #	pragma pop_macro("neverinline") | ||||||
|  |  | ||||||
|  | #	pragma push_macro("enum_underlying") | ||||||
|  |  | ||||||
|  | #	pragma pop_macro("enum_underlying") | ||||||
|  |  | ||||||
| #	undef def_constant_spec | #	undef def_constant_spec | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -235,28 +239,27 @@ void init() | |||||||
| 	{ | 	{ | ||||||
| 		GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; | 		GlobalAllocator = AllocatorInfo { & Global_Allocator_Proc, nullptr }; | ||||||
|  |  | ||||||
| 		Global_AllocatorBuckets = Array<Arena>::init_reserve( heap(), 128 ); | 		Global_AllocatorBuckets = array_init_reserve<Arena>( heap(), 128 ); | ||||||
|  |  | ||||||
| 		if ( Global_AllocatorBuckets == nullptr ) | 		if ( Global_AllocatorBuckets == nullptr ) | ||||||
| 			GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets"); | 			GEN_FATAL( "Failed to reserve memory for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 		Arena bucket = Arena::init_from_allocator( heap(), Global_BucketSize ); | 		Arena bucket = arena_init_from_allocator( heap(), Global_BucketSize ); | ||||||
|  |  | ||||||
| 		if ( bucket.PhysicalStart == nullptr ) | 		if ( bucket.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); | 			GEN_FATAL( "Failed to create first bucket for Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 		Global_AllocatorBuckets.append( bucket ); | 		append( Global_AllocatorBuckets, bucket ); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the arrays | 	// Setup the arrays | ||||||
| 	{ | 	{ | ||||||
| 		CodePools = Array<Pool>::init_reserve( Allocator_DataArrays, InitSize_DataArrays ); | 		CodePools = array_init_reserve<Pool>( Allocator_DataArrays, InitSize_DataArrays ); | ||||||
|  |  | ||||||
| 		if ( CodePools == nullptr ) | 		if ( CodePools == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the CodePools array" ); | 			GEN_FATAL( "gen::init: Failed to initialize the CodePools array" ); | ||||||
|  |  | ||||||
| 		StringArenas = Array<Arena>::init_reserve( Allocator_DataArrays, InitSize_DataArrays ); | 		StringArenas = array_init_reserve<Arena>( Allocator_DataArrays, InitSize_DataArrays ); | ||||||
|  |  | ||||||
| 		if ( StringArenas == nullptr ) | 		if ( StringArenas == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" ); | 			GEN_FATAL( "gen::init: Failed to initialize the StringArenas array" ); | ||||||
| @@ -264,33 +267,33 @@ void init() | |||||||
|  |  | ||||||
| 	// Setup the code pool and code entries arena. | 	// Setup the code pool and code entries arena. | ||||||
| 	{ | 	{ | ||||||
| 		Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | 		Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | ||||||
|  |  | ||||||
| 		if ( code_pool.PhysicalStart == nullptr ) | 		if ( code_pool.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the code pool" ); | 			GEN_FATAL( "gen::init: Failed to initialize the code pool" ); | ||||||
|  |  | ||||||
| 		CodePools.append( code_pool ); | 		append(CodePools, code_pool ); | ||||||
|  |  | ||||||
| 		LexArena = Arena::init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | 		LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | ||||||
|  |  | ||||||
| 		Arena string_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | 		Arena string_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		if ( string_arena.PhysicalStart == nullptr ) | 		if ( string_arena.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the string arena" ); | 			GEN_FATAL( "gen::init: Failed to initialize the string arena" ); | ||||||
|  |  | ||||||
| 		StringArenas.append( string_arena ); | 		append(StringArenas, string_arena ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the hash tables | 	// Setup the hash tables | ||||||
| 	{ | 	{ | ||||||
| 		StringCache = StringTable::init( Allocator_StringTable ); | 		StringCache = hashtable_init<StringCached>(Allocator_StringTable); | ||||||
|  |  | ||||||
| 		if ( StringCache.Entries == nullptr ) | 		if ( StringCache.Entries == nullptr ) | ||||||
| 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | 			GEN_FATAL( "gen::init: Failed to initialize the StringCache"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Preprocessor Defines | 	// Preprocessor Defines | ||||||
| 	PreprocessorDefines = Array<StringCached>::init_reserve( GlobalAllocator, kilobytes(1) ); | 	PreprocessorDefines = array_init_reserve<StringCached>( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	define_constants(); | 	define_constants(); | ||||||
| 	parser::init(); | 	parser::init(); | ||||||
| @@ -298,63 +301,63 @@ void init() | |||||||
|  |  | ||||||
| void deinit() | void deinit() | ||||||
| { | { | ||||||
| 	uw index = 0; | 	usize index = 0; | ||||||
| 	uw left  = CodePools.num(); | 	usize left  = num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		code_pool->free(); | 		free(* code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = StringArenas.num(); | 	left  = num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| 		string_arena->free(); | 		free(* string_arena); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	StringCache.destroy(); | 	destroy(StringCache); | ||||||
|  |  | ||||||
| 	CodePools.free(); | 	free(CodePools); | ||||||
| 	StringArenas.free(); | 	free(StringArenas); | ||||||
|  |  | ||||||
| 	LexArena.free(); | 	free(LexArena); | ||||||
|  |  | ||||||
| 	PreprocessorDefines.free(); | 	free(PreprocessorDefines); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = Global_AllocatorBuckets.num(); | 	left  = num(Global_AllocatorBuckets); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | ||||||
| 		bucket->free(); | 		free(* bucket); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	Global_AllocatorBuckets.free(); | 	free(Global_AllocatorBuckets); | ||||||
| 	parser::deinit(); | 	parser::deinit(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void reset() | void reset() | ||||||
| { | { | ||||||
| 	s32 index = 0; | 	s32 index = 0; | ||||||
| 	s32 left  = CodePools.num(); | 	s32 left  = num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		code_pool->clear(); | 		clear(* code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = StringArenas.num(); | 	left  = num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| @@ -363,28 +366,28 @@ void reset() | |||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	StringCache.clear(); | 	clear(StringCache); | ||||||
|  |  | ||||||
| 	define_constants(); | 	define_constants(); | ||||||
| } | } | ||||||
|  |  | ||||||
| AllocatorInfo get_string_allocator( s32 str_length ) | AllocatorInfo get_string_allocator( s32 str_length ) | ||||||
| { | { | ||||||
| 	Arena* last = & StringArenas.back(); | 	Arena* last = & back(StringArenas); | ||||||
|  |  | ||||||
| 	uw size_req = str_length + sizeof(String::Header) + sizeof(char*); | 	usize size_req = str_length + sizeof(StringHeader) + sizeof(char*); | ||||||
|  |  | ||||||
| 	if ( last->TotalUsed + size_req > last->TotalSize ) | 	if ( last->TotalUsed + ssize(size_req) > last->TotalSize ) | ||||||
| 	{ | 	{ | ||||||
| 		Arena new_arena = Arena::init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | 		Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		if ( ! StringArenas.append( new_arena ) ) | 		if ( ! append(StringArenas, new_arena ) ) | ||||||
| 			GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" ); | 			GEN_FATAL( "gen::get_string_allocator: Failed to allocate a new string arena" ); | ||||||
|  |  | ||||||
| 		last = & StringArenas.back(); | 		last = & back(StringArenas); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return * last; | 	return allocator_info(* last); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Will either make or retrive a code string. | // Will either make or retrive a code string. | ||||||
| @@ -393,14 +396,14 @@ StringCached get_cached_string( StrC str ) | |||||||
| 	s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; | 	s32 hash_length = str.Len > kilobytes(1) ? kilobytes(1) : str.Len; | ||||||
| 	u64 key         = crc32( str.Ptr, hash_length ); | 	u64 key         = crc32( str.Ptr, hash_length ); | ||||||
| 	{ | 	{ | ||||||
| 		StringCached* result = StringCache.get( key ); | 		StringCached* result = get(StringCache, key ); | ||||||
|  |  | ||||||
| 		if ( result ) | 		if ( result ) | ||||||
| 			return * result; | 			return * result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String result = String::make( get_string_allocator( str.Len ), str ); | 	String result = string_make( get_string_allocator( str.Len ), str ); | ||||||
| 	StringCache.set( key, result ); | 	set<StringCached>(StringCache, key, result ); | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -408,21 +411,21 @@ StringCached get_cached_string( StrC str ) | |||||||
| // Used internally to retireve a Code object form the CodePool. | // Used internally to retireve a Code object form the CodePool. | ||||||
| Code make_code() | Code make_code() | ||||||
| { | { | ||||||
| 	Pool* allocator = & CodePools.back(); | 	Pool* allocator = & back(CodePools); | ||||||
| 	if ( allocator->FreeList == nullptr ) | 	if ( allocator->FreeList == nullptr ) | ||||||
| 	{ | 	{ | ||||||
| 		Pool code_pool = Pool::init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | 		Pool code_pool = pool_init( Allocator_CodePool, CodePool_NumBlocks, sizeof(AST) ); | ||||||
|  |  | ||||||
| 		if ( code_pool.PhysicalStart == nullptr ) | 		if ( code_pool.PhysicalStart == nullptr ) | ||||||
| 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." ); | 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePool allcoator returned nullptr." ); | ||||||
|  |  | ||||||
| 		if ( ! CodePools.append( code_pool ) ) | 		if ( ! append( CodePools, code_pool ) ) | ||||||
| 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." ); | 			GEN_FATAL( "gen::make_code: Failed to allocate a new code pool - CodePools failed to append new pool." ); | ||||||
|  |  | ||||||
| 		allocator = & CodePools.back(); | 		allocator = & back(CodePools); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code result { rcast( AST*, alloc( * allocator, sizeof(AST) )) }; | 	Code result { rcast( AST*, alloc( allocator_info(* allocator), sizeof(AST) )) }; | ||||||
| 	mem_set( result.ast, 0, sizeof(AST) ); | 	mem_set( result.ast, 0, sizeof(AST) ); | ||||||
| 	// result->Type = ECode::Invalid; | 	// result->Type = ECode::Invalid; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,9 +44,9 @@ CodeComment    def_comment   ( StrC content ); | |||||||
|  |  | ||||||
| CodeClass def_class( StrC name | CodeClass def_class( StrC name | ||||||
| 	, Code           body         = NoCode | 	, Code           body         = NoCode | ||||||
| 	, CodeType       parent       = NoCode, AccessSpec access = AccessSpec::Default | 	, CodeType       parent       = NoCode, AccessSpec access = AccessSpec_Default | ||||||
| 	, CodeAttributes attributes   = NoCode | 	, CodeAttributes attributes   = NoCode | ||||||
| 	, ModuleFlag     mflags       = ModuleFlag::None | 	, ModuleFlag     mflags       = ModuleFlag_None | ||||||
| 	, CodeType*      interfaces   = nullptr, s32 num_interfaces = 0 ); | 	, CodeType*      interfaces   = nullptr, s32 num_interfaces = 0 ); | ||||||
|  |  | ||||||
| CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode ); | CodeConstructor def_constructor( CodeParam params = NoCode, Code initializer_list = NoCode, Code body = NoCode ); | ||||||
| @@ -56,9 +56,9 @@ CodeDefine def_define( StrC name, StrC content ); | |||||||
| CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode ); | CodeDestructor def_destructor( Code body = NoCode, CodeSpecifiers specifiers = NoCode ); | ||||||
|  |  | ||||||
| CodeEnum def_enum( StrC name | CodeEnum def_enum( StrC name | ||||||
| 	, Code         body      = NoCode,      CodeType       type       = NoCode | 	, Code         body      = NoCode,           CodeType       type       = NoCode | ||||||
| 	, EnumT        specifier = EnumRegular, CodeAttributes attributes = NoCode | 	, EnumT        specifier = EnumDecl_Regular, CodeAttributes attributes = NoCode | ||||||
| 	, ModuleFlag   mflags    = ModuleFlag::None ); | 	, ModuleFlag   mflags    = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeExec   def_execution  ( StrC content ); | CodeExec   def_execution  ( StrC content ); | ||||||
| CodeExtern def_extern_link( StrC name, Code body ); | CodeExtern def_extern_link( StrC name, Code body ); | ||||||
| @@ -67,16 +67,16 @@ CodeFriend def_friend     ( Code symbol ); | |||||||
| CodeFn def_function( StrC name | CodeFn def_function( StrC name | ||||||
| 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | ||||||
| 	, ModuleFlag mflags     = ModuleFlag::None ); | 	, ModuleFlag mflags     = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeInclude   def_include  ( StrC content, bool foreign = false ); | CodeInclude   def_include  ( StrC content, bool foreign = false ); | ||||||
| CodeModule    def_module   ( StrC name,            ModuleFlag mflags = ModuleFlag::None ); | CodeModule    def_module   ( StrC name,            ModuleFlag mflags = ModuleFlag_None ); | ||||||
| CodeNS        def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None ); | CodeNS        def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeOperator def_operator( OperatorT op, StrC nspace | CodeOperator def_operator( OperatorT op, StrC nspace | ||||||
| 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | 	, CodeParam      params     = NoCode, CodeType       ret_type   = NoCode, Code body = NoCode | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None ); | 	, ModuleFlag     mflags     = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode ); | CodeOpCast def_operator_cast( CodeType type, Code body = NoCode, CodeSpecifiers specs = NoCode ); | ||||||
|  |  | ||||||
| @@ -89,27 +89,27 @@ CodeSpecifiers def_specifier( SpecifierT specifier ); | |||||||
|  |  | ||||||
| CodeStruct def_struct( StrC name | CodeStruct def_struct( StrC name | ||||||
| 	, Code           body       = NoCode | 	, Code           body       = NoCode | ||||||
| 	, CodeType       parent     = NoCode, AccessSpec access = AccessSpec::Default | 	, CodeType       parent     = NoCode, AccessSpec access = AccessSpec_Default | ||||||
| 	, CodeAttributes attributes = NoCode | 	, CodeAttributes attributes = NoCode | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None | 	, ModuleFlag     mflags     = ModuleFlag_None | ||||||
| 	, CodeType*      interfaces = nullptr, s32 num_interfaces = 0 ); | 	, CodeType*      interfaces = nullptr, s32 num_interfaces = 0 ); | ||||||
|  |  | ||||||
| CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag::None ); | CodeTemplate def_template( CodeParam params, Code definition, ModuleFlag mflags = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeType    def_type   ( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode ); | CodeType    def_type   ( StrC name, Code arrayexpr = NoCode, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode ); | ||||||
| CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); | CodeTypedef def_typedef( StrC name, Code type, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); | CodeUnion def_union( StrC name, Code body, CodeAttributes attributes = NoCode, ModuleFlag mflags = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeUsing def_using( StrC name, CodeType type = NoCode | CodeUsing def_using( StrC name, CodeType type = NoCode | ||||||
| 	, CodeAttributes attributess = NoCode | 	, CodeAttributes attributess = NoCode | ||||||
| 	, ModuleFlag     mflags      = ModuleFlag::None ); | 	, ModuleFlag     mflags      = ModuleFlag_None ); | ||||||
|  |  | ||||||
| CodeUsing def_using_namespace( StrC name ); | CodeUsing def_using_namespace( StrC name ); | ||||||
|  |  | ||||||
| CodeVar def_variable( CodeType type, StrC name, Code value = NoCode | CodeVar def_variable( CodeType type, StrC name, Code value = NoCode | ||||||
| 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | 	, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode | ||||||
| 	, ModuleFlag     mflags     = ModuleFlag::None ); | 	, ModuleFlag     mflags     = ModuleFlag_None ); | ||||||
|  |  | ||||||
| // Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries. | // Constructs an empty body. Use AST::validate_body() to check if the body is was has valid entries. | ||||||
| CodeBody def_body( CodeT type ); | CodeBody def_body( CodeT type ); | ||||||
| @@ -166,7 +166,7 @@ namespace parser { | |||||||
| } | } | ||||||
|  |  | ||||||
| struct ParseInfo | struct ParseInfo | ||||||
|  | { | ||||||
| 	Arena FileMem; | 	Arena FileMem; | ||||||
| 	Arena TokMem; | 	Arena TokMem; | ||||||
| 	Arena CodeMem; | 	Arena CodeMem; | ||||||
| @@ -175,7 +175,7 @@ struct ParseInfo | |||||||
| 	Array<parser::Token> Tokens; | 	Array<parser::Token> Tokens; | ||||||
| 	Array<parser::Error> Errors; | 	Array<parser::Error> Errors; | ||||||
| 	// Errors are allocated to a dedicated general arena. | 	// Errors are allocated to a dedicated general arena. | ||||||
| ; | }; | ||||||
|  |  | ||||||
| CodeBody parse_file( StrC path ); | CodeBody parse_file( StrC path ); | ||||||
| #endif | #endif | ||||||
| @@ -204,9 +204,9 @@ CodeVar         parse_variable     ( StrC var_def         ); | |||||||
|  |  | ||||||
| #pragma region Untyped text | #pragma region Untyped text | ||||||
|  |  | ||||||
| sw   token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ); | ssize   token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ); | ||||||
| //! Do not use directly. Use the token_fmt macro instead. | //! Do not use directly. Use the token_fmt macro instead. | ||||||
| StrC token_fmt_impl( sw, ... ); | StrC token_fmt_impl( ssize, ... ); | ||||||
|  |  | ||||||
| Code untyped_str      ( StrC content); | Code untyped_str      ( StrC content); | ||||||
| Code untyped_fmt      ( char const* fmt, ... ); | Code untyped_fmt      ( char const* fmt, ... ); | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ | |||||||
| #include "interface.parsing.cpp" | #include "interface.parsing.cpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | ||||||
| { | { | ||||||
| 	char const* buf_begin = buf; | 	char const* buf_begin = buf; | ||||||
| 	sw          remaining = buf_size; | 	ssize       remaining = buf_size; | ||||||
|  |  | ||||||
| 	local_persist | 	local_persist | ||||||
| 	Arena tok_map_arena; | 	Arena tok_map_arena; | ||||||
| @@ -16,8 +16,8 @@ sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | |||||||
| 		local_persist | 		local_persist | ||||||
| 		char tok_map_mem[ TokenFmt_TokenMap_MemSize ]; | 		char tok_map_mem[ TokenFmt_TokenMap_MemSize ]; | ||||||
|  |  | ||||||
| 		tok_map_arena = Arena::init_from_memory( tok_map_mem, sizeof(tok_map_mem) ); | 		tok_map_arena = arena_init_from_memory( tok_map_mem, sizeof(tok_map_mem) ); | ||||||
| 		tok_map       = HashTable<StrC>::init( tok_map_arena ); | 		tok_map       = hashtable_init<StrC>( allocator_info(tok_map_arena) ); | ||||||
|  |  | ||||||
| 		s32 left = num_tokens - 1; | 		s32 left = num_tokens - 1; | ||||||
|  |  | ||||||
| @@ -28,7 +28,7 @@ sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | |||||||
|  |  | ||||||
| 			u32 key = crc32( token, str_len(token) ); | 			u32 key = crc32( token, str_len(token) ); | ||||||
|  |  | ||||||
| 			tok_map.set( key, value ); | 			set(tok_map, key, value ); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -37,7 +37,7 @@ sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | |||||||
|  |  | ||||||
| 	while ( current ) | 	while ( current ) | ||||||
| 	{ | 	{ | ||||||
| 		sw len = 0; | 		ssize len = 0; | ||||||
|  |  | ||||||
| 		while ( current && current != '<' && remaining ) | 		while ( current && current != '<' && remaining ) | ||||||
| 		{ | 		{ | ||||||
| @@ -64,11 +64,11 @@ sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | |||||||
| 			char const* token = fmt + 1; | 			char const* token = fmt + 1; | ||||||
|  |  | ||||||
| 			u32       key   = crc32( token, tok_len ); | 			u32       key   = crc32( token, tok_len ); | ||||||
| 			StrC*     value = tok_map.get( key ); | 			StrC*     value = get(tok_map, key ); | ||||||
|  |  | ||||||
| 			if ( value ) | 			if ( value ) | ||||||
| 			{ | 			{ | ||||||
| 				sw          left = value->Len; | 				ssize          left = value->Len; | ||||||
| 				char const* str  = value->Ptr; | 				char const* str  = value->Ptr; | ||||||
|  |  | ||||||
| 				while ( left-- ) | 				while ( left-- ) | ||||||
| @@ -94,10 +94,10 @@ sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va ) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	tok_map.clear(); | 	clear(tok_map); | ||||||
| 	tok_map_arena.free(); | 	free(tok_map_arena); | ||||||
|  |  | ||||||
| 	sw result = buf_size - remaining; | 	ssize result = buf_size - remaining; | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -138,7 +138,7 @@ Code untyped_fmt( char const* fmt, ...) | |||||||
|  |  | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start(va, fmt); | 	va_start(va, fmt); | ||||||
| 	sw length = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | 	ssize length = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| @@ -169,7 +169,7 @@ Code untyped_token_fmt( s32 num_tokens, ... ) | |||||||
|  |  | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start(va, num_tokens); | 	va_start(va, num_tokens); | ||||||
| 	sw length = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num_tokens, va); | 	ssize length = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num_tokens, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
|   | |||||||
| @@ -458,7 +458,7 @@ CodeComment def_comment( StrC content ) | |||||||
|  |  | ||||||
| 	static char line[ MaxCommentLineLength ]; | 	static char line[ MaxCommentLineLength ]; | ||||||
|  |  | ||||||
| 	String      cmt_formatted = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String      cmt_formatted = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	char const* end           = content.Ptr + content.Len; | 	char const* end           = content.Ptr + content.Len; | ||||||
| 	char const* scanner       = content.Ptr; | 	char const* scanner       = content.Ptr; | ||||||
| 	s32         curr          = 0; | 	s32         curr          = 0; | ||||||
| @@ -474,15 +474,15 @@ CodeComment def_comment( StrC content ) | |||||||
| 		length++; | 		length++; | ||||||
|  |  | ||||||
| 		str_copy( line, scanner, length ); | 		str_copy( line, scanner, length ); | ||||||
| 		cmt_formatted.append_fmt( "//%.*s", length, line ); | 		append_fmt(cmt_formatted, "//%.*s", length, line ); | ||||||
| 		mem_set( line, 0, MaxCommentLineLength ); | 		mem_set( line, 0, MaxCommentLineLength ); | ||||||
|  |  | ||||||
| 		scanner += length; | 		scanner += length; | ||||||
| 	} | 	} | ||||||
| 	while ( scanner <= end ); | 	while ( scanner <= end ); | ||||||
|  |  | ||||||
| 	if ( cmt_formatted.back() != '\n' ) | 	if ( back(cmt_formatted) != '\n' ) | ||||||
| 		cmt_formatted.append( "\n" ); | 		append( cmt_formatted, "\n" ); | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| @@ -490,7 +490,7 @@ CodeComment def_comment( StrC content ) | |||||||
| 	result->Name    = get_cached_string( cmt_formatted ); | 	result->Name    = get_cached_string( cmt_formatted ); | ||||||
| 	result->Content = result->Name; | 	result->Content = result->Name; | ||||||
|  |  | ||||||
| 	cmt_formatted.free(); | 	free(cmt_formatted); | ||||||
|  |  | ||||||
| 	return (CodeComment) result; | 	return (CodeComment) result; | ||||||
| } | } | ||||||
| @@ -719,14 +719,14 @@ CodeEnum def_enum( StrC name | |||||||
| 				return CodeInvalid; | 				return CodeInvalid; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		result->Type = specifier == EnumClass ? | 		result->Type = specifier == EnumDecl_Class ? | ||||||
| 			Enum_Class : Enum; | 			Enum_Class : Enum; | ||||||
|  |  | ||||||
| 		result->Body = body; | 		result->Body = body; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		result->Type = specifier == EnumClass ? | 		result->Type = specifier == EnumDecl_Class ? | ||||||
| 			Enum_Class_Fwd : Enum_Fwd; | 			Enum_Class_Fwd : Enum_Fwd; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1145,16 +1145,16 @@ CodePreprocessCond def_preprocess_cond( EPreprocessCond type, StrC expr ) | |||||||
|  |  | ||||||
| 	switch (type) | 	switch (type) | ||||||
| 	{ | 	{ | ||||||
| 		case EPreprocessCond::If: | 		case PreprocessCond_If: | ||||||
| 			result->Type = Preprocess_If; | 			result->Type = Preprocess_If; | ||||||
| 		break; | 		break; | ||||||
| 		case EPreprocessCond::IfDef: | 		case PreprocessCond_IfDef: | ||||||
| 			result->Type = Preprocess_IfDef; | 			result->Type = Preprocess_IfDef; | ||||||
| 		break; | 		break; | ||||||
| 		case EPreprocessCond::IfNotDef: | 		case PreprocessCond_IfNotDef: | ||||||
| 			result->Type = Preprocess_IfNotDef; | 			result->Type = Preprocess_IfNotDef; | ||||||
| 		break; | 		break; | ||||||
| 		case EPreprocessCond::ElIf: | 		case PreprocessCond_ElIf: | ||||||
| 			result->Type = Preprocess_ElIf; | 			result->Type = Preprocess_ElIf; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -89,11 +89,11 @@ struct Token | |||||||
|  |  | ||||||
| 	String to_string() | 	String to_string() | ||||||
| 	{ | 	{ | ||||||
| 		String result = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 		String result = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
|  |  | ||||||
| 		StrC type_str = ETokType::to_str( Type ); | 		StrC type_str = ETokType::to_str( Type ); | ||||||
|  |  | ||||||
| 		result.append_fmt( "Line: %d Column: %d, Type: %.*s Content: %.*s" | 		append_fmt( result, "Line: %d Column: %d, Type: %.*s Content: %.*s" | ||||||
| 			, Line, Column | 			, Line, Column | ||||||
| 			, type_str.Len, type_str.Ptr | 			, type_str.Len, type_str.Ptr | ||||||
| 			, Length, Text | 			, Length, Text | ||||||
| @@ -159,7 +159,7 @@ struct TokArray | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| global Arena_128KB     defines_map_arena; | global Arena_256KB     defines_map_arena; | ||||||
| global HashTable<StrC> defines; | global HashTable<StrC> defines; | ||||||
| global Array<Token>    Tokens; | global Array<Token>    Tokens; | ||||||
|  |  | ||||||
| @@ -222,7 +222,7 @@ s32 lex_preprocessor_directive( | |||||||
| 	, Token&           token ) | 	, Token&           token ) | ||||||
| { | { | ||||||
| 	char const* hash = scanner; | 	char const* hash = scanner; | ||||||
| 	Tokens.append( { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } ); | 	append(Tokens, { hash, 1, TokType::Preprocess_Hash, line, column, TF_Preprocess } ); | ||||||
|  |  | ||||||
| 	move_forward(); | 	move_forward(); | ||||||
| 	SkipWhitespace(); | 	SkipWhitespace(); | ||||||
| @@ -298,14 +298,14 @@ s32 lex_preprocessor_directive( | |||||||
|  |  | ||||||
| 		token.Length = token.Length + token.Text - hash; | 		token.Length = token.Length + token.Text - hash; | ||||||
| 		token.Text   = hash; | 		token.Text   = hash; | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		return Lex_Continue; // Skip found token, its all handled here. | 		return Lex_Continue; // Skip found token, its all handled here. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf ) | 	if ( token.Type == TokType::Preprocess_Else || token.Type == TokType::Preprocess_EndIf ) | ||||||
| 	{ | 	{ | ||||||
| 		token.Flags |= TF_Preprocess_Cond; | 		token.Flags |= TF_Preprocess_Cond; | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		end_line(); | 		end_line(); | ||||||
| 		return Lex_Continue; | 		return Lex_Continue; | ||||||
| 	} | 	} | ||||||
| @@ -314,7 +314,7 @@ s32 lex_preprocessor_directive( | |||||||
| 		token.Flags |= TF_Preprocess_Cond; | 		token.Flags |= TF_Preprocess_Cond; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Tokens.append( token ); | 	append(Tokens, token ); | ||||||
|  |  | ||||||
| 	SkipWhitespace(); | 	SkipWhitespace(); | ||||||
|  |  | ||||||
| @@ -338,10 +338,10 @@ s32 lex_preprocessor_directive( | |||||||
| 			name.Length++; | 			name.Length++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		Tokens.append( name ); | 		append(Tokens, name ); | ||||||
|  |  | ||||||
| 		u64 key = crc32( name.Text, name.Length ); | 		u64 key = crc32( name.Text, name.Length ); | ||||||
| 		defines.set( key, name ); | 		set<StrC>(defines, key, name ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess }; | 	Token preprocess_content = { scanner, 0, TokType::Preprocess_Content, line, column, TF_Preprocess }; | ||||||
| @@ -352,7 +352,7 @@ s32 lex_preprocessor_directive( | |||||||
|  |  | ||||||
| 		if ( current != '"' && current != '<' ) | 		if ( current != '"' && current != '<' ) | ||||||
| 		{ | 		{ | ||||||
| 			String directive_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text ); | 			String directive_str = string_fmt_buf( GlobalAllocator, "%.*s", min( 80, left + preprocess_content.Length ), token.Text ); | ||||||
|  |  | ||||||
| 			log_failure( "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s" | 			log_failure( "gen::Parser::lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s" | ||||||
| 				, current | 				, current | ||||||
| @@ -374,7 +374,17 @@ s32 lex_preprocessor_directive( | |||||||
| 		move_forward(); | 		move_forward(); | ||||||
| 		preprocess_content.Length++; | 		preprocess_content.Length++; | ||||||
|  |  | ||||||
| 		Tokens.append( preprocess_content ); | 		if ( current == '\r' && scanner[1] == '\n' ) | ||||||
|  | 		{ | ||||||
|  | 			move_forward(); | ||||||
|  | 			move_forward(); | ||||||
|  | 		} | ||||||
|  | 		else if ( current == '\n' ) | ||||||
|  | 		{ | ||||||
|  | 			move_forward(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		append(Tokens, preprocess_content ); | ||||||
| 		return Lex_Continue; // Skip found token, its all handled here. | 		return Lex_Continue; // Skip found token, its all handled here. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -409,8 +419,8 @@ s32 lex_preprocessor_directive( | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				String directive_str = String::make_length( GlobalAllocator, token.Text, token.Length ); | 				String directive_str = string_make_length( GlobalAllocator, token.Text, token.Length ); | ||||||
| 				String content_str   = String::fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text ); | 				String content_str   = string_fmt_buf( GlobalAllocator, "%.*s", min( 400, left + preprocess_content.Length ), preprocess_content.Text ); | ||||||
|  |  | ||||||
| 				log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" | 				log_failure( "gen::Parser::lex: Invalid escape sequence '\\%c' (%d, %d)" | ||||||
| 							" in preprocessor directive '%s' (%d, %d)\n%s" | 							" in preprocessor directive '%s' (%d, %d)\n%s" | ||||||
| @@ -436,7 +446,7 @@ s32 lex_preprocessor_directive( | |||||||
| 		preprocess_content.Length++; | 		preprocess_content.Length++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Tokens.append( preprocess_content ); | 	append(Tokens, preprocess_content ); | ||||||
| 	return Lex_Continue; // Skip found token, its all handled here. | 	return Lex_Continue; // Skip found token, its all handled here. | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -451,7 +461,7 @@ void lex_found_token( StrC& content | |||||||
| { | { | ||||||
| 	if ( token.Type != TokType::Invalid ) | 	if ( token.Type != TokType::Invalid ) | ||||||
| 	{ | 	{ | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -478,7 +488,7 @@ void lex_found_token( StrC& content | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		token.Type = type; | 		token.Type = type; | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -488,7 +498,7 @@ void lex_found_token( StrC& content | |||||||
| 	{ | 	{ | ||||||
| 		token.Type   = type; | 		token.Type   = type; | ||||||
| 		token.Flags |= TF_Specifier; | 		token.Flags |= TF_Specifier; | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -496,7 +506,7 @@ void lex_found_token( StrC& content | |||||||
| 	if ( type != TokType::Invalid ) | 	if ( type != TokType::Invalid ) | ||||||
| 	{ | 	{ | ||||||
| 		token.Type = type; | 		token.Type = type; | ||||||
| 		Tokens.append( token ); | 		append(Tokens, token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -506,7 +516,7 @@ void lex_found_token( StrC& content | |||||||
| 	else | 	else | ||||||
| 		key = crc32( token.Text, token.Length ); | 		key = crc32( token.Text, token.Length ); | ||||||
|  |  | ||||||
| 	StrC* define = defines.get( key ); | 	StrC* define = get(defines, key ); | ||||||
| 	if ( define ) | 	if ( define ) | ||||||
| 	{ | 	{ | ||||||
| 		token.Type = TokType::Preprocess_Macro; | 		token.Type = TokType::Preprocess_Macro; | ||||||
| @@ -548,7 +558,7 @@ void lex_found_token( StrC& content | |||||||
| 		token.Type = TokType::Identifier; | 		token.Type = TokType::Identifier; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Tokens.append( token ); | 	append(Tokens, token ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -572,11 +582,11 @@ TokArray lex( StrC content ) | |||||||
| 		return { { nullptr }, 0 }; | 		return { { nullptr }, 0 }; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( StringCached entry : PreprocessorDefines ) | 	foreach( StringCached, entry, PreprocessorDefines ) | ||||||
| 	{ | 	{ | ||||||
| 		s32         length  = 0; | 		s32         length  = 0; | ||||||
| 		char const* scanner = entry.Data; | 		char const* scanner = entry.Data; | ||||||
| 		while ( entry.length() > length && char_is_alphanumeric( *scanner ) || *scanner == '_' ) | 		while ( GEN_NS length(entry) > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') ) | ||||||
| 		{ | 		{ | ||||||
| 			scanner++; | 			scanner++; | ||||||
| 			length ++; | 			length ++; | ||||||
| @@ -587,10 +597,10 @@ TokArray lex( StrC content ) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		u64 key = crc32( entry.Data, length ); | 		u64 key = crc32( entry.Data, length ); | ||||||
| 		defines.set( key, entry ); | 		set<StrC>(defines, key, entry ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Tokens.clear(); | 	clear(Tokens); | ||||||
|  |  | ||||||
| 	while (left ) | 	while (left ) | ||||||
| 	{ | 	{ | ||||||
| @@ -620,7 +630,7 @@ TokArray lex( StrC content ) | |||||||
| 				token.Type = TokType::NewLine; | 				token.Type = TokType::NewLine; | ||||||
| 				token.Length++; | 				token.Length++; | ||||||
|  |  | ||||||
| 				Tokens.append( token ); | 				append(Tokens, token ); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -668,7 +678,7 @@ TokArray lex( StrC content ) | |||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
| 					{ | 					{ | ||||||
| 						String context_str = String::fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) ); | 						String context_str = string_fmt_buf( GlobalAllocator, "%s", scanner, min( 100, left ) ); | ||||||
|  |  | ||||||
| 						log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str ); | 						log_failure( "gen::lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", current, line, column, context_str ); | ||||||
| 					} | 					} | ||||||
| @@ -1089,7 +1099,7 @@ TokArray lex( StrC content ) | |||||||
| 							move_forward(); | 							move_forward(); | ||||||
| 							token.Length++; | 							token.Length++; | ||||||
| 						} | 						} | ||||||
| 						Tokens.append( token ); | 						append(Tokens, token ); | ||||||
| 						continue; | 						continue; | ||||||
| 					} | 					} | ||||||
| 					else if ( current == '*' ) | 					else if ( current == '*' ) | ||||||
| @@ -1125,7 +1135,7 @@ TokArray lex( StrC content ) | |||||||
| 							move_forward(); | 							move_forward(); | ||||||
| 							token.Length++; | 							token.Length++; | ||||||
| 						} | 						} | ||||||
| 						Tokens.append( token ); | 						append(Tokens, token ); | ||||||
| 						// end_line(); | 						// end_line(); | ||||||
| 						continue; | 						continue; | ||||||
| 					} | 					} | ||||||
| @@ -1192,15 +1202,35 @@ TokArray lex( StrC content ) | |||||||
| 					move_forward(); | 					move_forward(); | ||||||
| 					token.Length++; | 					token.Length++; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				// Handle number literal suffixes in a botched way | ||||||
|  | 				if (left && ( | ||||||
|  | 					current == 'l' || current == 'L' ||  // long/long long | ||||||
|  | 					current == 'u' || current == 'U' ||  // unsigned | ||||||
|  | 					current == 'f' || current == 'F' ||  // float | ||||||
|  | 					current == 'i' || current == 'I' ||  // imaginary | ||||||
|  | 					current == 'z' || current == 'Z'))   // complex | ||||||
|  | 				{ | ||||||
|  | 					char prev = current; | ||||||
|  | 					move_forward(); | ||||||
|  | 					token.Length++; | ||||||
|  |  | ||||||
|  | 					// Handle 'll'/'LL' as a special case when we just processed an 'l'/'L' | ||||||
|  | 					if (left && (prev == 'l' || prev == 'L') && (current == 'l' || current == 'L')) | ||||||
|  | 					{ | ||||||
|  | 						move_forward(); | ||||||
|  | 						token.Length++; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			goto FoundToken; | 			goto FoundToken; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			s32 start = max( 0, Tokens.num() - 100 ); | 			s32 start = max( 0, num(Tokens) - 100 ); | ||||||
| 			log_fmt("\n%d\n", start); | 			log_fmt("\n%d\n", start); | ||||||
| 			for ( s32 idx = start; idx < Tokens.num(); idx++ ) | 			for ( s32 idx = start; idx < num(Tokens); idx++ ) | ||||||
| 			{ | 			{ | ||||||
| 				log_fmt( "Token %d Type: %s : %.*s\n" | 				log_fmt( "Token %d Type: %s : %.*s\n" | ||||||
| 					, idx | 					, idx | ||||||
| @@ -1209,7 +1239,7 @@ TokArray lex( StrC content ) | |||||||
| 				); | 				); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			String context_str = String::fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner ); | 			String context_str = string_fmt_buf( GlobalAllocator, "%.*s", min( 100, left ), scanner ); | ||||||
| 			log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str ); | 			log_failure( "Failed to lex token '%c' (%d, %d)\n%s", current, line, column, context_str ); | ||||||
|  |  | ||||||
| 			// Skip to next whitespace since we can't know if anything else is valid until then. | 			// Skip to next whitespace since we can't know if anything else is valid until then. | ||||||
| @@ -1223,13 +1253,13 @@ TokArray lex( StrC content ) | |||||||
| 		lex_found_token( content, left, scanner, line, column, defines, token ); | 		lex_found_token( content, left, scanner, line, column, defines, token ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( Tokens.num() == 0 ) | 	if ( num(Tokens) == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "Failed to lex any tokens" ); | 		log_failure( "Failed to lex any tokens" ); | ||||||
| 		return { { nullptr }, 0 }; | 		return { { nullptr }, 0 }; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	defines.clear(); | 	clear(defines); | ||||||
| 	// defines_map_arena.free(); | 	// defines_map_arena.free(); | ||||||
| 	return { Tokens, 0 }; | 	return { Tokens, 0 }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -45,31 +45,31 @@ struct ParseContext | |||||||
|  |  | ||||||
| 	String to_string() | 	String to_string() | ||||||
| 	{ | 	{ | ||||||
| 		String result = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 		String result = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
|  |  | ||||||
| 		Token scope_start = Scope->Start; | 		Token scope_start = Scope->Start; | ||||||
| 		Token last_valid  = Tokens.Idx >= Tokens.Arr.num() ? Tokens.Arr[Tokens.Arr.num() -1] : Tokens.current(); | 		Token last_valid  = Tokens.Idx >= num(Tokens.Arr) ? Tokens.Arr[num(Tokens.Arr) -1] : Tokens.current(); | ||||||
|  |  | ||||||
| 		sptr        length  = scope_start.Length; | 		sptr        length  = scope_start.Length; | ||||||
| 		char const* current = scope_start.Text + length; | 		char const* current = scope_start.Text + length; | ||||||
| 		while ( current <= Tokens.Arr.back().Text && *current != '\n' && length < 74 ) | 		while ( current <= back(Tokens.Arr).Text && *current != '\n' && length < 74 ) | ||||||
| 		{ | 		{ | ||||||
| 			current++; | 			current++; | ||||||
| 			length++; | 			length++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		String line = String::make( GlobalAllocator, { length, scope_start.Text } ); | 		String line = string_make( GlobalAllocator, { length, scope_start.Text } ); | ||||||
| 		result.append_fmt("\tScope    : %s\n", line ); | 		append_fmt( result, "\tScope    : %s\n", line ); | ||||||
| 		line.free(); | 		free(line); | ||||||
|  |  | ||||||
| 		sptr   dist            = (sptr)last_valid.Text - (sptr)scope_start.Text + 2; | 		sptr   dist            = (sptr)last_valid.Text - (sptr)scope_start.Text + 2; | ||||||
| 		sptr   length_from_err = dist; | 		sptr   length_from_err = dist; | ||||||
| 		String line_from_err   = String::make( GlobalAllocator, { length_from_err, last_valid.Text } ); | 		String line_from_err   = string_make( GlobalAllocator, { length_from_err, last_valid.Text } ); | ||||||
|  |  | ||||||
| 		if ( length_from_err < 100 ) | 		if ( length_from_err < 100 ) | ||||||
| 			result.append_fmt("\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); | 			append_fmt(result, "\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); | ||||||
| 		else | 		else | ||||||
| 			result.append_fmt("\t(%d, %d)\n", last_valid.Line, last_valid.Column ); | 			append_fmt(result, "\t(%d, %d)\n", last_valid.Line, last_valid.Column ); | ||||||
|  |  | ||||||
| 		StackNode* curr_scope = Scope; | 		StackNode* curr_scope = Scope; | ||||||
| 		s32 level = 0; | 		s32 level = 0; | ||||||
| @@ -77,11 +77,11 @@ struct ParseContext | |||||||
| 		{ | 		{ | ||||||
| 			if ( curr_scope->Name ) | 			if ( curr_scope->Name ) | ||||||
| 			{ | 			{ | ||||||
| 				result.append_fmt("\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Length, curr_scope->Name.Text ); | 				append_fmt(result, "\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Length, curr_scope->Name.Text ); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				result.append_fmt("\t%d: %s\n", level, curr_scope->ProcName.Ptr ); | 				append_fmt(result, "\t%d: %s\n", level, curr_scope->ProcName.Ptr ); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			curr_scope = curr_scope->Prev; | 			curr_scope = curr_scope->Prev; | ||||||
| @@ -96,7 +96,7 @@ global ParseContext Context; | |||||||
|  |  | ||||||
| bool TokArray::__eat( TokType type ) | bool TokArray::__eat( TokType type ) | ||||||
| { | { | ||||||
| 	if ( Arr.num() - Idx <= 0 ) | 	if ( num(Arr) - Idx <= 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "No tokens left.\n%s", Context.to_string() ); | 		log_failure( "No tokens left.\n%s", Context.to_string() ); | ||||||
| 		return false; | 		return false; | ||||||
| @@ -132,12 +132,12 @@ bool TokArray::__eat( TokType type ) | |||||||
| internal | internal | ||||||
| void init() | void init() | ||||||
| { | { | ||||||
| 	Tokens = Array<Token>::init_reserve( LexArena | 	Tokens = array_init_reserve<Token>( allocator_info(LexArena) | ||||||
| 		, ( LexAllocator_Size - sizeof( Array<Token>::Header ) ) / sizeof(Token) | 		, ( LexAllocator_Size - sizeof( ArrayHeader ) ) / sizeof(Token) | ||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	defines_map_arena = Arena_128KB::init(); | 	fixed_arena_init(defines_map_arena); | ||||||
| 	defines           = HashTable<StrC>::init( defines_map_arena ); | 	defines = hashtable_init_reserve<StrC>( allocator_info(defines_map_arena), 256 ); | ||||||
| } | } | ||||||
|  |  | ||||||
| internal | internal | ||||||
| @@ -167,7 +167,13 @@ if ( def.Ptr == nullptr )                                                      \ | |||||||
| #	define prevtok        Context.Tokens.previous() | #	define prevtok        Context.Tokens.previous() | ||||||
| #	define nexttok		  Context.Tokens.next() | #	define nexttok		  Context.Tokens.next() | ||||||
| #	define eat( Type_ )   Context.Tokens.__eat( Type_ ) | #	define eat( Type_ )   Context.Tokens.__eat( Type_ ) | ||||||
| #	define left           ( Context.Tokens.Arr.num() - Context.Tokens.Idx ) | #	define left           ( num(Context.Tokens.Arr) - Context.Tokens.Idx ) | ||||||
|  |  | ||||||
|  | #ifdef check | ||||||
|  | #define CHECK_WAS_DEFINED | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #	define check_noskip( Type_ ) ( left && currtok_noskip.Type == Type_ ) | #	define check_noskip( Type_ ) ( left && currtok_noskip.Type == Type_ ) | ||||||
| #	define check( Type_ )        ( left && currtok.Type == Type_ ) | #	define check( Type_ )        ( left && currtok.Type == Type_ ) | ||||||
| @@ -237,7 +243,7 @@ constexpr bool strip_formatting_dont_preserve_newlines = false; | |||||||
| internal | internal | ||||||
| String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | ||||||
| { | { | ||||||
| 	String content = String::make_reserve( GlobalAllocator, raw_text.Len ); | 	String content = string_make_reserve( GlobalAllocator, raw_text.Len ); | ||||||
|  |  | ||||||
| 	if ( raw_text.Len == 0 ) | 	if ( raw_text.Len == 0 ) | ||||||
| 		return content; | 		return content; | ||||||
| @@ -284,7 +290,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if ( tokleft ) | 			if ( tokleft ) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content, cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -306,7 +312,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if ( tokleft ) | 			if ( tokleft ) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content, cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -320,7 +326,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			scanner += 2; | 			scanner += 2; | ||||||
| 			tokleft -= 2; | 			tokleft -= 2; | ||||||
|  |  | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content,  cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -339,7 +345,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if (tokleft) | 			if (tokleft) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content,  cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -348,10 +354,10 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 		if (scanner[0] == '\t') | 		if (scanner[0] == '\t') | ||||||
| 		{ | 		{ | ||||||
| 			if (pos > last_cut) | 			if (pos > last_cut) | ||||||
| 				content.append(cut_ptr, cut_length); | 				append( content, cut_ptr, cut_length); | ||||||
|  |  | ||||||
| 			if ( content.back() != ' ' ) | 			if ( back( content ) != ' ' ) | ||||||
| 				content.append(' '); | 				append( content, ' '); | ||||||
|  |  | ||||||
| 			move_fwd(); | 			move_fwd(); | ||||||
| 			last_cut = sptr(scanner) - sptr(raw_text.Ptr); | 			last_cut = sptr(scanner) - sptr(raw_text.Ptr); | ||||||
| @@ -367,17 +373,17 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 				scanner += 2; | 				scanner += 2; | ||||||
| 				tokleft -= 2; | 				tokleft -= 2; | ||||||
|  |  | ||||||
| 				content.append( cut_ptr, cut_length ); | 				append( content,  cut_ptr, cut_length ); | ||||||
| 				last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 				last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if ( pos > last_cut ) | 			if ( pos > last_cut ) | ||||||
| 				content.append( cut_ptr, cut_length ); | 				append( content,  cut_ptr, cut_length ); | ||||||
|  |  | ||||||
| 			// Replace with a space | 			// Replace with a space | ||||||
| 			if ( content.back() != ' ' ) | 			if ( back( content ) != ' ' ) | ||||||
| 				content.append( ' ' ); | 				append( content,  ' ' ); | ||||||
|  |  | ||||||
| 			scanner += 2; | 			scanner += 2; | ||||||
| 			tokleft -= 2; | 			tokleft -= 2; | ||||||
| @@ -394,17 +400,17 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
|  |  | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 				content.append( cut_ptr, cut_length ); | 				append( content,  cut_ptr, cut_length ); | ||||||
| 				last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 				last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if ( pos > last_cut ) | 			if ( pos > last_cut ) | ||||||
| 				content.append( cut_ptr, cut_length ); | 				append( content,  cut_ptr, cut_length ); | ||||||
|  |  | ||||||
| 			// Replace with a space | 			// Replace with a space | ||||||
| 			if ( content.back() != ' ' ) | 			if ( back( content ) != ' ' ) | ||||||
| 				content.append( ' ' ); | 				append( content,  ' ' ); | ||||||
|  |  | ||||||
| 			move_fwd(); | 			move_fwd(); | ||||||
|  |  | ||||||
| @@ -415,7 +421,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 		// Escaped newlines | 		// Escaped newlines | ||||||
| 		if ( scanner[0] == '\\' ) | 		if ( scanner[0] == '\\' ) | ||||||
| 		{ | 		{ | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content,  cut_ptr, cut_length ); | ||||||
|  |  | ||||||
| 			s32 amount_to_skip = 1; | 			s32 amount_to_skip = 1; | ||||||
| 			if ( tokleft > 1 && scanner[1] == '\n' ) | 			if ( tokleft > 1 && scanner[1] == '\n' ) | ||||||
| @@ -442,7 +448,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 		// Consectuive spaces | 		// Consectuive spaces | ||||||
| 		if ( tokleft > 1 && char_is_space( scanner[0] ) && char_is_space( scanner[ 1 ] ) ) | 		if ( tokleft > 1 && char_is_space( scanner[0] ) && char_is_space( scanner[ 1 ] ) ) | ||||||
| 		{ | 		{ | ||||||
| 			content.append( cut_ptr, cut_length ); | 			append( content,  cut_ptr, cut_length ); | ||||||
| 			do | 			do | ||||||
| 			{ | 			{ | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
| @@ -452,8 +458,8 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
|  |  | ||||||
| 			// Preserve only 1 space of formattting | 			// Preserve only 1 space of formattting | ||||||
| 			if ( content.back() != ' ' ) | 			if ( back( content ) != ' ' ) | ||||||
| 				content.append( ' ' ); | 				append( content,  ' ' ); | ||||||
|  |  | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -463,7 +469,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
|  |  | ||||||
| 	if ( last_cut < raw_text.Len ) | 	if ( last_cut < raw_text.Len ) | ||||||
| 	{ | 	{ | ||||||
| 		content.append( cut_ptr, raw_text.Len - last_cut ); | 		append( content,  cut_ptr, raw_text.Len - last_cut ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #undef cut_ptr | #undef cut_ptr | ||||||
| @@ -554,40 +560,6 @@ Code parse_array_decl() | |||||||
| 	return { nullptr }; | 	return { nullptr }; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal inline |  | ||||||
| Code parse_assignment_expression() |  | ||||||
| { |  | ||||||
| 	Code expr = { nullptr }; |  | ||||||
|  |  | ||||||
| 	eat( TokType::Operator ); |  | ||||||
| 	// <Attributes> <Specifiers> <ValueType> <Name> = |  | ||||||
|  |  | ||||||
| 	Token expr_tok = currtok; |  | ||||||
|  |  | ||||||
| 	if ( currtok.Type == TokType::Statement_End && currtok.Type != TokType::Comma ) |  | ||||||
| 	{ |  | ||||||
| 		log_failure( "Expected expression after assignment operator\n%s", Context.to_string() ); |  | ||||||
| 		Context.pop(); |  | ||||||
| 		return CodeInvalid; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	s32 level = 0; |  | ||||||
| 	while ( left && currtok.Type != TokType::Statement_End && (currtok.Type != TokType::Comma || level > 0) ) |  | ||||||
| 	{ |  | ||||||
| 		if (currtok.Type == TokType::Capture_Start) |  | ||||||
| 			level++; |  | ||||||
| 		else if (currtok.Type == TokType::Capture_End) |  | ||||||
| 			level--; |  | ||||||
|  |  | ||||||
| 		eat( currtok.Type ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	expr_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )expr_tok.Text - 1; |  | ||||||
| 	expr            = untyped_str( expr_tok ); |  | ||||||
| 	// = <Expression> |  | ||||||
| 	return expr; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| internal inline | internal inline | ||||||
| CodeAttributes parse_attributes() | CodeAttributes parse_attributes() | ||||||
| { | { | ||||||
| @@ -710,17 +682,17 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
|  |  | ||||||
| 	Token name { nullptr, 0, TokType::Invalid }; | 	Token name { nullptr, 0, TokType::Invalid }; | ||||||
|  |  | ||||||
| 	AccessSpec     access     = AccessSpec::Default; | 	AccessSpec     access     = AccessSpec_Default; | ||||||
| 	CodeType       parent     = { nullptr }; | 	CodeType       parent     = { nullptr }; | ||||||
| 	CodeBody       body       = { nullptr }; | 	CodeBody       body       = { nullptr }; | ||||||
| 	CodeAttributes attributes = { nullptr }; | 	CodeAttributes attributes = { nullptr }; | ||||||
| 	ModuleFlag     mflags     = ModuleFlag::None; | 	ModuleFlag     mflags     = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	CodeClass result = CodeInvalid; | 	CodeClass result = CodeInvalid; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <ModuleFlags> | 	// <ModuleFlags> | ||||||
| @@ -740,7 +712,10 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
|  |  | ||||||
| 	local_persist | 	local_persist | ||||||
| 	char interface_arr_mem[ kilobytes(4) ] {0}; | 	char interface_arr_mem[ kilobytes(4) ] {0}; | ||||||
| 	Array<CodeType> interfaces = Array<CodeType>::init_reserve( Arena::init_from_memory(interface_arr_mem, kilobytes(4) ), 4 ); | 	Array<CodeType> interfaces; { | ||||||
|  | 		Arena arena = arena_init_from_memory( interface_arr_mem, kilobytes(4) ); | ||||||
|  | 		interfaces  = array_init_reserve<CodeType>( allocator_info(arena), 4 ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. | 	// TODO(Ed) : Make an AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. | ||||||
| 	if ( check( TokType::Assign_Classifer ) ) | 	if ( check( TokType::Assign_Classifer ) ) | ||||||
| @@ -770,7 +745,7 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
| 			} | 			} | ||||||
| 			Token interface_tok = parse_identifier(); | 			Token interface_tok = parse_identifier(); | ||||||
|  |  | ||||||
| 			interfaces.append( def_type( interface_tok ) ); | 			append(interfaces, def_type( interface_tok ) ); | ||||||
| 			// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... | 			// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -802,7 +777,7 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
| 	if ( inline_cmt ) | 	if ( inline_cmt ) | ||||||
| 		result->InlineCmt = inline_cmt; | 		result->InlineCmt = inline_cmt; | ||||||
|  |  | ||||||
| 	interfaces.free(); | 	free(interfaces); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1064,8 +1039,8 @@ CodeBody parse_class_struct_body( TokType which, Token name ) | |||||||
|  |  | ||||||
| 					if ( attributes ) | 					if ( attributes ) | ||||||
| 					{ | 					{ | ||||||
| 						String fused = String::make_reserve( GlobalAllocator, attributes->Content.length() + more_attributes->Content.length() ); | 						String fused = string_make_reserve( GlobalAllocator, length(attributes->Content) + length(more_attributes->Content) ); | ||||||
| 						fused.append_fmt( "%S %S", attributes->Content, more_attributes->Content ); | 						append_fmt( fused, "%S %S", attributes->Content, more_attributes->Content ); | ||||||
|  |  | ||||||
| 						attributes->Name    = get_cached_string(fused); | 						attributes->Name    = get_cached_string(fused); | ||||||
| 						attributes->Content = attributes->Name; | 						attributes->Content = attributes->Name; | ||||||
| @@ -1177,7 +1152,7 @@ Code parse_complicated_definition( TokType which ) | |||||||
|  |  | ||||||
| 	s32 idx         = tokens.Idx; | 	s32 idx         = tokens.Idx; | ||||||
| 	s32 level       = 0; | 	s32 level       = 0; | ||||||
| 	for ( ; idx < tokens.Arr.num(); idx++ ) | 	for ( ; idx < num(tokens.Arr); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( tokens[ idx ].Type == TokType::BraceCurly_Open ) | 		if ( tokens[ idx ].Type == TokType::BraceCurly_Open ) | ||||||
| 			level++; | 			level++; | ||||||
| @@ -1345,17 +1320,14 @@ CodeDefine parse_define() | |||||||
| 	eat( TokType::Identifier ); | 	eat( TokType::Identifier ); | ||||||
| 	// #define <Name> | 	// #define <Name> | ||||||
|  |  | ||||||
| 	// Defines don't necessarily need content. |  | ||||||
| #if 0 |  | ||||||
| 	if ( ! check( TokType::Preprocess_Content )) | 	if ( ! check( TokType::Preprocess_Content )) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() ); | 		log_failure( "Error, expected content after #define %s\n%s", define->Name, Context.to_string() ); | ||||||
| 		Context.pop(); | 		Context.pop(); | ||||||
| 		return CodeInvalid; | 		return CodeInvalid; | ||||||
| 	} | 	} | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	if ( check(TokType::Preprocess_Content) && currtok.Length != 0 ) | 	if ( currtok.Length == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		define->Content = get_cached_string( currtok ); | 		define->Content = get_cached_string( currtok ); | ||||||
| 		eat( TokType::Preprocess_Content ); | 		eat( TokType::Preprocess_Content ); | ||||||
| @@ -1373,6 +1345,44 @@ CodeDefine parse_define() | |||||||
| 	return define; | 	return define; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | internal inline | ||||||
|  | Code parse_assignment_expression() | ||||||
|  | { | ||||||
|  | 	Code expr = { nullptr }; | ||||||
|  |  | ||||||
|  | 	eat( TokType::Operator ); | ||||||
|  | 	// <Attributes> <Specifiers> <ValueType> <Name> = | ||||||
|  |  | ||||||
|  | 	Token expr_tok = currtok; | ||||||
|  |  | ||||||
|  | 	if ( currtok.Type == TokType::Statement_End && currtok.Type != TokType::Comma ) | ||||||
|  | 	{ | ||||||
|  | 		log_failure( "Expected expression after assignment operator\n%s", Context.to_string() ); | ||||||
|  | 		Context.pop(); | ||||||
|  | 		return CodeInvalid; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s32 level = 0; | ||||||
|  | 	while ( left && currtok.Type != TokType::Statement_End && (currtok.Type != TokType::Comma || level > 0) ) | ||||||
|  | 	{ | ||||||
|  | 		if (currtok.Type == TokType::BraceCurly_Open ) | ||||||
|  | 			level++; | ||||||
|  | 		if (currtok.Type == TokType::BraceCurly_Close ) | ||||||
|  | 			level--; | ||||||
|  | 		if (currtok.Type == TokType::Capture_Start) | ||||||
|  | 			level++; | ||||||
|  | 		else if (currtok.Type == TokType::Capture_End) | ||||||
|  | 			level--; | ||||||
|  |  | ||||||
|  | 		eat( currtok.Type ); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expr_tok.Length = ( ( sptr )currtok.Text + currtok.Length ) - ( sptr )expr_tok.Text - 1; | ||||||
|  | 	expr            = untyped_str( expr_tok ); | ||||||
|  | 	// = <Expression> | ||||||
|  | 	return expr; | ||||||
|  | } | ||||||
|  |  | ||||||
| internal inline | internal inline | ||||||
| Code parse_forward_or_definition( TokType which, bool is_inplace ) | Code parse_forward_or_definition( TokType which, bool is_inplace ) | ||||||
| { | { | ||||||
| @@ -1403,8 +1413,6 @@ Code parse_forward_or_definition( TokType which, bool is_inplace ) | |||||||
|  |  | ||||||
| 			return CodeInvalid; | 			return CodeInvalid; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return CodeInvalid; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Function parsing is handled in multiple places because its initial signature is shared with variable parsing | // Function parsing is handled in multiple places because its initial signature is shared with variable parsing | ||||||
| @@ -1476,8 +1484,8 @@ CodeFn parse_function_after_name( | |||||||
| 	using namespace ECode; | 	using namespace ECode; | ||||||
|  |  | ||||||
| 	String | 	String | ||||||
| 	name_stripped = String::make( GlobalAllocator, name ); | 	name_stripped = string_make( GlobalAllocator, name ); | ||||||
| 	name_stripped.strip_space(); | 	strip_space(name_stripped); | ||||||
|  |  | ||||||
| 	CodeFn | 	CodeFn | ||||||
| 	result              = (CodeFn) make_code(); | 	result              = (CodeFn) make_code(); | ||||||
| @@ -1539,18 +1547,18 @@ Code parse_function_body() | |||||||
| 	result->Type = Function_Body; | 	result->Type = Function_Body; | ||||||
|  |  | ||||||
| 	// TODO : Support actual parsing of function body | 	// TODO : Support actual parsing of function body | ||||||
| 	Token start = currtok; | 	Token start = currtok_noskip; | ||||||
|  |  | ||||||
| 	s32 level = 0; | 	s32 level = 0; | ||||||
| 	while ( left && ( currtok.Type != TokType::BraceCurly_Close || level > 0 ) ) | 	while ( left && ( currtok_noskip.Type != TokType::BraceCurly_Close || level > 0 ) ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( currtok.Type == TokType::BraceCurly_Open ) | 		if ( currtok_noskip.Type == TokType::BraceCurly_Open ) | ||||||
| 			level++; | 			level++; | ||||||
|  |  | ||||||
| 		else if ( currtok.Type == TokType::BraceCurly_Close && level > 0 ) | 		else if ( currtok_noskip.Type == TokType::BraceCurly_Close && level > 0 ) | ||||||
| 			level--; | 			level--; | ||||||
|  |  | ||||||
| 		eat( currtok.Type ); | 		eat( currtok_noskip.Type ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Token previous = prevtok; | 	Token previous = prevtok; | ||||||
| @@ -1829,7 +1837,7 @@ CodeBody parse_global_nspace( CodeT which ) | |||||||
| 				bool found_operator_cast_outside_class_implmentation = false; | 				bool found_operator_cast_outside_class_implmentation = false; | ||||||
| 				s32  idx = Context.Tokens.Idx; | 				s32  idx = Context.Tokens.Idx; | ||||||
|  |  | ||||||
| 				for ( ; idx < Context.Tokens.Arr.num(); idx++ ) | 				for ( ; idx < num(Context.Tokens.Arr); idx++ ) | ||||||
| 				{ | 				{ | ||||||
| 					Token tok = Context.Tokens[ idx ]; | 					Token tok = Context.Tokens[ idx ]; | ||||||
|  |  | ||||||
| @@ -1851,7 +1859,7 @@ CodeBody parse_global_nspace( CodeT which ) | |||||||
|  |  | ||||||
| 				if ( found_operator_cast_outside_class_implmentation ) | 				if ( found_operator_cast_outside_class_implmentation ) | ||||||
| 				{ | 				{ | ||||||
| 					member = parse_operator_cast(); | 					member = parse_operator_cast( specifiers ); | ||||||
| 					// <Attributes> <Specifiers> <Name>::operator <Type>() { ... } | 					// <Attributes> <Specifiers> <Name>::operator <Type>() { ... } | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| @@ -1901,14 +1909,14 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) | |||||||
|  |  | ||||||
| 	s32   idx = tokens.Idx; | 	s32   idx = tokens.Idx; | ||||||
| 	Token nav = tokens[ idx ]; | 	Token nav = tokens[ idx ]; | ||||||
| 	for ( ; idx < tokens.Arr.num(); idx++, nav = tokens[ idx ] ) | 	for ( ; idx < num(tokens.Arr); idx++, nav = tokens[ idx ] ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( nav.Text[0] == '<' ) | 		if ( nav.Text[0] == '<' ) | ||||||
| 		{ | 		{ | ||||||
| 			// Skip templated expressions as they mey have expressions with the () operators | 			// Skip templated expressions as they mey have expressions with the () operators | ||||||
| 			s32 capture_level  = 0; | 			s32 capture_level  = 0; | ||||||
| 			s32 template_level = 0; | 			s32 template_level = 0; | ||||||
| 			for ( ; idx < tokens.Arr.num(); idx++, nav = tokens[idx] ) | 			for ( ; idx < num(tokens.Arr); idx++, nav = tokens[idx] ) | ||||||
| 			{ | 			{ | ||||||
| 				if (nav.Text[ 0 ] == '<') | 				if (nav.Text[ 0 ] == '<') | ||||||
| 					++ template_level; | 					++ template_level; | ||||||
| @@ -2503,7 +2511,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes | |||||||
| 	bool found_operator = false; | 	bool found_operator = false; | ||||||
| 	s32  idx            = Context.Tokens.Idx; | 	s32  idx            = Context.Tokens.Idx; | ||||||
|  |  | ||||||
| 	for ( ; idx < Context.Tokens.Arr.num(); idx++ ) | 	for ( ; idx < num(Context.Tokens.Arr); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		Token tok = Context.Tokens[ idx ]; | 		Token tok = Context.Tokens[ idx ]; | ||||||
|  |  | ||||||
| @@ -2526,7 +2534,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes | |||||||
| 	if ( found_operator ) | 	if ( found_operator ) | ||||||
| 	{ | 	{ | ||||||
| 		// Dealing with an operator overload | 		// Dealing with an operator overload | ||||||
| 		result = parse_operator_after_ret_type( ModuleFlag::None, attributes, specifiers, type ); | 		result = parse_operator_after_ret_type( ModuleFlag_None, attributes, specifiers, type ); | ||||||
| 		// <Attributes> <Specifiers> <ReturnType> operator ... | 		// <Attributes> <Specifiers> <ReturnType> operator ... | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| @@ -2534,10 +2542,17 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes | |||||||
| 		Token name = parse_identifier(); | 		Token name = parse_identifier(); | ||||||
| 		Context.Scope->Name = name; | 		Context.Scope->Name = name; | ||||||
|  |  | ||||||
| 		if ( check( TokType::Capture_Start) ) | 		bool detected_capture = check( TokType::Capture_Start ); | ||||||
|  |  | ||||||
|  | 		// Check three tokens ahead to make sure that were not dealing with a constructor initialization... | ||||||
|  | 		//                  (         350.0f    ,         <---  Could be the scenario | ||||||
|  | 		// Example : <Capture_Start> <Value> <Comma> | ||||||
|  | 		//                 idx         +1      +2 | ||||||
|  | 		bool detected_comma = Context.Tokens.Arr[ Context.Tokens.Idx + 2 ].Type == TokType::Comma; | ||||||
|  | 		if ( detected_capture && ! detected_comma ) | ||||||
| 		{ | 		{ | ||||||
| 			// Dealing with a function | 			// Dealing with a function | ||||||
| 			result = parse_function_after_name( ModuleFlag::None, attributes, specifiers, type, name ); | 			result = parse_function_after_name( ModuleFlag_None, attributes, specifiers, type, name ); | ||||||
| 			// <Attributes> <Specifiers> <ReturnType> <Name> ( ... | 			// <Attributes> <Specifiers> <ReturnType> <Name> ( ... | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @@ -2550,7 +2565,7 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			// Dealing with a variable | 			// Dealing with a variable | ||||||
| 			result = parse_variable_after_name( ModuleFlag::None, attributes, specifiers, type, name ); | 			result = parse_variable_after_name( ModuleFlag_None, attributes, specifiers, type, name ); | ||||||
| 			// <Attributes> <Specifiers> <ValueType> <Name> ... | 			// <Attributes> <Specifiers> <ValueType> <Name> ... | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -2619,10 +2634,11 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 		return { nullptr }; | 		return { nullptr }; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code     macro = { nullptr }; | 	Code     macro           = { nullptr }; | ||||||
| 	CodeType type  = { nullptr }; | 	CodeType type            = { nullptr }; | ||||||
| 	Code     value = { nullptr }; | 	Code     value           = { nullptr }; | ||||||
| 	Token    name  = NullToken; | 	Token    name            = NullToken; | ||||||
|  | 	Code     post_name_macro = { nullptr }; | ||||||
|  |  | ||||||
| 	if ( check( TokType::Varadic_Argument ) ) | 	if ( check( TokType::Varadic_Argument ) ) | ||||||
| 	{ | 	{ | ||||||
| @@ -2664,6 +2680,15 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 			// ( <Macro> <ValueType> <Name> | 			// ( <Macro> <ValueType> <Name> | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// Unreal has yet another type of macro: | ||||||
|  | 		// template<class T UE_REQUIRES(TPointerIsConvertibleFromTo<T, UInterface>::Value)> | ||||||
|  | 		// class T ... and then ^this^ UE_REQUIRES shows up | ||||||
|  | 		// So we need to consume that. | ||||||
|  | 		if ( check( TokType::Preprocess_Macro )) | ||||||
|  | 		{ | ||||||
|  | 			post_name_macro = parse_simple_preprocess( ETokType::Preprocess_Macro ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		// In template captures you can have a typename have direct assignment without a name | 		// In template captures you can have a typename have direct assignment without a name | ||||||
| 		// typename = typename ... | 		// typename = typename ... | ||||||
| 		// Which would result in a static value type from a struct expansion (traditionally) | 		// Which would result in a static value type from a struct expansion (traditionally) | ||||||
| @@ -2683,7 +2708,7 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
|  |  | ||||||
| 			s32 capture_level  = 0; | 			s32 capture_level  = 0; | ||||||
| 			s32 template_level = 0; | 			s32 template_level = 0; | ||||||
| 			while ( left && (currtok.Type != TokType::Comma) && template_level >= 0 && CheckEndParams() || capture_level > 0 || template_level > 0 ) | 			while ( (left && ( currtok.Type != TokType::Comma ) && template_level >= 0 && CheckEndParams()) || (capture_level > 0 || template_level > 0) ) | ||||||
| 			{ | 			{ | ||||||
| 				if (currtok.Text[ 0 ] == '<') | 				if (currtok.Text[ 0 ] == '<') | ||||||
| 					++ template_level; | 					++ template_level; | ||||||
| @@ -2767,6 +2792,15 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 				// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> | 				// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// Unreal has yet another type of macro: | ||||||
|  | 			// template<class T UE_REQUIRES(TPointerIsConvertibleFromTo<T, UInterface>::Value)> | ||||||
|  | 			// class T ... and then ^this^ UE_REQUIRES shows up | ||||||
|  | 			// So we need to consume that. | ||||||
|  | 			if ( check( TokType::Preprocess_Macro )) | ||||||
|  | 			{ | ||||||
|  | 				post_name_macro = parse_simple_preprocess( ETokType::Preprocess_Macro ); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			// In template captures you can have a typename have direct assignment without a name | 			// In template captures you can have a typename have direct assignment without a name | ||||||
| 			// typename = typename ... | 			// typename = typename ... | ||||||
| 			// Which would result in a static value type from a struct expansion (traditionally) | 			// Which would result in a static value type from a struct expansion (traditionally) | ||||||
| @@ -2786,11 +2820,10 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
|  |  | ||||||
| 				s32 capture_level  = 0; | 				s32 capture_level  = 0; | ||||||
| 				s32 template_level = 0; | 				s32 template_level = 0; | ||||||
| 				while ( left | 				while ( (left | ||||||
| 				&& currtok.Type != TokType::Comma | 				&& currtok.Type != TokType::Comma | ||||||
| 				&& template_level >= 0 | 				&& template_level >= 0 | ||||||
| 				&& CheckEndParams() | 				&& CheckEndParams()) || (capture_level > 0 || template_level > 0) ) | ||||||
| 				|| capture_level > 0 || template_level > 0 ) |  | ||||||
| 				{ | 				{ | ||||||
| 					if (currtok.Text[ 0 ] == '<') | 					if (currtok.Text[ 0 ] == '<') | ||||||
| 						++ template_level; | 						++ template_level; | ||||||
| @@ -2824,7 +2857,8 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 		if ( name.Length > 0 ) | 		if ( name.Length > 0 ) | ||||||
| 			param->Name = get_cached_string( name ); | 			param->Name = get_cached_string( name ); | ||||||
|  |  | ||||||
| 		param->ValueType = type; | 		param->PostNameMacro = post_name_macro; | ||||||
|  | 		param->ValueType     = type; | ||||||
|  |  | ||||||
| 		if ( value ) | 		if ( value ) | ||||||
| 			param->Value = value; | 			param->Value = value; | ||||||
| @@ -2867,7 +2901,7 @@ CodePreprocessCond parse_preprocess_cond() | |||||||
|  |  | ||||||
| 	CodePreprocessCond | 	CodePreprocessCond | ||||||
| 	cond       = (CodePreprocessCond) make_code(); | 	cond       = (CodePreprocessCond) make_code(); | ||||||
| 	cond->Type = scast(CodeT, currtok.Type - (ETokType::Preprocess_If - ECode::Preprocess_If) ); | 	cond->Type = scast(CodeT, currtok.Type - ( TokType::Preprocess_If - ECode::Preprocess_If ) ); | ||||||
| 	eat( currtok.Type ); | 	eat( currtok.Type ); | ||||||
| 	// #<Conditional> | 	// #<Conditional> | ||||||
|  |  | ||||||
| @@ -3062,6 +3096,8 @@ CodeVar parse_variable_after_name( | |||||||
| 	Code expr          = { nullptr }; | 	Code expr          = { nullptr }; | ||||||
| 	Code bitfield_expr = { nullptr }; | 	Code bitfield_expr = { nullptr }; | ||||||
|  |  | ||||||
|  | 	b32 using_constructor_initializer = false; | ||||||
|  |  | ||||||
| 	if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | 	if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) ) | ||||||
| 	{ | 	{ | ||||||
| 		// <Attributes> <Specifiers> <ValueType> <Name> = <Expression> | 		// <Attributes> <Specifiers> <ValueType> <Name> = <Expression> | ||||||
| @@ -3093,6 +3129,33 @@ CodeVar parse_variable_after_name( | |||||||
| 		// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> } | 		// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> } | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if ( currtok.Type == TokType::Capture_Start ) | ||||||
|  | 	{ | ||||||
|  | 		eat( TokType:: Capture_Start); | ||||||
|  | 		// <Attributes> <Specifiers> <ValueType> <Name> ( | ||||||
|  |  | ||||||
|  | 		Token expr_token = currtok; | ||||||
|  |  | ||||||
|  | 		using_constructor_initializer = true; | ||||||
|  |  | ||||||
|  | 		s32 level = 0; | ||||||
|  | 		while ( left && ( currtok.Type != TokType::Capture_End || level > 0 ) ) | ||||||
|  | 		{ | ||||||
|  | 			if ( currtok.Type == TokType::Capture_Start ) | ||||||
|  | 				level++; | ||||||
|  |  | ||||||
|  | 			else if ( currtok.Type == TokType::Capture_End && level > 0 ) | ||||||
|  | 				level--; | ||||||
|  |  | ||||||
|  | 			eat( currtok.Type ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		expr_token.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)expr_token.Text; | ||||||
|  | 		expr              = untyped_str( expr_token ); | ||||||
|  | 		eat( TokType::Capture_End ); | ||||||
|  | 		// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> ) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if ( currtok.Type == TokType::Assign_Classifer ) | 	if ( currtok.Type == TokType::Assign_Classifer ) | ||||||
| 	{ | 	{ | ||||||
| 		eat( TokType::Assign_Classifer ); | 		eat( TokType::Assign_Classifer ); | ||||||
| @@ -3187,6 +3250,8 @@ CodeVar parse_variable_after_name( | |||||||
| 		result->NextVar->Parent = result; | 		result->NextVar->Parent = result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	result->VarConstructorInit = using_constructor_initializer; | ||||||
|  |  | ||||||
| 	Context.pop(); | 	Context.pop(); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -3241,6 +3306,8 @@ CodeVar parse_variable_declaration_list() | |||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// eat(currtok.Type); | ||||||
|  |  | ||||||
| 			if ( specifiers ) | 			if ( specifiers ) | ||||||
| 				specifiers.append( spec ); | 				specifiers.append( spec ); | ||||||
| 			else | 			else | ||||||
| @@ -3252,7 +3319,7 @@ CodeVar parse_variable_declaration_list() | |||||||
| 		eat( TokType::Identifier ); | 		eat( TokType::Identifier ); | ||||||
| 		// , <Specifiers> <Name> | 		// , <Specifiers> <Name> | ||||||
|  |  | ||||||
| 		CodeVar var = parse_variable_after_name( ModuleFlag::None, NoCode, specifiers, NoCode, name ); | 		CodeVar var = parse_variable_after_name( ModuleFlag_None, NoCode, specifiers, NoCode, name ); | ||||||
| 		// , <Specifiers> <Name> ... | 		// , <Specifiers> <Name> ... | ||||||
|  |  | ||||||
| 		if ( ! result ) | 		if ( ! result ) | ||||||
| @@ -3522,6 +3589,8 @@ CodeEnum parse_enum( bool inplace_def ) | |||||||
| 	} | 	} | ||||||
| 	// enum <class> <Attributes> <Name> | 	// enum <class> <Attributes> <Name> | ||||||
|  |  | ||||||
|  | 	b32  use_macro_underlying = false; | ||||||
|  | 	Code underlying_macro = { nullptr }; | ||||||
| 	if ( currtok.Type == TokType::Assign_Classifer ) | 	if ( currtok.Type == TokType::Assign_Classifer ) | ||||||
| 	{ | 	{ | ||||||
| 		eat( TokType::Assign_Classifer ); | 		eat( TokType::Assign_Classifer ); | ||||||
| @@ -3536,6 +3605,17 @@ CodeEnum parse_enum( bool inplace_def ) | |||||||
| 		} | 		} | ||||||
| 		// enum <class> <Attributes> <Name> : <UnderlyingType> | 		// enum <class> <Attributes> <Name> : <UnderlyingType> | ||||||
| 	} | 	} | ||||||
|  | 	else if ( currtok.Type == TokType::Preprocess_Define ) | ||||||
|  | 	{ | ||||||
|  | 		// We'll support the enum_underlying macro | ||||||
|  | 		StrC sig = txt("enum_underlying"); | ||||||
|  |  | ||||||
|  | 		if (currtok.Length >= sig.Len && str_compare(currtok.Text, sig.Ptr, sig.Len) == 0 ) | ||||||
|  | 		{ | ||||||
|  | 			use_macro_underlying = true; | ||||||
|  | 			underlying_macro     = parse_simple_preprocess( ETokType::Preprocess_Macro); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	CodeBody body = { nullptr }; | 	CodeBody body = { nullptr }; | ||||||
|  |  | ||||||
| @@ -3642,6 +3722,13 @@ CodeEnum parse_enum( bool inplace_def ) | |||||||
| 						// <Name> = <Expression> <Macro>, | 						// <Name> = <Expression> <Macro>, | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | 					// Consume inline comments | ||||||
|  | 					// if ( currtok.Type == TokType::Comment && prevtok.Line == currtok.Line ) | ||||||
|  | 					// { | ||||||
|  | 						// eat( TokType::Comment ); | ||||||
|  | 						// <Name> = <Expression> <Macro>, // <Inline Comment> | ||||||
|  | 					// } | ||||||
|  |  | ||||||
| 					entry.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)entry.Text; | 					entry.Length = ( (sptr)prevtok.Text + prevtok.Length ) - (sptr)entry.Text; | ||||||
|  |  | ||||||
| 					member = untyped_str( entry ); | 					member = untyped_str( entry ); | ||||||
| @@ -3696,11 +3783,18 @@ CodeEnum parse_enum( bool inplace_def ) | |||||||
| 		result->Attributes = attributes; | 		result->Attributes = attributes; | ||||||
|  |  | ||||||
| 	if ( type ) | 	if ( type ) | ||||||
| 		result->UnderlyingType = type; | 	{ | ||||||
|  | 		result->EnumUnderlyingMacro = use_macro_underlying; | ||||||
|  | 		if ( use_macro_underlying ) | ||||||
|  | 			result->UnderlyingTypeMacro = underlying_macro; | ||||||
|  | 		else | ||||||
|  | 			result->UnderlyingType = type; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if ( inline_cmt ) | 	if ( inline_cmt ) | ||||||
| 		result->InlineCmt = inline_cmt; | 		result->InlineCmt = inline_cmt; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	Context.pop(); | 	Context.pop(); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -3786,7 +3880,7 @@ CodeFriend parse_friend() | |||||||
| 		Context.Scope->Name = name; | 		Context.Scope->Name = name; | ||||||
| 		// friend <ReturnType> <Name> | 		// friend <ReturnType> <Name> | ||||||
|  |  | ||||||
| 		function = parse_function_after_name( ModuleFlag::None, NoCode, NoCode, type, name ); | 		function = parse_function_after_name( ModuleFlag_None, NoCode, NoCode, type, name ); | ||||||
|  |  | ||||||
| 		// Parameter list | 		// Parameter list | ||||||
| 		// CodeParam params = parse_params(); | 		// CodeParam params = parse_params(); | ||||||
| @@ -3840,11 +3934,11 @@ CodeFn parse_function() | |||||||
|  |  | ||||||
| 	CodeAttributes attributes = { nullptr }; | 	CodeAttributes attributes = { nullptr }; | ||||||
| 	CodeSpecifiers specifiers = { nullptr }; | 	CodeSpecifiers specifiers = { nullptr }; | ||||||
| 	ModuleFlag     mflags     = ModuleFlag::None; | 	ModuleFlag     mflags     = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <export> | 	// <export> | ||||||
| @@ -3950,14 +4044,14 @@ CodeOperator parse_operator() | |||||||
|  |  | ||||||
| 	CodeAttributes attributes = { nullptr }; | 	CodeAttributes attributes = { nullptr }; | ||||||
| 	CodeSpecifiers specifiers = { nullptr }; | 	CodeSpecifiers specifiers = { nullptr }; | ||||||
| 	ModuleFlag     mflags     = ModuleFlag::None; | 	ModuleFlag     mflags     = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | 	SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | ||||||
| 	s32        NumSpecifiers = 0; | 	s32        NumSpecifiers = 0; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <export> | 	// <export> | ||||||
| @@ -4015,8 +4109,6 @@ CodeOpCast parse_operator_cast( CodeSpecifiers specifiers ) | |||||||
| { | { | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
|  |  | ||||||
| 	// TODO : Specifiers attributed to the cast |  | ||||||
|  |  | ||||||
| 	// Operator's namespace if not within same class. | 	// Operator's namespace if not within same class. | ||||||
| 	Token name = NullToken; | 	Token name = NullToken; | ||||||
| 	if ( check( TokType::Identifier ) ) | 	if ( check( TokType::Identifier ) ) | ||||||
| @@ -4042,7 +4134,7 @@ CodeOpCast parse_operator_cast( CodeSpecifiers specifiers ) | |||||||
| 	Code type = parse_type(); | 	Code type = parse_type(); | ||||||
| 	// <Specifiers> <Qualifier> :: ... operator <UnderlyingType> | 	// <Specifiers> <Qualifier> :: ... operator <UnderlyingType> | ||||||
|  |  | ||||||
| 	Context.Scope->Name = { type->Name.Data, type->Name.length() }; | 	Context.Scope->Name = { type->Name.Data, length(type->Name) }; | ||||||
|  |  | ||||||
| 	eat( TokType::Capture_Start ); | 	eat( TokType::Capture_Start ); | ||||||
| 	eat( TokType::Capture_End ); | 	eat( TokType::Capture_End ); | ||||||
| @@ -4140,11 +4232,11 @@ CodeTemplate parse_template() | |||||||
|  |  | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
|  |  | ||||||
| 	ModuleFlag mflags = ModuleFlag::None; | 	ModuleFlag mflags = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	if ( check( TokType::Module_Export ) ) | 	if ( check( TokType::Module_Export ) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <export> template | 	// <export> template | ||||||
| @@ -4276,7 +4368,7 @@ CodeTemplate parse_template() | |||||||
| 			bool found_operator_cast_outside_class_implmentation = false; | 			bool found_operator_cast_outside_class_implmentation = false; | ||||||
| 			s32  idx = Context.Tokens.Idx; | 			s32  idx = Context.Tokens.Idx; | ||||||
|  |  | ||||||
| 			for ( ; idx < Context.Tokens.Arr.num(); idx++ ) | 			for ( ; idx < num(Context.Tokens.Arr); idx++ ) | ||||||
| 			{ | 			{ | ||||||
| 				Token tok = Context.Tokens[ idx ]; | 				Token tok = Context.Tokens[ idx ]; | ||||||
|  |  | ||||||
| @@ -4314,6 +4406,7 @@ CodeTemplate parse_template() | |||||||
| 	result->Params      = params; | 	result->Params      = params; | ||||||
| 	result->Declaration = definition; | 	result->Declaration = definition; | ||||||
| 	result->ModuleFlags = mflags; | 	result->ModuleFlags = mflags; | ||||||
|  | 	// result->Name        = definition->Name; | ||||||
|  |  | ||||||
| 	Context.pop(); | 	Context.pop(); | ||||||
| 	return result; | 	return result; | ||||||
| @@ -4445,6 +4538,18 @@ else if ( currtok.Type == TokType::DeclType ) | |||||||
| 		name = currtok; | 		name = currtok; | ||||||
| 		eat(TokType::Type_Typename); | 		eat(TokType::Type_Typename); | ||||||
| 		// <typename> | 		// <typename> | ||||||
|  |  | ||||||
|  | 		if ( ! from_template ) | ||||||
|  | 		{ | ||||||
|  | 			name                = parse_identifier(); | ||||||
|  | 			Context.Scope->Name = name; | ||||||
|  | 			if ( ! name ) | ||||||
|  | 			{ | ||||||
|  | 				log_failure( "Error, failed to type signature\n%s", Context.to_string() ); | ||||||
|  | 				Context.pop(); | ||||||
|  | 				return CodeInvalid; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// The usual Identifier type signature that may have namespace qualifiers | 	// The usual Identifier type signature that may have namespace qualifiers | ||||||
| @@ -4771,11 +4876,11 @@ CodeTypedef parse_typedef() | |||||||
| 	Code  array_expr  = { nullptr }; | 	Code  array_expr  = { nullptr }; | ||||||
| 	Code  type        = { nullptr }; | 	Code  type        = { nullptr }; | ||||||
|  |  | ||||||
| 	ModuleFlag mflags = ModuleFlag::None; | 	ModuleFlag mflags = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <ModuleFlags> | 	// <ModuleFlags> | ||||||
| @@ -4812,7 +4917,7 @@ CodeTypedef parse_typedef() | |||||||
|  |  | ||||||
| 			s32 idx = tokens.Idx; | 			s32 idx = tokens.Idx; | ||||||
| 			s32 level = 0; | 			s32 level = 0; | ||||||
| 			for ( ; idx < tokens.Arr.num(); idx ++ ) | 			for ( ; idx < num(tokens.Arr); idx ++ ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( tokens[idx].Type == TokType::BraceCurly_Open ) | 				if ( tokens[idx].Type == TokType::BraceCurly_Open ) | ||||||
| 					level++; | 					level++; | ||||||
| @@ -4966,11 +5071,11 @@ CodeUnion parse_union( bool inplace_def ) | |||||||
| { | { | ||||||
| 	push_scope(); | 	push_scope(); | ||||||
|  |  | ||||||
| 	ModuleFlag mflags = ModuleFlag::None; | 	ModuleFlag mflags = ModuleFlag_None; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <ModuleFlags> | 	// <ModuleFlags> | ||||||
| @@ -5115,12 +5220,12 @@ CodeUsing parse_using() | |||||||
|  |  | ||||||
| 	bool is_namespace = false; | 	bool is_namespace = false; | ||||||
|  |  | ||||||
| 	ModuleFlag     mflags     = ModuleFlag::None; | 	ModuleFlag     mflags     = ModuleFlag_None; | ||||||
| 	CodeAttributes attributes = { nullptr }; | 	CodeAttributes attributes = { nullptr }; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <ModuleFlags> | 	// <ModuleFlags> | ||||||
| @@ -5209,13 +5314,13 @@ CodeVar parse_variable() | |||||||
| 	SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | 	SpecifierT specs_found[16] { ESpecifier::NumSpecifiers }; | ||||||
| 	s32        NumSpecifiers = 0; | 	s32        NumSpecifiers = 0; | ||||||
|  |  | ||||||
| 	ModuleFlag	   mflags     = ModuleFlag::None; | 	ModuleFlag	   mflags     = ModuleFlag_None; | ||||||
| 	CodeAttributes attributes = { nullptr }; | 	CodeAttributes attributes = { nullptr }; | ||||||
| 	CodeSpecifiers specifiers = { nullptr }; | 	CodeSpecifiers specifiers = { nullptr }; | ||||||
|  |  | ||||||
| 	if ( check(TokType::Module_Export) ) | 	if ( check(TokType::Module_Export) ) | ||||||
| 	{ | 	{ | ||||||
| 		mflags = ModuleFlag::Export; | 		mflags = ModuleFlag_Export; | ||||||
| 		eat( TokType::Module_Export ); | 		eat( TokType::Module_Export ); | ||||||
| 	} | 	} | ||||||
| 	// <ModuleFlags> | 	// <ModuleFlags> | ||||||
| @@ -5282,3 +5387,7 @@ CodeVar parse_variable() | |||||||
|  |  | ||||||
| // namespace parser | // namespace parser | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef CHECK_WAS_DEFINED | ||||||
|  | #pragma pop_macro("check") | ||||||
|  | #endif | ||||||
|   | |||||||
| @@ -9,4 +9,3 @@ | |||||||
| #ifndef GEN_ROLL_OWN_DEPENDENCIES | #ifndef GEN_ROLL_OWN_DEPENDENCIES | ||||||
| #	include "gen.dep.cpp" | #	include "gen.dep.cpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -97,8 +97,8 @@ global CodeType t_u16; | |||||||
| global CodeType t_u32; | global CodeType t_u32; | ||||||
| global CodeType t_u64; | global CodeType t_u64; | ||||||
|  |  | ||||||
| global CodeType t_sw; | global CodeType t_ssize; | ||||||
| global CodeType t_uw; | global CodeType t_usize; | ||||||
|  |  | ||||||
| global CodeType t_f32; | global CodeType t_f32; | ||||||
| global CodeType t_f64; | global CodeType t_f64; | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| #include "header_start.hpp" | #include "header_start.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| using LogFailType = sw(*)(char const*, ...); | using LogFailType = ssize(*)(char const*, ...); | ||||||
|  |  | ||||||
| // By default this library will either crash or exit if an error is detected while generating codes. | // By default this library will either crash or exit if an error is detected while generating codes. | ||||||
| // Even if set to not use GEN_FATAL, GEN_FATAL will still be used for memory failures as the library is unusable when they occur. | // Even if set to not use GEN_FATAL, GEN_FATAL will still be used for memory failures as the library is unusable when they occur. | ||||||
| @@ -13,64 +13,73 @@ using LogFailType = sw(*)(char const*, ...); | |||||||
| 	#define log_failure GEN_FATAL | 	#define log_failure GEN_FATAL | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| enum class AccessSpec : u32 | enum AccessSpec enum_underlying(u32) | ||||||
| { | { | ||||||
| 	Default, | 	AccessSpec_Default, | ||||||
| 	Private, | 	AccessSpec_Private, | ||||||
| 	Protected, | 	AccessSpec_Protected, | ||||||
| 	Public, | 	AccessSpec_Public, | ||||||
|  |  | ||||||
| 	Num_AccessSpec, | 	AccessSpec_Num_AccessSpec, | ||||||
| 	Invalid, | 	AccessSpec_Invalid, | ||||||
|  |  | ||||||
|  | 	AccessSpec_SizeDef = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | static_assert( size_of(AccessSpec) == size_of(u32)); | ||||||
|  |  | ||||||
| inline | inline | ||||||
| char const* to_str( AccessSpec type ) | char const* to_str( AccessSpec type ) | ||||||
| { | { | ||||||
| 	local_persist | 	local_persist | ||||||
| 	char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = { | 	char const* lookup[ (u32)AccessSpec_Num_AccessSpec ] = { | ||||||
| 		"", | 		"", | ||||||
| 		"private", | 		"private", | ||||||
| 		"protected", | 		"protected", | ||||||
| 		"public", | 		"public", | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	if ( type > AccessSpec::Public ) | 	if ( type > AccessSpec_Public ) | ||||||
| 		return "Invalid"; | 		return "Invalid"; | ||||||
|  |  | ||||||
| 	return lookup[ (u32)type ]; | 	return lookup[ (u32)type ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum CodeFlag enum_underlying(u32) | ||||||
| enum CodeFlag : u32 |  | ||||||
| { | { | ||||||
| 	None          = 0, | 	CodeFlag_None          = 0, | ||||||
| 	FunctionType  = bit(0), | 	CodeFlag_FunctionType  = bit(0), | ||||||
| 	ParamPack     = bit(1), | 	CodeFlag_ParamPack     = bit(1), | ||||||
| 	Module_Export = bit(2), | 	CodeFlag_Module_Export = bit(2), | ||||||
| 	Module_Import = bit(3), | 	CodeFlag_Module_Import = bit(3), | ||||||
|  |  | ||||||
|  | 	CodeFlag_SizeDef = GEN_U32_MAX, | ||||||
| }; | }; | ||||||
|  | static_assert( size_of(CodeFlag) == size_of(u32)); | ||||||
|  |  | ||||||
| // Used to indicate if enum definitoin is an enum class or regular enum. | // Used to indicate if enum definitoin is an enum class or regular enum. | ||||||
| enum class EnumT : u8 | enum EnumDecl enum_underlying(u8) | ||||||
| { | { | ||||||
| 	Regular, | 	EnumDecl_Regular, | ||||||
| 	Class | 	EnumDecl_Class, | ||||||
|  |  | ||||||
|  | 	EnumT_SizeDef = GEN_U8_MAX, | ||||||
| }; | }; | ||||||
|  | typedef u8 EnumT; | ||||||
|  |  | ||||||
| constexpr EnumT EnumClass   = EnumT::Class; | enum ModuleFlag enum_underlying(u32) | ||||||
| constexpr EnumT EnumRegular = EnumT::Regular; |  | ||||||
|  |  | ||||||
| enum class ModuleFlag : u32 |  | ||||||
| { | { | ||||||
| 	None    = 0, | 	ModuleFlag_None    = 0, | ||||||
| 	Export  = bit(0), | 	ModuleFlag_Export  = bit(0), | ||||||
| 	Import  = bit(1), | 	ModuleFlag_Import  = bit(1), | ||||||
|  |  | ||||||
| 	Num_ModuleFlags, | 	Num_ModuleFlags, | ||||||
| 	Invalid, | 	ModuleFlag_Invalid, | ||||||
| }; |  | ||||||
|  |  | ||||||
|  | 	ModuleFlag_SizeDef = GEN_U32_MAX, | ||||||
|  | }; | ||||||
|  | static_assert( size_of(ModuleFlag) == size_of(u32)); | ||||||
|  |  | ||||||
|  | inline | ||||||
| StrC to_str( ModuleFlag flag ) | StrC to_str( ModuleFlag flag ) | ||||||
| { | { | ||||||
| 	local_persist | 	local_persist | ||||||
| @@ -80,26 +89,25 @@ StrC to_str( ModuleFlag flag ) | |||||||
| 		{ sizeof("import"), "import" }, | 		{ sizeof("import"), "import" }, | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	if ( flag > ModuleFlag::Import ) | 	if ( flag > ModuleFlag_Import ) | ||||||
| 		return { sizeof("invalid"), "invalid" }; | 		return { sizeof("invalid"), "invalid" }; | ||||||
|  |  | ||||||
| 	return lookup[ (u32)flag ]; | 	return lookup[ (u32)flag ]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline | ||||||
| ModuleFlag operator|( ModuleFlag A, ModuleFlag B) | ModuleFlag operator|( ModuleFlag A, ModuleFlag B) | ||||||
| { | { | ||||||
| 	return (ModuleFlag)( (u32)A | (u32)B ); | 	return (ModuleFlag)( (u32)A | (u32)B ); | ||||||
| } | } | ||||||
|  |  | ||||||
| enum class EPreprocessCond : u32 | enum EPreprocessCond enum_underlying(u32) | ||||||
| { | { | ||||||
| 	If, | 	PreprocessCond_If, | ||||||
| 	IfDef, | 	PreprocessCond_IfDef, | ||||||
| 	IfNotDef, | 	PreprocessCond_IfNotDef, | ||||||
| 	ElIf | 	PreprocessCond_ElIf, | ||||||
| }; |  | ||||||
|  |  | ||||||
| constexpr EPreprocessCond PreprocessCond_If       = EPreprocessCond::If; | 	EPreprocessCond_SizeDef = GEN_U32_MAX, | ||||||
| constexpr EPreprocessCond PreprocessCond_IfDef    = EPreprocessCond::IfDef; | }; | ||||||
| constexpr EPreprocessCond PreprocessCond_IfNotDef = EPreprocessCond::IfNotDef; | static_assert( size_of(EPreprocessCond) == size_of(u32)); | ||||||
| constexpr EPreprocessCond PreprocessCond_ElIf     = EPreprocessCond::ElIf; |  | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| #ifdef GEN_INTELLISENSE_DIRECTIVES | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
| #	pragma once | #	pragma once | ||||||
|  | #	include "platform.hpp" | ||||||
| #	include "macros.hpp" | #	include "macros.hpp" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -47,21 +48,21 @@ | |||||||
| #if defined( GEN_COMPILER_MSVC ) | #if defined( GEN_COMPILER_MSVC ) | ||||||
| #	if _MSC_VER < 1300 | #	if _MSC_VER < 1300 | ||||||
| typedef unsigned char  u8; | typedef unsigned char  u8; | ||||||
| typedef signed char    s8; | typedef signed   char  s8; | ||||||
| typedef unsigned short u16; | typedef unsigned short u16; | ||||||
| typedef signed short   s16; | typedef signed   short s16; | ||||||
| typedef unsigned int   u32; | typedef unsigned int   u32; | ||||||
| typedef signed int     s32; | typedef signed   int   s32; | ||||||
| #    else | #    else | ||||||
| typedef unsigned __int8  u8; | typedef unsigned __int8  u8; | ||||||
| typedef signed __int8    s8; | typedef signed   __int8  s8; | ||||||
| typedef unsigned __int16 u16; | typedef unsigned __int16 u16; | ||||||
| typedef signed __int16   s16; | typedef signed   __int16 s16; | ||||||
| typedef unsigned __int32 u32; | typedef unsigned __int32 u32; | ||||||
| typedef signed __int32   s32; | typedef signed   __int32 s32; | ||||||
| #    endif | #    endif | ||||||
| typedef unsigned __int64 u64; | typedef unsigned __int64 u64; | ||||||
| typedef signed __int64   s64; | typedef signed   __int64 s64; | ||||||
| #else | #else | ||||||
| #	include <stdint.h> | #	include <stdint.h> | ||||||
|  |  | ||||||
| @@ -85,10 +86,10 @@ static_assert( sizeof( u16 ) == 2, "sizeof(u16) != 2" ); | |||||||
| static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" ); | static_assert( sizeof( u32 ) == 4, "sizeof(u32) != 4" ); | ||||||
| static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" ); | static_assert( sizeof( u64 ) == 8, "sizeof(u64) != 8" ); | ||||||
|  |  | ||||||
| typedef size_t    uw; | typedef size_t    usize; | ||||||
| typedef ptrdiff_t sw; | typedef ptrdiff_t ssize; | ||||||
|  |  | ||||||
| static_assert( sizeof( uw ) == sizeof( sw ), "sizeof(uw) != sizeof(sw)" ); | static_assert( sizeof( usize ) == sizeof( ssize ), "sizeof(usize) != sizeof(ssize)" ); | ||||||
|  |  | ||||||
| // NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 bit OSes. | // NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 bit OSes. | ||||||
| #if defined( _WIN64 ) | #if defined( _WIN64 ) | ||||||
| @@ -122,4 +123,21 @@ typedef s8  b8; | |||||||
| typedef s16 b16; | typedef s16 b16; | ||||||
| typedef s32 b32; | typedef s32 b32; | ||||||
|  |  | ||||||
|  | typedef void*       mem_ptr; | ||||||
|  | typedef void const* mem_ptr_const ; | ||||||
|  |  | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
|  | template<typename Type> uptr to_uptr( Type* ptr ) { return (uptr)ptr; } | ||||||
|  | template<typename Type> sptr to_sptr( Type* ptr ) { return (sptr)ptr; } | ||||||
|  |  | ||||||
|  | template<typename Type> mem_ptr       to_mem_ptr      ( Type ptr ) { return (mem_ptr)      ptr; } | ||||||
|  | template<typename Type> mem_ptr_const to_mem_ptr_const( Type ptr ) { return (mem_ptr_const)ptr; } | ||||||
|  | #else | ||||||
|  | #define to_utpr( ptr ) ((uptr)(ptr)) | ||||||
|  | #define to_stpr( ptr ) ((sptr)(ptr)) | ||||||
|  |  | ||||||
|  | #define to_mem_ptr( ptr)       ((mem_ptr)ptr) | ||||||
|  | #define to_mem_ptr_const( ptr) ((mem_ptr)ptr) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Basic Types | #pragma endregion Basic Types | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -24,7 +24,7 @@ | |||||||
| 	{                                                                                        \ | 	{                                                                                        \ | ||||||
| 		if ( ! ( cond ) )                                                                    \ | 		if ( ! ( cond ) )                                                                    \ | ||||||
| 		{                                                                                    \ | 		{                                                                                    \ | ||||||
| 			assert_handler( #cond, __FILE__, zpl_cast( s64 ) __LINE__, msg, ##__VA_ARGS__ ); \ | 			assert_handler( #cond, __FILE__, scast( s64, __LINE__ ), msg, ##__VA_ARGS__ );   \ | ||||||
| 			GEN_DEBUG_TRAP();                                                                \ | 			GEN_DEBUG_TRAP();                                                                \ | ||||||
| 		}                                                                                    \ | 		}                                                                                    \ | ||||||
| 	} while ( 0 ) | 	} while ( 0 ) | ||||||
| @@ -34,10 +34,6 @@ | |||||||
| // NOTE: Things that shouldn't happen with a message! | // NOTE: Things that shouldn't happen with a message! | ||||||
| #define GEN_PANIC( msg, ... ) GEN_ASSERT_MSG( 0, msg, ##__VA_ARGS__ ) | #define GEN_PANIC( msg, ... ) GEN_ASSERT_MSG( 0, msg, ##__VA_ARGS__ ) | ||||||
|  |  | ||||||
| void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); |  | ||||||
| s32  assert_crash( char const* condition ); |  | ||||||
| void process_exit( u32 code ); |  | ||||||
|  |  | ||||||
| #if Build_Debug | #if Build_Debug | ||||||
| 	#define GEN_FATAL( ... )                               \ | 	#define GEN_FATAL( ... )                               \ | ||||||
| 	do                                                     \ | 	do                                                     \ | ||||||
| @@ -60,4 +56,8 @@ void process_exit( u32 code ); | |||||||
| 	while (0) | 	while (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); | ||||||
|  | s32  assert_crash( char const* condition ); | ||||||
|  | void process_exit( u32 code ); | ||||||
|  |  | ||||||
| #pragma endregion Debug | #pragma endregion Debug | ||||||
|   | |||||||
| @@ -7,10 +7,11 @@ | |||||||
|  |  | ||||||
| #if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) | #if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) | ||||||
|  |  | ||||||
| internal wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, sw* w_len_ ) | internal | ||||||
|  | wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, ssize* w_len_ ) | ||||||
| { | { | ||||||
| 	wchar_t* w_text = NULL; | 	wchar_t* w_text = NULL; | ||||||
| 	sw       len = 0, w_len = 0, w_len1 = 0; | 	ssize       len = 0, w_len = 0, w_len1 = 0; | ||||||
| 	if ( text == NULL ) | 	if ( text == NULL ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( w_len_ ) | 		if ( w_len_ ) | ||||||
| @@ -24,7 +25,7 @@ internal wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, sw* w_ | |||||||
| 			*w_len_ = w_len; | 			*w_len_ = w_len; | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 	w_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, zpl_cast( int ) len, NULL, 0 ); | 	w_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), NULL, 0 ); | ||||||
| 	if ( w_len == 0 ) | 	if ( w_len == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( w_len_ ) | 		if ( w_len_ ) | ||||||
| @@ -32,7 +33,7 @@ internal wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, sw* w_ | |||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 	w_text = alloc_array( a, wchar_t, w_len + 1 ); | 	w_text = alloc_array( a, wchar_t, w_len + 1 ); | ||||||
| 	w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, zpl_cast( int ) len, w_text, zpl_cast( int ) w_len ); | 	w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), w_text, scast( int, w_len) ); | ||||||
| 	if ( w_len1 == 0 ) | 	if ( w_len1 == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		free( a, w_text ); | 		free( a, w_text ); | ||||||
| @@ -46,7 +47,8 @@ internal wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, sw* w_ | |||||||
| 	return w_text; | 	return w_text; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_SEEK_PROC( _win32_file_seek ) | internal | ||||||
|  | GEN_FILE_SEEK_PROC( _win32_file_seek ) | ||||||
| { | { | ||||||
| 	LARGE_INTEGER li_offset; | 	LARGE_INTEGER li_offset; | ||||||
| 	li_offset.QuadPart = offset; | 	li_offset.QuadPart = offset; | ||||||
| @@ -60,12 +62,13 @@ internal GEN_FILE_SEEK_PROC( _win32_file_seek ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_READ_AT_PROC( _win32_file_read ) | internal | ||||||
|  | GEN_FILE_READ_AT_PROC( _win32_file_read ) | ||||||
| { | { | ||||||
| 	// unused( stop_at_newline ); | 	// unused( stop_at_newline ); | ||||||
| 	b32 result = false; | 	b32 result = false; | ||||||
| 	_win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); | 	_win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); | ||||||
| 	DWORD size_ = zpl_cast( DWORD )( size > GEN_I32_MAX ? GEN_I32_MAX : size ); | 	DWORD size_ = scast( DWORD, ( size > GEN_I32_MAX ? GEN_I32_MAX : size )); | ||||||
| 	DWORD bytes_read_; | 	DWORD bytes_read_; | ||||||
| 	if ( ReadFile( fd.p, buffer, size_, &bytes_read_, NULL ) ) | 	if ( ReadFile( fd.p, buffer, size_, &bytes_read_, NULL ) ) | ||||||
| 	{ | 	{ | ||||||
| @@ -77,9 +80,10 @@ internal GEN_FILE_READ_AT_PROC( _win32_file_read ) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_WRITE_AT_PROC( _win32_file_write ) | internal | ||||||
|  | GEN_FILE_WRITE_AT_PROC( _win32_file_write ) | ||||||
| { | { | ||||||
| 	DWORD size_ = zpl_cast( DWORD )( size > GEN_I32_MAX ? GEN_I32_MAX : size ); | 	DWORD size_ = scast( DWORD, ( size > GEN_I32_MAX ? GEN_I32_MAX : size )); | ||||||
| 	DWORD bytes_written_; | 	DWORD bytes_written_; | ||||||
| 	_win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); | 	_win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); | ||||||
| 	if ( WriteFile( fd.p, buffer, size_, &bytes_written_, NULL ) ) | 	if ( WriteFile( fd.p, buffer, size_, &bytes_written_, NULL ) ) | ||||||
| @@ -91,14 +95,16 @@ internal GEN_FILE_WRITE_AT_PROC( _win32_file_write ) | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_CLOSE_PROC( _win32_file_close ) | internal | ||||||
|  | GEN_FILE_CLOSE_PROC( _win32_file_close ) | ||||||
| { | { | ||||||
| 	CloseHandle( fd.p ); | 	CloseHandle( fd.p ); | ||||||
| } | } | ||||||
|  |  | ||||||
| FileOperations const default_file_operations = { _win32_file_read, _win32_file_write, _win32_file_seek, _win32_file_close }; | FileOperations const default_file_operations = { _win32_file_read, _win32_file_write, _win32_file_seek, _win32_file_close }; | ||||||
|  |  | ||||||
| neverinline GEN_FILE_OPEN_PROC( _win32_file_open ) | neverinline | ||||||
|  | GEN_FILE_OPEN_PROC( _win32_file_open ) | ||||||
| { | { | ||||||
| 	DWORD    desired_access; | 	DWORD    desired_access; | ||||||
| 	DWORD    creation_disposition; | 	DWORD    creation_disposition; | ||||||
| @@ -176,7 +182,8 @@ neverinline GEN_FILE_OPEN_PROC( _win32_file_open ) | |||||||
| #else    // POSIX | #else    // POSIX | ||||||
| #	include <fcntl.h> | #	include <fcntl.h> | ||||||
|  |  | ||||||
| internal GEN_FILE_SEEK_PROC( _posix_file_seek ) | internal | ||||||
|  | GEN_FILE_SEEK_PROC( _posix_file_seek ) | ||||||
| { | { | ||||||
| #	if defined( GEN_SYSTEM_OSX ) | #	if defined( GEN_SYSTEM_OSX ) | ||||||
| 	s64 res = lseek( fd.i, offset, whence ); | 	s64 res = lseek( fd.i, offset, whence ); | ||||||
| @@ -190,10 +197,11 @@ internal GEN_FILE_SEEK_PROC( _posix_file_seek ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_READ_AT_PROC( _posix_file_read ) | internal | ||||||
|  | GEN_FILE_READ_AT_PROC( _posix_file_read ) | ||||||
| { | { | ||||||
| 	unused( stop_at_newline ); | 	unused( stop_at_newline ); | ||||||
| 	sw res = pread( fd.i, buffer, size, offset ); | 	ssize res = pread( fd.i, buffer, size, offset ); | ||||||
| 	if ( res < 0 ) | 	if ( res < 0 ) | ||||||
| 		return false; | 		return false; | ||||||
| 	if ( bytes_read ) | 	if ( bytes_read ) | ||||||
| @@ -201,19 +209,20 @@ internal GEN_FILE_READ_AT_PROC( _posix_file_read ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_WRITE_AT_PROC( _posix_file_write ) | internal | ||||||
|  | GEN_FILE_WRITE_AT_PROC( _posix_file_write ) | ||||||
| { | { | ||||||
| 	sw  res; | 	ssize  res; | ||||||
| 	s64 curr_offset = 0; | 	s64 curr_offset = 0; | ||||||
| 	_posix_file_seek( fd, 0, ESeekWhence_CURRENT, &curr_offset ); | 	_posix_file_seek( fd, 0, ESeekWhence_CURRENT, &curr_offset ); | ||||||
| 	if ( curr_offset == offset ) | 	if ( curr_offset == offset ) | ||||||
| 	{ | 	{ | ||||||
| 		// NOTE: Writing to stdout et al. doesn't like pwrite for numerous reasons | 		// NOTE: Writing to stdout et al. doesn't like pwrite for numerous reasons | ||||||
| 		res = write( zpl_cast( int ) fd.i, buffer, size ); | 		res = write( scast( int, fd.i), buffer, size ); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		res = pwrite( zpl_cast( int ) fd.i, buffer, size, offset ); | 		res = pwrite( scast( int, fd.i), buffer, size, offset ); | ||||||
| 	} | 	} | ||||||
| 	if ( res < 0 ) | 	if ( res < 0 ) | ||||||
| 		return false; | 		return false; | ||||||
| @@ -222,14 +231,16 @@ internal GEN_FILE_WRITE_AT_PROC( _posix_file_write ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_CLOSE_PROC( _posix_file_close ) | internal | ||||||
|  | GEN_FILE_CLOSE_PROC( _posix_file_close ) | ||||||
| { | { | ||||||
| 	close( fd.i ); | 	close( fd.i ); | ||||||
| } | } | ||||||
|  |  | ||||||
| FileOperations const default_file_operations = { _posix_file_read, _posix_file_write, _posix_file_seek, _posix_file_close }; | FileOperations const default_file_operations = { _posix_file_read, _posix_file_write, _posix_file_seek, _posix_file_close }; | ||||||
|  |  | ||||||
| neverinline GEN_FILE_OPEN_PROC( _posix_file_open ) | neverinline | ||||||
|  | GEN_FILE_OPEN_PROC( _posix_file_open ) | ||||||
| { | { | ||||||
| 	s32 os_mode; | 	s32 os_mode; | ||||||
| 	switch ( mode & GEN_FILE_MODES ) | 	switch ( mode & GEN_FILE_MODES ) | ||||||
| @@ -329,7 +340,7 @@ FileError file_close( FileInfo* f ) | |||||||
| 		return EFileError_INVALID; | 		return EFileError_INVALID; | ||||||
|  |  | ||||||
| 	if ( f->filename ) | 	if ( f->filename ) | ||||||
| 		free( heap(), zpl_cast( char* ) f->filename ); | 		free( heap(), ccast( char*, f->filename )); | ||||||
|  |  | ||||||
| #if defined( GEN_SYSTEM_WINDOWS ) | #if defined( GEN_SYSTEM_WINDOWS ) | ||||||
| 	if ( f->fd.p == INVALID_HANDLE_VALUE ) | 	if ( f->fd.p == INVALID_HANDLE_VALUE ) | ||||||
| @@ -364,14 +375,14 @@ FileError file_close( FileInfo* f ) | |||||||
| FileError file_new( FileInfo* f, FileDescriptor fd, FileOperations ops, char const* filename ) | FileError file_new( FileInfo* f, FileDescriptor fd, FileOperations ops, char const* filename ) | ||||||
| { | { | ||||||
| 	FileError err = EFileError_NONE; | 	FileError err = EFileError_NONE; | ||||||
| 	sw        len = str_len( filename ); | 	ssize        len = str_len( filename ); | ||||||
|  |  | ||||||
| 	f->ops             = ops; | 	f->ops             = ops; | ||||||
| 	f->fd              = fd; | 	f->fd              = fd; | ||||||
| 	f->dir             = nullptr; | 	f->dir             = nullptr; | ||||||
| 	f->last_write_time = 0; | 	f->last_write_time = 0; | ||||||
| 	f->filename        = alloc_array( heap(), char, len + 1 ); | 	f->filename        = alloc_array( heap(), char, len + 1 ); | ||||||
| 	mem_copy( zpl_cast( char* ) f->filename, zpl_cast( char* ) filename, len + 1 ); | 	mem_copy( ccast( char*, f->filename), ccast( char*, filename), len + 1 ); | ||||||
|  |  | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| @@ -430,7 +441,7 @@ FileContents file_read_contents( AllocatorInfo a, b32 zero_terminate, char const | |||||||
|  |  | ||||||
| 	if ( file_open( &file, filepath ) == EFileError_NONE ) | 	if ( file_open( &file, filepath ) == EFileError_NONE ) | ||||||
| 	{ | 	{ | ||||||
| 		sw fsize = zpl_cast( sw ) file_size( &file ); | 		ssize fsize = scast( ssize , file_size( &file )); | ||||||
| 		if ( fsize > 0 ) | 		if ( fsize > 0 ) | ||||||
| 		{ | 		{ | ||||||
| 			result.data = alloc( a, zero_terminate ? fsize + 1 : fsize ); | 			result.data = alloc( a, zero_terminate ? fsize + 1 : fsize ); | ||||||
| @@ -438,7 +449,7 @@ FileContents file_read_contents( AllocatorInfo a, b32 zero_terminate, char const | |||||||
| 			file_read_at( &file, result.data, result.size, 0 ); | 			file_read_at( &file, result.data, result.size, 0 ); | ||||||
| 			if ( zero_terminate ) | 			if ( zero_terminate ) | ||||||
| 			{ | 			{ | ||||||
| 				u8* str      = zpl_cast( u8* ) result.data; | 				u8* str      = rcast( u8*, result.data); | ||||||
| 				str[ fsize ] = '\0'; | 				str[ fsize ] = '\0'; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -452,26 +463,28 @@ struct _memory_fd | |||||||
| { | { | ||||||
| 	u8            magic; | 	u8            magic; | ||||||
| 	u8*           buf;    //< zpl_array OR plain buffer if we can't write | 	u8*           buf;    //< zpl_array OR plain buffer if we can't write | ||||||
| 	sw            cursor; | 	ssize         cursor; | ||||||
| 	AllocatorInfo allocator; | 	AllocatorInfo allocator; | ||||||
|  |  | ||||||
| 	FileStreamFlags flags; | 	FileStreamFlags flags; | ||||||
| 	sw              cap; | 	ssize           cap; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define GEN__FILE_STREAM_FD_MAGIC 37 | #define GEN__FILE_STREAM_FD_MAGIC 37 | ||||||
|  |  | ||||||
| GEN_DEF_INLINE FileDescriptor _file_stream_fd_make( _memory_fd* d ); | FileDescriptor _file_stream_fd_make( _memory_fd* d ); | ||||||
| GEN_DEF_INLINE _memory_fd*    _file_stream_from_fd( FileDescriptor fd ); | _memory_fd*    _file_stream_from_fd( FileDescriptor fd ); | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE FileDescriptor _file_stream_fd_make( _memory_fd* d ) | inline | ||||||
|  | FileDescriptor _file_stream_fd_make( _memory_fd* d ) | ||||||
| { | { | ||||||
| 	FileDescriptor fd = { 0 }; | 	FileDescriptor fd = { 0 }; | ||||||
| 	fd.p              = ( void* )d; | 	fd.p              = ( void* )d; | ||||||
| 	return fd; | 	return fd; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE _memory_fd* _file_stream_from_fd( FileDescriptor fd ) | inline | ||||||
|  | _memory_fd* _file_stream_from_fd( FileDescriptor fd ) | ||||||
| { | { | ||||||
| 	_memory_fd* d = ( _memory_fd* )fd.p; | 	_memory_fd* d = ( _memory_fd* )fd.p; | ||||||
| 	GEN_ASSERT( d->magic == GEN__FILE_STREAM_FD_MAGIC ); | 	GEN_ASSERT( d->magic == GEN__FILE_STREAM_FD_MAGIC ); | ||||||
| @@ -492,7 +505,7 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator ) | |||||||
| 	d->allocator = allocator; | 	d->allocator = allocator; | ||||||
| 	d->flags     = EFileStream_CLONE_WRITABLE; | 	d->flags     = EFileStream_CLONE_WRITABLE; | ||||||
| 	d->cap       = 0; | 	d->cap       = 0; | ||||||
| 	d->buf       = Array<u8>::init( allocator ); | 	d->buf       = array_init<u8>( allocator ); | ||||||
|  |  | ||||||
| 	if ( ! d->buf ) | 	if ( ! d->buf ) | ||||||
| 		return false; | 		return false; | ||||||
| @@ -506,7 +519,7 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw size, FileStreamFlags flags ) | b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize size, FileStreamFlags flags ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_NOT_NULL( file ); | 	GEN_ASSERT_NOT_NULL( file ); | ||||||
| 	_memory_fd* d = ( _memory_fd* )alloc( allocator, size_of( _memory_fd ) ); | 	_memory_fd* d = ( _memory_fd* )alloc( allocator, size_of( _memory_fd ) ); | ||||||
| @@ -518,7 +531,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw siz | |||||||
| 	d->flags     = flags; | 	d->flags     = flags; | ||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = Array<u8>::init_reserve( allocator, size ); | 		Array<u8> arr = array_init_reserve<u8>( allocator, size ); | ||||||
| 		d->buf = arr; | 		d->buf = arr; | ||||||
|  |  | ||||||
| 		if ( ! d->buf ) | 		if ( ! d->buf ) | ||||||
| @@ -527,7 +540,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw siz | |||||||
| 		mem_copy( d->buf, buffer, size ); | 		mem_copy( d->buf, buffer, size ); | ||||||
| 		d->cap = size; | 		d->cap = size; | ||||||
|  |  | ||||||
| 		arr.get_header()->Num = size; | 		get_header(arr)->Num = size; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -543,7 +556,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw siz | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| u8* file_stream_buf( FileInfo* file, sw* size ) | u8* file_stream_buf( FileInfo* file, ssize* size ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_NOT_NULL( file ); | 	GEN_ASSERT_NOT_NULL( file ); | ||||||
| 	_memory_fd* d = _file_stream_from_fd( file->fd ); | 	_memory_fd* d = _file_stream_from_fd( file->fd ); | ||||||
| @@ -552,10 +565,11 @@ u8* file_stream_buf( FileInfo* file, sw* size ) | |||||||
| 	return d->buf; | 	return d->buf; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_SEEK_PROC( _memory_file_seek ) | internal | ||||||
|  | GEN_FILE_SEEK_PROC( _memory_file_seek ) | ||||||
| { | { | ||||||
| 	_memory_fd* d      = _file_stream_from_fd( fd ); | 	_memory_fd* d      = _file_stream_from_fd( fd ); | ||||||
| 	sw          buflen = d->cap; | 	ssize          buflen = d->cap; | ||||||
|  |  | ||||||
| 	if ( whence == ESeekWhence_BEGIN ) | 	if ( whence == ESeekWhence_BEGIN ) | ||||||
| 		d->cursor = 0; | 		d->cursor = 0; | ||||||
| @@ -568,7 +582,8 @@ internal GEN_FILE_SEEK_PROC( _memory_file_seek ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_READ_AT_PROC( _memory_file_read ) | internal | ||||||
|  | GEN_FILE_READ_AT_PROC( _memory_file_read ) | ||||||
| { | { | ||||||
| 	// unused( stop_at_newline ); | 	// unused( stop_at_newline ); | ||||||
| 	_memory_fd* d = _file_stream_from_fd( fd ); | 	_memory_fd* d = _file_stream_from_fd( fd ); | ||||||
| @@ -578,25 +593,26 @@ internal GEN_FILE_READ_AT_PROC( _memory_file_read ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | internal | ||||||
|  | GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | ||||||
| { | { | ||||||
| 	_memory_fd* d = _file_stream_from_fd( fd ); | 	_memory_fd* d = _file_stream_from_fd( fd ); | ||||||
|  |  | ||||||
| 	if ( ! ( d->flags & ( EFileStream_CLONE_WRITABLE | EFileStream_WRITABLE ) ) ) | 	if ( ! ( d->flags & ( EFileStream_CLONE_WRITABLE | EFileStream_WRITABLE ) ) ) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	sw buflen   = d->cap; | 	ssize buflen   = d->cap; | ||||||
| 	sw extralen = max( 0, size - ( buflen - offset ) ); | 	ssize extralen = max( 0, size - ( buflen - offset ) ); | ||||||
| 	sw rwlen    = size - extralen; | 	ssize rwlen    = size - extralen; | ||||||
| 	sw new_cap  = buflen + extralen; | 	ssize new_cap  = buflen + extralen; | ||||||
|  |  | ||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array<u8> arr = { d->buf }; | ||||||
|  |  | ||||||
| 		if ( arr.get_header()->Capacity < new_cap ) | 		if ( get_header(arr)->Capacity < usize(new_cap) ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( ! arr.grow( ( s64 )( new_cap ) ) ) | 			if ( ! grow( arr, ( s64 )( new_cap ) ) ) | ||||||
| 				return false; | 				return false; | ||||||
| 			d->buf = arr; | 			d->buf = arr; | ||||||
| 		} | 		} | ||||||
| @@ -610,7 +626,7 @@ internal GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
|  |  | ||||||
| 		mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen ); | 		mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen ); | ||||||
| 		d->cap = new_cap; | 		d->cap = new_cap; | ||||||
| 		arr.get_header()->Capacity = new_cap; | 		get_header(arr)->Capacity = new_cap; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -622,7 +638,8 @@ internal GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal GEN_FILE_CLOSE_PROC( _memory_file_close ) | internal | ||||||
|  | GEN_FILE_CLOSE_PROC( _memory_file_close ) | ||||||
| { | { | ||||||
| 	_memory_fd*   d         = _file_stream_from_fd( fd ); | 	_memory_fd*   d         = _file_stream_from_fd( fd ); | ||||||
| 	AllocatorInfo allocator = d->allocator; | 	AllocatorInfo allocator = d->allocator; | ||||||
| @@ -630,7 +647,7 @@ internal GEN_FILE_CLOSE_PROC( _memory_file_close ) | |||||||
| 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | 	if ( d->flags & EFileStream_CLONE_WRITABLE ) | ||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array<u8> arr = { d->buf }; | ||||||
| 		arr.free(); | 		free(arr); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free( allocator, d ); | 	free( allocator, d ); | ||||||
|   | |||||||
| @@ -48,8 +48,8 @@ union FileDescriptor | |||||||
| typedef struct FileOperations FileOperations; | typedef struct FileOperations FileOperations; | ||||||
|  |  | ||||||
| #define GEN_FILE_OPEN_PROC( name )     FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename ) | #define GEN_FILE_OPEN_PROC( name )     FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename ) | ||||||
| #define GEN_FILE_READ_AT_PROC( name )  b32 name( FileDescriptor fd, void* buffer, sw size, s64 offset, sw* bytes_read, b32 stop_at_newline ) | #define GEN_FILE_READ_AT_PROC( name )  b32 name( FileDescriptor fd, void* buffer, ssize size, s64 offset, ssize* bytes_read, b32 stop_at_newline ) | ||||||
| #define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, void const* buffer, sw size, s64 offset, sw* bytes_written ) | #define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, void const* buffer, ssize size, s64 offset, ssize* bytes_written ) | ||||||
| #define GEN_FILE_SEEK_PROC( name )     b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset ) | #define GEN_FILE_SEEK_PROC( name )     b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset ) | ||||||
| #define GEN_FILE_CLOSE_PROC( name )    void name( FileDescriptor fd ) | #define GEN_FILE_CLOSE_PROC( name )    void name( FileDescriptor fd ) | ||||||
|  |  | ||||||
| @@ -161,7 +161,7 @@ FileError file_open_mode( FileInfo* file, FileMode mode, char const* filename ); | |||||||
| 	* @param  buffer Buffer to read to | 	* @param  buffer Buffer to read to | ||||||
| 	* @param  size   Size to read | 	* @param  size   Size to read | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_read( FileInfo* file, void* buffer, sw size ); | b32 file_read( FileInfo* file, void* buffer, ssize size ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Reads file at a specific offset | 	* Reads file at a specific offset | ||||||
| @@ -171,7 +171,7 @@ GEN_DEF_INLINE b32 file_read( FileInfo* file, void* buffer, sw size ); | |||||||
| 	* @param  offset     Offset to read from | 	* @param  offset     Offset to read from | ||||||
| 	* @param  bytes_read How much data we've actually read | 	* @param  bytes_read How much data we've actually read | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_read_at( FileInfo* file, void* buffer, sw size, s64 offset ); | b32 file_read_at( FileInfo* file, void* buffer, ssize size, s64 offset ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Reads file safely | 	* Reads file safely | ||||||
| @@ -181,13 +181,13 @@ GEN_DEF_INLINE b32 file_read_at( FileInfo* file, void* buffer, sw size, s64 offs | |||||||
| 	* @param  offset     Offset to read from | 	* @param  offset     Offset to read from | ||||||
| 	* @param  bytes_read How much data we've actually read | 	* @param  bytes_read How much data we've actually read | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_read_at_check( FileInfo* file, void* buffer, sw size, s64 offset, sw* bytes_read ); | b32 file_read_at_check( FileInfo* file, void* buffer, ssize size, s64 offset, ssize* bytes_read ); | ||||||
|  |  | ||||||
| struct FileContents | struct FileContents | ||||||
| { | { | ||||||
| 	AllocatorInfo allocator; | 	AllocatorInfo allocator; | ||||||
| 	void*         data; | 	void*         data; | ||||||
| 	sw            size; | 	ssize            size; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| constexpr b32 zero_terminate    = true; | constexpr b32 zero_terminate    = true; | ||||||
| @@ -214,20 +214,20 @@ s64 file_size( FileInfo* file ); | |||||||
| 	* @param  file | 	* @param  file | ||||||
| 	* @param  offset Offset to seek to | 	* @param  offset Offset to seek to | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE s64 file_seek( FileInfo* file, s64 offset ); | s64 file_seek( FileInfo* file, s64 offset ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Seeks the file cursor to the end of the file | 	* Seeks the file cursor to the end of the file | ||||||
| 	* @param  file | 	* @param  file | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE s64 file_seek_to_end( FileInfo* file ); | s64 file_seek_to_end( FileInfo* file ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Returns the length from the beginning of the file we've read so far | 	* Returns the length from the beginning of the file we've read so far | ||||||
| 	* @param  file | 	* @param  file | ||||||
| 	* @return      Our current position in file | 	* @return      Our current position in file | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE s64 file_tell( FileInfo* file ); | s64 file_tell( FileInfo* file ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Writes to a file | 	* Writes to a file | ||||||
| @@ -235,7 +235,7 @@ GEN_DEF_INLINE s64 file_tell( FileInfo* file ); | |||||||
| 	* @param  buffer Buffer to read from | 	* @param  buffer Buffer to read from | ||||||
| 	* @param  size   Size to read | 	* @param  size   Size to read | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_write( FileInfo* file, void const* buffer, sw size ); | b32 file_write( FileInfo* file, void const* buffer, ssize size ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Writes to file at a specific offset | 	* Writes to file at a specific offset | ||||||
| @@ -245,7 +245,7 @@ GEN_DEF_INLINE b32 file_write( FileInfo* file, void const* buffer, sw size ); | |||||||
| 	* @param  offset        Offset to write to | 	* @param  offset        Offset to write to | ||||||
| 	* @param  bytes_written How much data we've actually written | 	* @param  bytes_written How much data we've actually written | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_write_at( FileInfo* file, void const* buffer, sw size, s64 offset ); | b32 file_write_at( FileInfo* file, void const* buffer, ssize size, s64 offset ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Writes to file safely | 	* Writes to file safely | ||||||
| @@ -255,86 +255,7 @@ GEN_DEF_INLINE b32 file_write_at( FileInfo* file, void const* buffer, sw size, s | |||||||
| 	* @param  offset        Offset to write to | 	* @param  offset        Offset to write to | ||||||
| 	* @param  bytes_written How much data we've actually written | 	* @param  bytes_written How much data we've actually written | ||||||
| 	*/ | 	*/ | ||||||
| GEN_DEF_INLINE b32 file_write_at_check( FileInfo* file, void const* buffer, sw size, s64 offset, sw* bytes_written ); | b32 file_write_at_check( FileInfo* file, void const* buffer, ssize size, s64 offset, ssize* bytes_written ); | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s64 file_seek( FileInfo* f, s64 offset ) |  | ||||||
| { |  | ||||||
| 	s64 new_offset = 0; |  | ||||||
|  |  | ||||||
| 	if ( ! f->ops.read_at ) |  | ||||||
| 		f->ops = default_file_operations; |  | ||||||
|  |  | ||||||
| 	f->ops.seek( f->fd, offset, ESeekWhence_BEGIN, &new_offset ); |  | ||||||
|  |  | ||||||
| 	return new_offset; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s64 file_seek_to_end( FileInfo* f ) |  | ||||||
| { |  | ||||||
| 	s64 new_offset = 0; |  | ||||||
|  |  | ||||||
| 	if ( ! f->ops.read_at ) |  | ||||||
| 		f->ops = default_file_operations; |  | ||||||
|  |  | ||||||
| 	f->ops.seek( f->fd, 0, ESeekWhence_END, &new_offset ); |  | ||||||
|  |  | ||||||
| 	return new_offset; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s64 file_tell( FileInfo* f ) |  | ||||||
| { |  | ||||||
| 	s64 new_offset = 0; |  | ||||||
|  |  | ||||||
| 	if ( ! f->ops.read_at ) |  | ||||||
| 		f->ops = default_file_operations; |  | ||||||
|  |  | ||||||
| 	f->ops.seek( f->fd, 0, ESeekWhence_CURRENT, &new_offset ); |  | ||||||
|  |  | ||||||
| 	return new_offset; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 file_read( FileInfo* f, void* buffer, sw size ) |  | ||||||
| { |  | ||||||
| 	s64 cur_offset = file_tell( f ); |  | ||||||
| 	b32 result     = file_read_at( f, buffer, size, file_tell( f ) ); |  | ||||||
| 	file_seek( f, cur_offset + size ); |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 file_read_at( FileInfo* f, void* buffer, sw size, s64 offset ) |  | ||||||
| { |  | ||||||
| 	return file_read_at_check( f, buffer, size, offset, NULL ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 file_read_at_check( FileInfo* f, void* buffer, sw size, s64 offset, sw* bytes_read ) |  | ||||||
| { |  | ||||||
| 	if ( ! f->ops.read_at ) |  | ||||||
| 		f->ops = default_file_operations; |  | ||||||
| 	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 ) |  | ||||||
| { |  | ||||||
| 	s64 cur_offset = file_tell( f ); |  | ||||||
| 	b32 result     = file_write_at( f, buffer, size, file_tell( f ) ); |  | ||||||
|  |  | ||||||
| 	file_seek( f, cur_offset + size ); |  | ||||||
|  |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 file_write_at( FileInfo* f, void const* buffer, sw size, s64 offset ) |  | ||||||
| { |  | ||||||
| 	return file_write_at_check( f, buffer, size, offset, NULL ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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 ) |  | ||||||
| 		f->ops = default_file_operations; |  | ||||||
|  |  | ||||||
| 	return f->ops.write_at( f->fd, buffer, size, offset, bytes_written ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| enum FileStreamFlags : u32 | enum FileStreamFlags : u32 | ||||||
| { | { | ||||||
| @@ -361,15 +282,103 @@ b8 file_stream_new( FileInfo* file, AllocatorInfo allocator ); | |||||||
| 	* @param  size     Buffer's size | 	* @param  size     Buffer's size | ||||||
| 	* @param  flags | 	* @param  flags | ||||||
| 	*/ | 	*/ | ||||||
| b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, sw size, FileStreamFlags flags ); | b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize size, FileStreamFlags flags ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* Retrieves the stream's underlying buffer and buffer size. | 	* Retrieves the stream's underlying buffer and buffer size. | ||||||
| 	* @param file memory stream | 	* @param file memory stream | ||||||
| 	* @param size (Optional) buffer size | 	* @param size (Optional) buffer size | ||||||
| 	*/ | 	*/ | ||||||
| u8* file_stream_buf( FileInfo* file, sw* size ); | u8* file_stream_buf( FileInfo* file, ssize* size ); | ||||||
|  |  | ||||||
| extern FileOperations const memory_file_operations; | extern FileOperations const memory_file_operations; | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | s64 file_seek( FileInfo* f, s64 offset ) | ||||||
|  | { | ||||||
|  | 	s64 new_offset = 0; | ||||||
|  |  | ||||||
|  | 	if ( ! f->ops.read_at ) | ||||||
|  | 		f->ops = default_file_operations; | ||||||
|  |  | ||||||
|  | 	f->ops.seek( f->fd, offset, ESeekWhence_BEGIN, &new_offset ); | ||||||
|  |  | ||||||
|  | 	return new_offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | s64 file_seek_to_end( FileInfo* f ) | ||||||
|  | { | ||||||
|  | 	s64 new_offset = 0; | ||||||
|  |  | ||||||
|  | 	if ( ! f->ops.read_at ) | ||||||
|  | 		f->ops = default_file_operations; | ||||||
|  |  | ||||||
|  | 	f->ops.seek( f->fd, 0, ESeekWhence_END, &new_offset ); | ||||||
|  |  | ||||||
|  | 	return new_offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | s64 file_tell( FileInfo* f ) | ||||||
|  | { | ||||||
|  | 	s64 new_offset = 0; | ||||||
|  |  | ||||||
|  | 	if ( ! f->ops.read_at ) | ||||||
|  | 		f->ops = default_file_operations; | ||||||
|  |  | ||||||
|  | 	f->ops.seek( f->fd, 0, ESeekWhence_CURRENT, &new_offset ); | ||||||
|  |  | ||||||
|  | 	return new_offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_read( FileInfo* f, void* buffer, ssize size ) | ||||||
|  | { | ||||||
|  | 	s64 cur_offset = file_tell( f ); | ||||||
|  | 	b32 result     = file_read_at( f, buffer, size, file_tell( f ) ); | ||||||
|  | 	file_seek( f, cur_offset + size ); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_read_at( FileInfo* f, void* buffer, ssize size, s64 offset ) | ||||||
|  | { | ||||||
|  | 	return file_read_at_check( f, buffer, size, offset, NULL ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_read_at_check( FileInfo* f, void* buffer, ssize size, s64 offset, ssize* bytes_read ) | ||||||
|  | { | ||||||
|  | 	if ( ! f->ops.read_at ) | ||||||
|  | 		f->ops = default_file_operations; | ||||||
|  | 	return f->ops.read_at( f->fd, buffer, size, offset, bytes_read, false ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_write( FileInfo* f, void const* buffer, ssize size ) | ||||||
|  | { | ||||||
|  | 	s64 cur_offset = file_tell( f ); | ||||||
|  | 	b32 result     = file_write_at( f, buffer, size, file_tell( f ) ); | ||||||
|  |  | ||||||
|  | 	file_seek( f, cur_offset + size ); | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_write_at( FileInfo* f, void const* buffer, ssize size, s64 offset ) | ||||||
|  | { | ||||||
|  | 	return file_write_at_check( f, buffer, size, offset, NULL ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 file_write_at_check( FileInfo* f, void const* buffer, ssize size, s64 offset, ssize* bytes_written ) | ||||||
|  | { | ||||||
|  | 	if ( ! f->ops.read_at ) | ||||||
|  | 		f->ops = default_file_operations; | ||||||
|  |  | ||||||
|  | 	return f->ops.write_at( f->fd, buffer, size, offset, bytes_written ); | ||||||
|  | } | ||||||
|  |  | ||||||
| #pragma endregion File Handling | #pragma endregion File Handling | ||||||
|   | |||||||
| @@ -27,11 +27,11 @@ global u32 const _crc32_table[ 256 ] = { | |||||||
| 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, | 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| u32 crc32( void const* data, sw len ) | u32 crc32( void const* data, ssize len ) | ||||||
| { | { | ||||||
| 	sw        remaining; | 	ssize        remaining; | ||||||
| 	u32       result = ~( zpl_cast( u32 ) 0 ); | 	u32       result = ~( scast( u32, 0) ); | ||||||
| 	u8 const* c      = zpl_cast( u8 const* ) data; | 	u8 const* c      = rcast( u8 const*, data); | ||||||
| 	for ( remaining = len; remaining--; c++ ) | 	for ( remaining = len; remaining--; c++ ) | ||||||
| 		result = ( result >> 8 ) ^ ( _crc32_table[ ( result ^ *c ) & 0xff ] ); | 		result = ( result >> 8 ) ^ ( _crc32_table[ ( result ^ *c ) & 0xff ] ); | ||||||
| 	return ~result; | 	return ~result; | ||||||
| @@ -77,11 +77,11 @@ global u64 const _crc64_table[ 256 ] = { | |||||||
| 	0xa6df411fbfb21ca3ull, 0xdc0731d78f8795daull, 0x536fa08fdfd90e51ull, 0x29b7d047efec8728ull, | 	0xa6df411fbfb21ca3ull, 0xdc0731d78f8795daull, 0x536fa08fdfd90e51ull, 0x29b7d047efec8728ull, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| u64 crc64( void const* data, sw len ) | u64 crc64( void const* data, ssize len ) | ||||||
| { | { | ||||||
| 	sw        remaining; | 	ssize        remaining; | ||||||
| 	u64       result = ( zpl_cast( u64 ) 0 ); | 	u64       result = ( scast( u64, 0) ); | ||||||
| 	u8 const* c      = zpl_cast( u8 const* ) data; | 	u8 const* c      = rcast( u8 const*, data); | ||||||
| 	for ( remaining = len; remaining--; c++ ) | 	for ( remaining = len; remaining--; c++ ) | ||||||
| 		result = ( result >> 8 ) ^ ( _crc64_table[ ( result ^ *c ) & 0xff ] ); | 		result = ( result >> 8 ) ^ ( _crc64_table[ ( result ^ *c ) & 0xff ] ); | ||||||
| 	return result; | 	return result; | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| #pragma region Hashing | #pragma region Hashing | ||||||
|  |  | ||||||
| u32 crc32( void const* data, sw len ); | u32 crc32( void const* data, ssize len ); | ||||||
| u64 crc64( void const* data, sw len ); | u64 crc64( void const* data, ssize len ); | ||||||
|  |  | ||||||
| #pragma endregion Hashing | #pragma endregion Hashing | ||||||
|   | |||||||
| @@ -1,52 +1,92 @@ | |||||||
| #ifdef GEN_INTELLISENSE_DIRECTIVES | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
| #	pragma once | #   pragma once | ||||||
| #	include "header_start.hpp" |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region Macros | #pragma region Macros | ||||||
|  |  | ||||||
| #define zpl_cast( Type ) ( Type ) | #ifndef global | ||||||
|  |  | ||||||
| // Keywords |  | ||||||
|  |  | ||||||
| #define global        static    // Global variables | #define global        static    // Global variables | ||||||
|  | #endif | ||||||
|  | #ifndef internal | ||||||
| #define internal      static    // Internal linkage | #define internal      static    // Internal linkage | ||||||
|  | #endif | ||||||
|  | #ifndef local_persist | ||||||
| #define local_persist static    // Local Persisting variables | #define local_persist static    // Local Persisting variables | ||||||
|  |  | ||||||
| #ifdef GEN_COMPILER_MSVC |  | ||||||
| #	define forceinline __forceinline |  | ||||||
| #	define neverinline __declspec( noinline ) |  | ||||||
| #elif defined(GEN_COMPILER_GCC) |  | ||||||
| #	define forceinline inline __attribute__((__always_inline__)) |  | ||||||
| #	define neverinline __attribute__( ( __noinline__ ) ) |  | ||||||
| #elif defined(GEN_COMPILER_CLANG) |  | ||||||
| #if __has_attribute(__always_inline__) |  | ||||||
| #	define forceinline inline __attribute__((__always_inline__)) |  | ||||||
| #	define neverinline __attribute__( ( __noinline__ ) ) |  | ||||||
| #else |  | ||||||
| #	define forceinline |  | ||||||
| #	define neverinline |  | ||||||
| #endif |  | ||||||
| #else |  | ||||||
| #	define forceinline |  | ||||||
| #	define neverinline |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Bits | #ifndef api_c | ||||||
|  | #define api_c extern "C" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef bit | ||||||
| #define bit( Value )                             ( 1 << Value ) | #define bit( Value )                             ( 1 << Value ) | ||||||
| #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) | #define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // Casting | #if ! GEN_C_COMPILER | ||||||
|  | #	ifndef ccast | ||||||
|  | #	define ccast( type, value ) ( const_cast< type >( (value) ) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef pcast | ||||||
|  | #	define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef rcast | ||||||
|  | #	define rcast( type, value ) reinterpret_cast< type >( value ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef scast | ||||||
|  | #	define scast( type, value ) static_cast< type >( value ) | ||||||
|  | #	endif | ||||||
|  | #else | ||||||
|  | #	ifndef ccast | ||||||
|  | #	define ccast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef pcast | ||||||
|  | #	define pcast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef rcast | ||||||
|  | #	define rcast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #	ifndef scast | ||||||
|  | #	define scast( type, value ) ( (type)(value) ) | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #define ccast( Type, Value ) ( * const_cast< Type* >( & (Value) ) ) | #ifndef stringize | ||||||
| #define pcast( Type, Value ) ( * reinterpret_cast< Type* >( & ( Value ) ) ) | #define stringize_va( ... ) #__VA_ARGS__ | ||||||
| #define rcast( Type, Value ) reinterpret_cast< Type >( Value ) | #define stringize( ... )    stringize_va( __VA_ARGS__ ) | ||||||
| #define scast( Type, Value ) static_cast< Type >( Value ) | #endif | ||||||
|  |  | ||||||
| // Num Arguments (Varadics) | #ifndef do_once | ||||||
| // #if defined(__GNUC__) || defined(__clang__) | #define do_once( statement ) for ( local_persist b32 once = true; once; once = false, (statement) ) | ||||||
| // Supports 0-50 arguments |  | ||||||
|  | #define do_once_start      \ | ||||||
|  | 	do                     \ | ||||||
|  | 	{                      \ | ||||||
|  | 		local_persist      \ | ||||||
|  | 		bool done = false; \ | ||||||
|  | 		if ( done )        \ | ||||||
|  | 			break;         \ | ||||||
|  | 		done = true; | ||||||
|  |  | ||||||
|  | #define do_once_end        \ | ||||||
|  | 	}                      \ | ||||||
|  | 	while(0); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef labeled_scope_start | ||||||
|  | #define labeled_scope_start if ( false ) { | ||||||
|  | #define labeled_scope_end   } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef         compiler_decorated_func_name | ||||||
|  | #   ifdef COMPILER_CLANG | ||||||
|  | #       define  compiler_decorated_func_name __PRETTY_NAME__ | ||||||
|  | #   elif defined(COMPILER_MSVC) | ||||||
|  | #   	define compiler_decorated_func_name __FUNCDNAME__ | ||||||
|  | #   endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef num_args_impl | ||||||
| #define num_args_impl( _0,                                 \ | #define num_args_impl( _0,                                 \ | ||||||
| 		_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10,   \ | 		_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10,   \ | ||||||
| 		_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,  \ | 		_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,  \ | ||||||
| @@ -61,7 +101,7 @@ | |||||||
| 		N, ...                                             \ | 		N, ...                                             \ | ||||||
| 	) N | 	) N | ||||||
|  |  | ||||||
| 	// ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) | // ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) | ||||||
| #define num_args(...)                            \ | #define num_args(...)                            \ | ||||||
| 	num_args_impl(_, ## __VA_ARGS__,             \ | 	num_args_impl(_, ## __VA_ARGS__,             \ | ||||||
| 		100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \ | 		100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \ | ||||||
| @@ -76,93 +116,103 @@ | |||||||
| 		 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, \ | 		 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, \ | ||||||
| 		 0                                       \ | 		 0                                       \ | ||||||
| 	) | 	) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // #else | #ifndef clamp | ||||||
| // This doesn't work on latest msvc so I had to use /Zc:preprocessor flag. |  | ||||||
|  |  | ||||||
| // Supports 1-50 arguments |  | ||||||
| // #define num_args_impl(                                  \ |  | ||||||
| // 		_1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, _10,   \ |  | ||||||
| // 		_11, _12, _13, _14, _15, _16, _17, _18, _19, _20,  \ |  | ||||||
| // 		_21, _22, _23, _24, _25, _26, _27, _28, _29, _30,  \ |  | ||||||
| // 		_31, _32, _33, _34, _35, _36, _37, _38, _39, _40,  \ |  | ||||||
| // 		_41, _42, _43, _44, _45, _46, _47, _48, _49, _50,  \ |  | ||||||
| // 		_51, _52, _53, _54, _55, _56, _57, _58, _59, _60,  \ |  | ||||||
| // 		_61, _62, _63, _64, _65, _66, _67, _68, _69, _70,  \ |  | ||||||
| // 		_71, _72, _73, _74, _75, _76, _77, _78, _79, _80,  \ |  | ||||||
| // 		_81, _82, _83, _84, _85, _86, _87, _88, _89, _90,  \ |  | ||||||
| // 		_91, _92, _93, _94, _95, _96, _97, _98, _99, _100, \ |  | ||||||
| // 		N, ...                                             \ |  | ||||||
| // 	) N |  | ||||||
|  |  | ||||||
| // #define num_args(...)                         \ |  | ||||||
| // 	num_args_impl( __VA_ARGS__,                  \ |  | ||||||
| // 		100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \ |  | ||||||
| // 		 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, \ |  | ||||||
| // 		 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, \ |  | ||||||
| // 		 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \ |  | ||||||
| // 		 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ |  | ||||||
| // 		 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ |  | ||||||
| // 		 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ |  | ||||||
| // 		 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ |  | ||||||
| // 		 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ |  | ||||||
| // 		 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ |  | ||||||
| // 		 10,  9,  8,  7,  6,  5,  4,  3,  2,  1  \ |  | ||||||
| // 	) |  | ||||||
| // #endif |  | ||||||
|  |  | ||||||
| // Stringizing |  | ||||||
| #define stringize_va( ... ) #__VA_ARGS__ |  | ||||||
| #define stringize( ... )    stringize_va( __VA_ARGS__ ) |  | ||||||
|  |  | ||||||
| // Function do once |  | ||||||
|  |  | ||||||
| #define do_once()          \ |  | ||||||
| 	do                     \ |  | ||||||
| 	{                      \ |  | ||||||
| 		static             \ |  | ||||||
| 		bool Done = false; \ |  | ||||||
| 		if ( Done )        \ |  | ||||||
| 			return;        \ |  | ||||||
| 		Done = true;       \ |  | ||||||
| 	}                      \ |  | ||||||
| 	while(0) |  | ||||||
|  |  | ||||||
| #define do_once_start      \ |  | ||||||
| 	do                     \ |  | ||||||
| 	{                      \ |  | ||||||
| 		static             \ |  | ||||||
| 		bool Done = false; \ |  | ||||||
| 		if ( Done )        \ |  | ||||||
| 			break;         \ |  | ||||||
| 		Done = true; |  | ||||||
|  |  | ||||||
| #define do_once_end        \ |  | ||||||
| 	}                      \ |  | ||||||
| 	while(0); |  | ||||||
|  |  | ||||||
| #define labeled_scope_start if ( false ) { |  | ||||||
| #define labeled_scope_end   } |  | ||||||
|  |  | ||||||
| #define clamp( x, lower, upper )      min( max( ( x ), ( lower ) ), ( upper ) ) | #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 ] ) ) ) ) ) | #endif | ||||||
|  | #ifndef count_of | ||||||
|  | #define count_of( x )                 ( ( size_of( x ) / size_of( 0 [ x ] ) ) / ( ( ssize )( ! ( size_of( x ) % size_of( 0 [ x ] ) ) ) ) ) | ||||||
|  | #endif | ||||||
|  | #ifndef is_between | ||||||
| #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 ) ) | #endif | ||||||
| #define min( a, b )                   ( ( a ) < ( b ) ? ( a ) : ( b ) ) | #ifndef size_of | ||||||
| #define size_of( x )                  ( sw )( sizeof( x ) ) | #define size_of( x )                  ( ssize )( sizeof( x ) ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if defined( _MSC_VER ) || defined( GEN_COMPILER_TINYC ) | #ifndef max | ||||||
| #	define offset_of( Type, element ) ( ( GEN_NS( gen_sw ) ) & ( ( ( Type* )0 )->element ) ) | #define max( a, b ) ( (a > b) ? (a) : (b) ) | ||||||
|  | #endif | ||||||
|  | #ifndef min | ||||||
|  | #define min( a, b ) ( (a < b) ? (a) : (b) ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_MSVC || GEN_COMPILER_TINYC | ||||||
|  | #	define offset_of( Type, element ) ( ( GEN_NS( ssize ) ) & ( ( ( Type* )0 )->element ) ) | ||||||
| #else | #else | ||||||
| #	define offset_of( Type, element ) __builtin_offsetof( Type, element ) | #	define offset_of( Type, element ) __builtin_offsetof( Type, element ) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| template< class Type > | #ifndef        forceinline | ||||||
| void swap( Type& a, Type& b ) | #	if GEN_COMPILER_MSVC | ||||||
| { | #		define forceinline __forceinline | ||||||
| 	Type tmp = a; | #		define neverinline __declspec( noinline ) | ||||||
| 	a = b; | #	elif GEN_COMPILER_GCC | ||||||
| 	b = tmp; | #		define forceinline inline __attribute__((__always_inline__)) | ||||||
| } | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
|  | #	elif GEN_COMPILER_CLANG | ||||||
|  | #	if __has_attribute(__always_inline__) | ||||||
|  | #		define forceinline inline __attribute__((__always_inline__)) | ||||||
|  | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
|  | #	else | ||||||
|  | #		define forceinline | ||||||
|  | #		define neverinline | ||||||
|  | #	endif | ||||||
|  | #	else | ||||||
|  | #		define forceinline | ||||||
|  | #		define neverinline | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef        neverinline | ||||||
|  | #	if GEN_COMPILER_MSVC | ||||||
|  | #		define neverinline __declspec( noinline ) | ||||||
|  | #	elif GEN_COMPILER_GCC | ||||||
|  | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
|  | #	elif GEN_COMPILER_CLANG | ||||||
|  | #	if __has_attribute(__always_inline__) | ||||||
|  | #		define neverinline __attribute__( ( __noinline__ ) ) | ||||||
|  | #	else | ||||||
|  | #		define neverinline | ||||||
|  | #	endif | ||||||
|  | #	else | ||||||
|  | #		define neverinline | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if !defined(GEN_SUPPORT_CPP_MEMBER_FEATURES) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L) | ||||||
|  | #	define GEN_SUPPORT_CPP_MEMBER_FEATURES 0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if !defined(typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L) | ||||||
|  | #	if ! GEN_COMPILER_C | ||||||
|  | #		define typeof decltype | ||||||
|  | #	elif defined(_MSC_VER) | ||||||
|  | #		define typeof(x) __typeof(x) | ||||||
|  | #	elif defined(__GNUC__) || defined(__clang__) | ||||||
|  | #		define typeof(x) __typeof__(x) | ||||||
|  | #	else | ||||||
|  | #		error "Compiler not supported" | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // This is intended to only really be used internally or with the C-library variant | ||||||
|  | // C++ users can just use the for-range directly. | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #	define foreach(Type, entry_id, iterable) for ( Type entry_id = begin(iterable); entry_id != end(iterable); entry_id = next(iterable, entry_id) ) | ||||||
|  | #else | ||||||
|  | #	define foreach(Type, entry_id, iterable) for ( Type entry_id : iterable ) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #	if __STDC_VERSION__ >= 202311L | ||||||
|  | #		define enum_underlying(type) : type | ||||||
|  | #	else | ||||||
|  | #		define enum_underlying(type) | ||||||
|  | #   endif | ||||||
|  | #else | ||||||
|  | #	define enum_underlying(type) : type | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Macros | #pragma endregion Macros | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
|  |  | ||||||
| #pragma region Memory | #pragma region Memory | ||||||
|  |  | ||||||
| void* mem_copy( void* dest, void const* source, sw n ) | void* mem_copy( void* dest, void const* source, ssize n ) | ||||||
| { | { | ||||||
| 	if ( dest == NULL ) | 	if ( dest == NULL ) | ||||||
| 	{ | 	{ | ||||||
| @@ -15,25 +15,25 @@ void* mem_copy( void* dest, void const* source, sw n ) | |||||||
| 	return memcpy( dest, source, n ); | 	return memcpy( dest, source, n ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void const* mem_find( void const* data, u8 c, sw n ) | void const* mem_find( void const* data, u8 c, ssize n ) | ||||||
| { | { | ||||||
| 	u8 const* s = zpl_cast( u8 const* ) data; | 	u8 const* s = rcast( u8 const*, data); | ||||||
| 	while ( ( zpl_cast( uptr ) s & ( sizeof( uw ) - 1 ) ) && n && *s != c ) | 	while ( ( rcast( uptr, s) & ( sizeof( usize ) - 1 ) ) && n && *s != c ) | ||||||
| 	{ | 	{ | ||||||
| 		s++; | 		s++; | ||||||
| 		n--; | 		n--; | ||||||
| 	} | 	} | ||||||
| 	if ( n && *s != c ) | 	if ( n && *s != c ) | ||||||
| 	{ | 	{ | ||||||
| 		sw const* w; | 		ssize const* w; | ||||||
| 		sw        k = GEN__ONES * c; | 		ssize        k = GEN__ONES * c; | ||||||
| 		w           = zpl_cast( sw const* ) s; | 		w           = rcast( ssize const*, s); | ||||||
| 		while ( n >= size_of( sw ) && ! GEN__HAS_ZERO( *w ^ k ) ) | 		while ( n >= size_of( ssize ) && ! GEN__HAS_ZERO( *w ^ k ) ) | ||||||
| 		{ | 		{ | ||||||
| 			w++; | 			w++; | ||||||
| 			n -= size_of( sw ); | 			n -= size_of( ssize ); | ||||||
| 		} | 		} | ||||||
| 		s = zpl_cast( u8 const* ) w; | 		s = rcast( u8 const*, w); | ||||||
| 		while ( n && *s != c ) | 		while ( n && *s != c ) | ||||||
| 		{ | 		{ | ||||||
| 			s++; | 			s++; | ||||||
| @@ -41,7 +41,7 @@ void const* mem_find( void const* data, u8 c, sw n ) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return n ? zpl_cast( void const* ) s : NULL; | 	return n ? rcast( void const*, s ) : NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| #define GEN_HEAP_STATS_MAGIC 0xDEADC0DE | #define GEN_HEAP_STATS_MAGIC 0xDEADC0DE | ||||||
| @@ -49,8 +49,8 @@ void const* mem_find( void const* data, u8 c, sw n ) | |||||||
| struct _heap_stats | struct _heap_stats | ||||||
| { | { | ||||||
| 	u32 magic; | 	u32 magic; | ||||||
| 	sw  used_memory; | 	ssize  used_memory; | ||||||
| 	sw  alloc_count; | 	ssize  alloc_count; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| global _heap_stats _heap_stats_info; | global _heap_stats _heap_stats_info; | ||||||
| @@ -61,13 +61,13 @@ void heap_stats_init( void ) | |||||||
| 	_heap_stats_info.magic = GEN_HEAP_STATS_MAGIC; | 	_heap_stats_info.magic = GEN_HEAP_STATS_MAGIC; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw heap_stats_used_memory( void ) | ssize heap_stats_used_memory( void ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call heap_stats_init first!" ); | 	GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call heap_stats_init first!" ); | ||||||
| 	return _heap_stats_info.used_memory; | 	return _heap_stats_info.used_memory; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw heap_stats_alloc_count( void ) | ssize heap_stats_alloc_count( void ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call heap_stats_init first!" ); | 	GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call heap_stats_init first!" ); | ||||||
| 	return _heap_stats_info.alloc_count; | 	return _heap_stats_info.alloc_count; | ||||||
| @@ -82,11 +82,11 @@ void heap_stats_check( void ) | |||||||
|  |  | ||||||
| struct _heap_alloc_info | struct _heap_alloc_info | ||||||
| { | { | ||||||
| 	sw    size; | 	ssize    size; | ||||||
| 	void* physical_start; | 	void* physical_start; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) | void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	void* ptr = NULL; | 	void* ptr = NULL; | ||||||
| 	// unused( allocator_data ); | 	// unused( allocator_data ); | ||||||
| @@ -95,16 +95,16 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw ali | |||||||
| 		alignment = GEN_DEFAULT_MEMORY_ALIGNMENT; | 		alignment = GEN_DEFAULT_MEMORY_ALIGNMENT; | ||||||
|  |  | ||||||
| #ifdef GEN_HEAP_ANALYSIS | #ifdef GEN_HEAP_ANALYSIS | ||||||
| 	sw alloc_info_size      = size_of( _heap_alloc_info ); | 	ssize alloc_info_size      = size_of( _heap_alloc_info ); | ||||||
| 	sw alloc_info_remainder = ( alloc_info_size % alignment ); | 	ssize alloc_info_remainder = ( alloc_info_size % alignment ); | ||||||
| 	sw track_size           = max( alloc_info_size, alignment ) + alloc_info_remainder; | 	ssize track_size           = max( alloc_info_size, alignment ) + alloc_info_remainder; | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| 	{ | 	{ | ||||||
| 		case EAllocation_FREE : | 		case EAllocation_FREE : | ||||||
| 			{ | 			{ | ||||||
| 				if ( ! old_memory ) | 				if ( ! old_memory ) | ||||||
| 					break; | 					break; | ||||||
| 				_heap_alloc_info* alloc_info  = zpl_cast( _heap_alloc_info* ) old_memory - 1; | 				_heap_alloc_info* alloc_info  = rcast( _heap_alloc_info*, old_memory) - 1; | ||||||
| 				_heap_stats_info.used_memory -= alloc_info->size; | 				_heap_stats_info.used_memory -= alloc_info->size; | ||||||
| 				_heap_stats_info.alloc_count--; | 				_heap_stats_info.alloc_count--; | ||||||
| 				old_memory = alloc_info->physical_start; | 				old_memory = alloc_info->physical_start; | ||||||
| @@ -195,11 +195,11 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw ali | |||||||
| #ifdef GEN_HEAP_ANALYSIS | #ifdef GEN_HEAP_ANALYSIS | ||||||
| 	if ( type == EAllocation_ALLOC ) | 	if ( type == EAllocation_ALLOC ) | ||||||
| 	{ | 	{ | ||||||
| 		_heap_alloc_info* alloc_info = zpl_cast( _heap_alloc_info* )( zpl_cast( char* ) ptr + alloc_info_remainder ); | 		_heap_alloc_info* alloc_info = rcast( _heap_alloc_info*, rcast( char*, ptr) + alloc_info_remainder ); | ||||||
| 		zero_item( alloc_info ); | 		zero_item( alloc_info ); | ||||||
| 		alloc_info->size              = size - track_size; | 		alloc_info->size              = size - track_size; | ||||||
| 		alloc_info->physical_start    = ptr; | 		alloc_info->physical_start    = ptr; | ||||||
| 		ptr                           = zpl_cast( void* )( alloc_info + 1 ); | 		ptr                           = rcast( void*, alloc_info + 1 ); | ||||||
| 		_heap_stats_info.used_memory += alloc_info->size; | 		_heap_stats_info.used_memory += alloc_info->size; | ||||||
| 		_heap_stats_info.alloc_count++; | 		_heap_stats_info.alloc_count++; | ||||||
| 	} | 	} | ||||||
| @@ -209,7 +209,7 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw ali | |||||||
| } | } | ||||||
|  |  | ||||||
| #pragma region VirtualMemory | #pragma region VirtualMemory | ||||||
| VirtualMemory vm_from_memory( void* data, sw size ) | VirtualMemory vm_from_memory( void* data, ssize size ) | ||||||
| { | { | ||||||
| 	VirtualMemory vm; | 	VirtualMemory vm; | ||||||
| 	vm.data = data; | 	vm.data = data; | ||||||
| @@ -218,7 +218,7 @@ VirtualMemory vm_from_memory( void* data, sw size ) | |||||||
| } | } | ||||||
|  |  | ||||||
| #if defined( GEN_SYSTEM_WINDOWS ) | #if defined( GEN_SYSTEM_WINDOWS ) | ||||||
| VirtualMemory vm_alloc( void* addr, sw size ) | VirtualMemory vm_alloc( void* addr, ssize size ) | ||||||
| { | { | ||||||
| 	VirtualMemory vm; | 	VirtualMemory vm; | ||||||
| 	GEN_ASSERT( size > 0 ); | 	GEN_ASSERT( size > 0 ); | ||||||
| @@ -234,7 +234,7 @@ b32 vm_free( VirtualMemory vm ) | |||||||
| 	{ | 	{ | ||||||
| 		if ( VirtualQuery( vm.data, &info, size_of( info ) ) == 0 ) | 		if ( VirtualQuery( vm.data, &info, size_of( info ) ) == 0 ) | ||||||
| 			return false; | 			return false; | ||||||
| 		if ( info.BaseAddress != vm.data || info.AllocationBase != vm.data || info.State != MEM_COMMIT || info.RegionSize > zpl_cast( uw ) vm.size ) | 		if ( info.BaseAddress != vm.data || info.AllocationBase != vm.data || info.State != MEM_COMMIT || info.RegionSize > scast( usize, vm.size) ) | ||||||
| 		{ | 		{ | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| @@ -246,7 +246,7 @@ b32 vm_free( VirtualMemory vm ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ) | VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ) | ||||||
| { | { | ||||||
| 	VirtualMemory new_vm = { 0 }; | 	VirtualMemory new_vm = { 0 }; | ||||||
| 	void*             ptr; | 	void*             ptr; | ||||||
| @@ -270,7 +270,7 @@ b32 vm_purge( VirtualMemory vm ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw virtual_memory_page_size( sw* alignment_out ) | ssize virtual_memory_page_size( ssize* alignment_out ) | ||||||
| { | { | ||||||
| 	SYSTEM_INFO info; | 	SYSTEM_INFO info; | ||||||
| 	GetSystemInfo( &info ); | 	GetSystemInfo( &info ); | ||||||
| @@ -285,7 +285,7 @@ sw virtual_memory_page_size( sw* alignment_out ) | |||||||
| #	ifndef MAP_ANONYMOUS | #	ifndef MAP_ANONYMOUS | ||||||
| #		define MAP_ANONYMOUS MAP_ANON | #		define MAP_ANONYMOUS MAP_ANON | ||||||
| #	endif | #	endif | ||||||
| VirtualMemory vm_alloc( void* addr, sw size ) | VirtualMemory vm_alloc( void* addr, ssize size ) | ||||||
| { | { | ||||||
| 	VirtualMemory vm; | 	VirtualMemory vm; | ||||||
| 	GEN_ASSERT( size > 0 ); | 	GEN_ASSERT( size > 0 ); | ||||||
| @@ -300,10 +300,10 @@ b32 vm_free( VirtualMemory vm ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ) | VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ) | ||||||
| { | { | ||||||
| 	void*  ptr; | 	void*  ptr; | ||||||
| 	sw trail_size; | 	ssize trail_size; | ||||||
| 	GEN_ASSERT( vm.size >= lead_size + size ); | 	GEN_ASSERT( vm.size >= lead_size + size ); | ||||||
|  |  | ||||||
| 	ptr        = pointer_add( vm.data, lead_size ); | 	ptr        = pointer_add( vm.data, lead_size ); | ||||||
| @@ -322,10 +322,10 @@ b32 vm_purge( VirtualMemory vm ) | |||||||
| 	return err != 0; | 	return err != 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw virtual_memory_page_size( sw* alignment_out ) | ssize virtual_memory_page_size( ssize* alignment_out ) | ||||||
| { | { | ||||||
| 	// TODO: Is this always true? | 	// TODO: Is this always true? | ||||||
| 	sw result = zpl_cast( sw ) sysconf( _SC_PAGE_SIZE ); | 	ssize result = scast( ssize, sysconf( _SC_PAGE_SIZE )); | ||||||
| 	if ( alignment_out ) | 	if ( alignment_out ) | ||||||
| 		*alignment_out = result; | 		*alignment_out = result; | ||||||
| 	return result; | 	return result; | ||||||
| @@ -334,7 +334,7 @@ sw virtual_memory_page_size( sw* alignment_out ) | |||||||
|  |  | ||||||
| #pragma endregion VirtualMemory | #pragma endregion VirtualMemory | ||||||
|  |  | ||||||
| void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) | void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Arena* arena = rcast(Arena*, allocator_data); | 	Arena* arena = rcast(Arena*, allocator_data); | ||||||
| 	void*      ptr   = NULL; | 	void*      ptr   = NULL; | ||||||
| @@ -346,10 +346,10 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw a | |||||||
| 		case EAllocation_ALLOC : | 		case EAllocation_ALLOC : | ||||||
| 			{ | 			{ | ||||||
| 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | ||||||
| 				sw    total_size = align_forward_i64( size, alignment ); | 				ssize    total_size = align_forward_i64( size, alignment ); | ||||||
|  |  | ||||||
| 				// NOTE: Out of memory | 				// NOTE: Out of memory | ||||||
| 				if ( arena->TotalUsed + total_size > (sw) arena->TotalSize ) | 				if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize ) | ||||||
| 				{ | 				{ | ||||||
| 					// zpl__printf_err("%s", "Arena out of memory\n"); | 					// zpl__printf_err("%s", "Arena out of memory\n"); | ||||||
| 					GEN_FATAL("Arena out of memory! (Possibly could not fit for the largest size Arena!!)"); | 					GEN_FATAL("Arena out of memory! (Possibly could not fit for the largest size Arena!!)"); | ||||||
| @@ -384,9 +384,9 @@ void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw a | |||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ) | void* pool_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) | ||||||
| { | { | ||||||
| 	Pool* pool = zpl_cast( Pool* ) allocator_data; | 	Pool* pool = rcast( Pool*, allocator_data); | ||||||
| 	void* ptr  = NULL; | 	void* ptr  = NULL; | ||||||
|  |  | ||||||
| 	// unused( old_size ); | 	// unused( old_size ); | ||||||
| @@ -401,9 +401,9 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw al | |||||||
| 				GEN_ASSERT( alignment == pool->BlockAlign ); | 				GEN_ASSERT( alignment == pool->BlockAlign ); | ||||||
| 				GEN_ASSERT( pool->FreeList != NULL ); | 				GEN_ASSERT( pool->FreeList != NULL ); | ||||||
|  |  | ||||||
| 				next_free        = *zpl_cast( uptr* ) pool->FreeList; | 				next_free        = * rcast( uptr*, pool->FreeList); | ||||||
| 				ptr              = pool->FreeList; | 				ptr              = pool->FreeList; | ||||||
| 				pool->FreeList   = zpl_cast( void* ) next_free; | 				pool->FreeList   = rcast( void*, next_free); | ||||||
| 				pool->TotalSize += pool->BlockSize; | 				pool->TotalSize += pool->BlockSize; | ||||||
|  |  | ||||||
| 				if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO ) | 				if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO ) | ||||||
| @@ -417,8 +417,8 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw al | |||||||
| 				if ( old_memory == NULL ) | 				if ( old_memory == NULL ) | ||||||
| 					return NULL; | 					return NULL; | ||||||
|  |  | ||||||
| 				next             = zpl_cast( uptr* ) old_memory; | 				next             = rcast( uptr*, old_memory); | ||||||
| 				*next            = zpl_cast( uptr ) pool->FreeList; | 				*next            = rcast( uptr, pool->FreeList); | ||||||
| 				pool->FreeList   = old_memory; | 				pool->FreeList   = old_memory; | ||||||
| 				pool->TotalSize -= pool->BlockSize; | 				pool->TotalSize -= pool->BlockSize; | ||||||
| 			} | 			} | ||||||
| @@ -426,7 +426,7 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw al | |||||||
|  |  | ||||||
| 		case EAllocation_FREE_ALL : | 		case EAllocation_FREE_ALL : | ||||||
| 			{ | 			{ | ||||||
| 				sw    actual_block_size, block_index; | 				ssize    actual_block_size, block_index; | ||||||
| 				void* curr; | 				void* curr; | ||||||
| 				uptr* end; | 				uptr* end; | ||||||
|  |  | ||||||
| @@ -437,13 +437,13 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw al | |||||||
| 				curr = pool->PhysicalStart; | 				curr = pool->PhysicalStart; | ||||||
| 				for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ ) | 				for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ ) | ||||||
| 				{ | 				{ | ||||||
| 					uptr* next = zpl_cast( uptr* ) curr; | 					uptr* next = rcast( uptr*, curr); | ||||||
| 					*next      = zpl_cast( uptr ) curr + actual_block_size; | 					* next     = rcast( uptr, curr) + actual_block_size; | ||||||
| 					curr       = pointer_add( curr, actual_block_size ); | 					curr       = pointer_add( curr, actual_block_size ); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				end            = zpl_cast( uptr* ) curr; | 				end            = rcast( uptr*, curr); | ||||||
| 				*end           = zpl_cast( uptr ) NULL; | 				* end          = scast( uptr, NULL); | ||||||
| 				pool->FreeList = pool->PhysicalStart; | 				pool->FreeList = pool->PhysicalStart; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @@ -457,11 +457,11 @@ void* Pool::allocator_proc( void* allocator_data, AllocType type, sw size, sw al | |||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| Pool Pool::init_align( AllocatorInfo backing, sw num_blocks, sw block_size, sw block_align ) | Pool pool_init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align ) | ||||||
| { | { | ||||||
| 	Pool pool = {}; | 	Pool pool = {}; | ||||||
|  |  | ||||||
| 	sw    actual_block_size, pool_size, block_index; | 	ssize    actual_block_size, pool_size, block_index; | ||||||
| 	void *data, *curr; | 	void *data, *curr; | ||||||
| 	uptr* end; | 	uptr* end; | ||||||
|  |  | ||||||
| @@ -495,16 +495,16 @@ Pool Pool::init_align( AllocatorInfo backing, sw num_blocks, sw block_size, sw b | |||||||
| 	return pool; | 	return pool; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Pool::clear() | void clear(Pool& pool) | ||||||
| { | { | ||||||
| 	sw    actual_block_size, block_index; | 	ssize actual_block_size, block_index; | ||||||
| 	void* curr; | 	void* curr; | ||||||
| 	uptr* end; | 	uptr* end; | ||||||
|  |  | ||||||
| 	actual_block_size = BlockSize + BlockAlign; | 	actual_block_size = pool.BlockSize + pool.BlockAlign; | ||||||
|  |  | ||||||
| 	curr = PhysicalStart; | 	curr = pool.PhysicalStart; | ||||||
| 	for ( block_index = 0; block_index < NumBlocks - 1; block_index++ ) | 	for ( block_index = 0; block_index < pool.NumBlocks - 1; block_index++ ) | ||||||
| 	{ | 	{ | ||||||
| 		uptr* next = ( uptr* ) curr; | 		uptr* next = ( uptr* ) curr; | ||||||
| 		*next      = ( uptr  ) curr + actual_block_size; | 		*next      = ( uptr  ) curr + actual_block_size; | ||||||
| @@ -514,7 +514,7 @@ void Pool::clear() | |||||||
| 	end  =  ( uptr* ) curr; | 	end  =  ( uptr* ) curr; | ||||||
| 	*end =  ( uptr )  NULL; | 	*end =  ( uptr )  NULL; | ||||||
|  |  | ||||||
| 	FreeList = PhysicalStart; | 	pool.FreeList = pool.PhysicalStart; | ||||||
| } | } | ||||||
|  |  | ||||||
| #pragma endregion Memory | #pragma endregion Memory | ||||||
|   | |||||||
| @@ -5,48 +5,56 @@ | |||||||
|  |  | ||||||
| #pragma region Memory | #pragma region Memory | ||||||
|  |  | ||||||
| #define kilobytes( x ) ( ( x ) * ( s64 )( 1024 ) ) | #define kilobytes( x ) (          ( x ) * ( s64 )( 1024 ) ) | ||||||
| #define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) ) | #define megabytes( x ) ( kilobytes( x ) * ( s64 )( 1024 ) ) | ||||||
| #define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) ) | #define gigabytes( x ) ( megabytes( x ) * ( s64 )( 1024 ) ) | ||||||
| #define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) ) | #define terabytes( x ) ( gigabytes( x ) * ( s64 )( 1024 ) ) | ||||||
|  |  | ||||||
| #define GEN__ONES          ( zpl_cast( uw ) - 1 / GEN_U8_MAX ) | #define GEN__ONES          ( scast( GEN_NS usize, - 1) / GEN_U8_MAX ) | ||||||
| #define GEN__HIGHS         ( GEN__ONES * ( GEN_U8_MAX / 2 + 1 ) ) | #define GEN__HIGHS         ( GEN__ONES * ( GEN_U8_MAX / 2 + 1 ) ) | ||||||
| #define GEN__HAS_ZERO( x ) ( ( ( x )-GEN__ONES ) & ~( x )&GEN__HIGHS ) | #define GEN__HAS_ZERO( x ) ( ( ( x ) - GEN__ONES ) & ~( x ) & GEN__HIGHS ) | ||||||
|  |  | ||||||
|  | template< class Type > | ||||||
|  | void swap( Type& a, Type& b ) | ||||||
|  | { | ||||||
|  | 	Type tmp = a; | ||||||
|  | 	a = b; | ||||||
|  | 	b = tmp; | ||||||
|  | } | ||||||
|  |  | ||||||
| //! Checks if value is power of 2. | //! Checks if value is power of 2. | ||||||
| GEN_DEF_INLINE b32 is_power_of_two( sw x ); | b32 is_power_of_two( ssize x ); | ||||||
|  |  | ||||||
| //! Aligns address to specified alignment. | //! Aligns address to specified alignment. | ||||||
| GEN_DEF_INLINE void* align_forward( void* ptr, sw alignment ); | void* align_forward( void* ptr, ssize alignment ); | ||||||
|  |  | ||||||
| //! Aligns value to a specified alignment. | //! Aligns value to a specified alignment. | ||||||
| GEN_DEF_INLINE s64 align_forward_i64( s64 value, sw alignment ); | s64 align_forward_i64( s64 value, ssize alignment ); | ||||||
|  |  | ||||||
| //! Moves pointer forward by bytes. | //! Moves pointer forward by bytes. | ||||||
| GEN_DEF_INLINE void* pointer_add( void* ptr, sw bytes ); | void* pointer_add( void* ptr, ssize bytes ); | ||||||
|  |  | ||||||
| //! Moves pointer forward by bytes. | //! Moves pointer forward by bytes. | ||||||
| GEN_DEF_INLINE void const* pointer_add_const( void const* ptr, sw bytes ); | void const* pointer_add_const( void const* ptr, ssize bytes ); | ||||||
|  |  | ||||||
| //! Calculates difference between two addresses. | //! Calculates difference between two addresses. | ||||||
| GEN_DEF_INLINE sw pointer_diff( void const* begin, void const* end ); | ssize 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, ssize size ); | ||||||
|  |  | ||||||
| //! Search for a constant value within the size limit at memory location. | //! Search for a constant value within the size limit at memory location. | ||||||
| void const* mem_find( void const* data, u8 byte_value, sw size ); | void const* mem_find( void const* data, u8 byte_value, ssize size ); | ||||||
|  |  | ||||||
| //! Copy memory from source to destination. | //! Copy memory from source to destination. | ||||||
| GEN_DEF_INLINE void* mem_move( void* dest, void const* source, sw size ); | void* mem_move( void* dest, void const* source, ssize size ); | ||||||
|  |  | ||||||
| //! Set constant value at memory location with specified size. | //! Set constant value at memory location with specified size. | ||||||
| GEN_DEF_INLINE void* mem_set( void* data, u8 byte_value, sw size ); | void* mem_set( void* data, u8 byte_value, ssize size ); | ||||||
|  |  | ||||||
| //! @param ptr Memory location to clear up. | //! @param ptr Memory location to clear up. | ||||||
| //! @param size The size to clear up with. | //! @param size The size to clear up with. | ||||||
| GEN_DEF_INLINE void zero_size( void* ptr, sw size ); | void zero_size( void* ptr, ssize size ); | ||||||
|  |  | ||||||
| //! Clears up an item. | //! Clears up an item. | ||||||
| #define zero_item( t ) zero_size( ( t ), size_of( *( t ) ) )    // NOTE: Pass pointer of struct | #define zero_item( t ) zero_size( ( t ), size_of( *( t ) ) )    // NOTE: Pass pointer of struct | ||||||
| @@ -62,10 +70,7 @@ enum AllocType : u8 | |||||||
| 	EAllocation_RESIZE, | 	EAllocation_RESIZE, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| using AllocatorProc = void* ( void* allocator_data, AllocType type | typedef void*(AllocatorProc)( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | ||||||
| 	, sw size, sw alignment |  | ||||||
| 	, void* old_memory, sw old_size |  | ||||||
| 	, u64 flags ); |  | ||||||
|  |  | ||||||
| struct AllocatorInfo | struct AllocatorInfo | ||||||
| { | { | ||||||
| @@ -87,22 +92,22 @@ enum AllocFlag | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| //! Allocate memory with default alignment. | //! Allocate memory with default alignment. | ||||||
| GEN_DEF_INLINE void* alloc( AllocatorInfo a, sw size ); | void* alloc( AllocatorInfo a, ssize size ); | ||||||
|  |  | ||||||
| //! Allocate memory with specified alignment. | //! Allocate memory with specified alignment. | ||||||
| GEN_DEF_INLINE void* alloc_align( AllocatorInfo a, sw size, sw alignment ); | void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ); | ||||||
|  |  | ||||||
| //! Free allocated memory. | //! Free allocated memory. | ||||||
| GEN_DEF_INLINE void free( AllocatorInfo a, void* ptr ); | void free( AllocatorInfo a, void* ptr ); | ||||||
|  |  | ||||||
| //! Free all memory allocated by an allocator. | //! Free all memory allocated by an allocator. | ||||||
| GEN_DEF_INLINE void free_all( AllocatorInfo a ); | void free_all( AllocatorInfo a ); | ||||||
|  |  | ||||||
| //! Resize an allocated memory. | //! Resize an allocated memory. | ||||||
| GEN_DEF_INLINE void* resize( AllocatorInfo a, void* ptr, sw old_size, sw new_size ); | void* resize( AllocatorInfo a, void* ptr, ssize old_size, ssize new_size ); | ||||||
|  |  | ||||||
| //! Resize an allocated memory with specified alignment. | //! Resize an allocated memory with specified alignment. | ||||||
| GEN_DEF_INLINE void* resize_align( AllocatorInfo a, void* ptr, sw old_size, sw new_size, sw alignment ); | void* resize_align( AllocatorInfo a, void* ptr, ssize old_size, ssize new_size, ssize alignment ); | ||||||
|  |  | ||||||
| //! Allocate memory for an item. | //! Allocate memory for an item. | ||||||
| #define alloc_item( allocator_, Type ) ( Type* )alloc( allocator_, size_of( Type ) ) | #define alloc_item( allocator_, Type ) ( Type* )alloc( allocator_, size_of( Type ) ) | ||||||
| @@ -114,17 +119,17 @@ GEN_DEF_INLINE void* resize_align( AllocatorInfo a, void* ptr, sw old_size, sw n | |||||||
| /* define GEN_HEAP_ANALYSIS to enable this feature */ | /* define GEN_HEAP_ANALYSIS to enable this feature */ | ||||||
| /* call zpl_heap_stats_init at the beginning of the entry point */ | /* call zpl_heap_stats_init at the beginning of the entry point */ | ||||||
| /* you can call zpl_heap_stats_check near the end of the execution to validate any possible leaks */ | /* you can call zpl_heap_stats_check near the end of the execution to validate any possible leaks */ | ||||||
| void heap_stats_init( void ); | void  heap_stats_init( void ); | ||||||
| sw   heap_stats_used_memory( void ); | ssize heap_stats_used_memory( void ); | ||||||
| sw   heap_stats_alloc_count( void ); | ssize heap_stats_alloc_count( void ); | ||||||
| void heap_stats_check( void ); | void  heap_stats_check( void ); | ||||||
|  |  | ||||||
| //! Allocate/Resize memory using default options. | //! Allocate/Resize memory using default options. | ||||||
|  |  | ||||||
| //! Use this if you don't need a "fancy" resize allocation | //! Use this if you don't need a "fancy" resize allocation | ||||||
| GEN_DEF_INLINE void* default_resize_align( AllocatorInfo a, void* ptr, sw old_size, sw new_size, sw alignment ); | void* default_resize_align( AllocatorInfo a, void* ptr, ssize old_size, ssize new_size, ssize alignment ); | ||||||
|  |  | ||||||
| void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ); | void* heap_allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ); | ||||||
|  |  | ||||||
| //! The heap allocator backed by operating system's memory manager. | //! The heap allocator backed by operating system's memory manager. | ||||||
| constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; } | constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; } | ||||||
| @@ -135,203 +140,466 @@ constexpr AllocatorInfo heap( void ) { return { heap_allocator_proc, nullptr }; | |||||||
| //! Helper to free memory allocated by heap allocator. | //! Helper to free memory allocated by heap allocator. | ||||||
| #define mfree( ptr ) free( heap(), ptr ) | #define mfree( ptr ) free( heap(), ptr ) | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 is_power_of_two( sw x ) | struct VirtualMemory | ||||||
| { | { | ||||||
|  | 	void*  data; | ||||||
|  | 	ssize size; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //! Initialize virtual memory from existing data. | ||||||
|  | VirtualMemory vm_from_memory( void* data, ssize size ); | ||||||
|  |  | ||||||
|  | //! Allocate virtual memory at address with size. | ||||||
|  |  | ||||||
|  | //! @param addr The starting address of the region to reserve. If NULL, it lets operating system to decide where to allocate it. | ||||||
|  | //! @param size The size to serve. | ||||||
|  | VirtualMemory vm_alloc( void* addr, ssize size ); | ||||||
|  |  | ||||||
|  | //! Release the virtual memory. | ||||||
|  | b32 vm_free( VirtualMemory vm ); | ||||||
|  |  | ||||||
|  | //! Trim virtual memory. | ||||||
|  | VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ); | ||||||
|  |  | ||||||
|  | //! Purge virtual memory. | ||||||
|  | b32 gen_vm_purge( VirtualMemory vm ); | ||||||
|  |  | ||||||
|  | //! Retrieve VM's page size and alignment. | ||||||
|  | ssize gen_virtual_memory_page_size( ssize* alignment_out ); | ||||||
|  |  | ||||||
|  | #pragma region Arena | ||||||
|  | struct Arena; | ||||||
|  |  | ||||||
|  | AllocatorInfo allocator_info( Arena& arena ); | ||||||
|  |  | ||||||
|  | // Remove static keyword and rename allocator_proc | ||||||
|  | void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags); | ||||||
|  |  | ||||||
|  | // Add these declarations after the Arena struct | ||||||
|  | Arena arena_init_from_allocator(AllocatorInfo backing, ssize size); | ||||||
|  | Arena arena_init_from_memory( void* start, ssize size ); | ||||||
|  | Arena init_sub(Arena& parent, ssize size); | ||||||
|  | ssize alignment_of(Arena& arena, ssize alignment); | ||||||
|  |  | ||||||
|  | // This id is defined by Unreal for asserts | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | void   check(Arena& arena); | ||||||
|  | #pragma pop_macro("check") | ||||||
|  |  | ||||||
|  | void  free(Arena& arena); | ||||||
|  | ssize size_remaining(Arena& arena, ssize alignment); | ||||||
|  |  | ||||||
|  | struct Arena | ||||||
|  | { | ||||||
|  | 	AllocatorInfo Backing; | ||||||
|  | 	void*         PhysicalStart; | ||||||
|  | 	ssize         TotalSize; | ||||||
|  | 	ssize         TotalUsed; | ||||||
|  | 	ssize         TempCount; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline operator AllocatorInfo() { return GEN_NS allocator_info(* this); } | ||||||
|  |  | ||||||
|  | 	forceinline static void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) { return GEN_NS arena_allocator_proc( allocator_data, type, size, alignment, old_memory, old_size, flags ); } | ||||||
|  | 	forceinline static Arena init_from_memory( void* start, ssize size )                                                                                      { return GEN_NS arena_init_from_memory( start, size ); } | ||||||
|  | 	forceinline static Arena init_from_allocator( AllocatorInfo backing, ssize size )                                                                         { return GEN_NS arena_init_from_allocator( backing, size ); } | ||||||
|  | 	forceinline static Arena init_sub( Arena& parent, ssize size )                                                                                            { return GEN_NS arena_init_from_allocator( parent.Backing, size ); } | ||||||
|  | 	forceinline        ssize alignment_of( ssize alignment )                                                                                                  { return GEN_NS alignment_of(* this, alignment); } | ||||||
|  | 	forceinline        void  free()                                                                                                                           { return GEN_NS free(* this);  } | ||||||
|  | 	forceinline        ssize size_remaining( ssize alignment )                                                                                                { return GEN_NS size_remaining(* this, alignment); } | ||||||
|  |  | ||||||
|  | // This id is defined by Unreal for asserts | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | 	forceinline void check() { GEN_NS check(* this); } | ||||||
|  | #pragma pop_macro("check") | ||||||
|  |  | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | AllocatorInfo allocator_info( Arena& arena ) { | ||||||
|  | 	return { arena_allocator_proc, &arena }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Arena arena_init_from_memory( void* start, ssize size ) | ||||||
|  | { | ||||||
|  | 	Arena arena = { | ||||||
|  | 		{ nullptr, nullptr }, | ||||||
|  | 		start, | ||||||
|  | 		size, | ||||||
|  | 		0, | ||||||
|  | 		0 | ||||||
|  | 	}; | ||||||
|  | 	return arena; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) { | ||||||
|  | 	Arena result = { | ||||||
|  | 		backing, | ||||||
|  | 		alloc(backing, size), | ||||||
|  | 		size, | ||||||
|  | 		0, | ||||||
|  | 		0 | ||||||
|  | 	}; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Arena init_sub(Arena& parent, ssize size) { | ||||||
|  | 	return arena_init_from_allocator(parent.Backing, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | ssize alignment_of(Arena& arena, ssize alignment) | ||||||
|  | { | ||||||
|  | 	ssize alignment_offset, result_pointer, mask; | ||||||
|  | 	GEN_ASSERT(is_power_of_two(alignment)); | ||||||
|  |  | ||||||
|  | 	alignment_offset = 0; | ||||||
|  | 	result_pointer  = (ssize)arena.PhysicalStart + arena.TotalUsed; | ||||||
|  | 	mask            = alignment - 1; | ||||||
|  |  | ||||||
|  | 	if (result_pointer & mask) | ||||||
|  | 	alignment_offset = alignment - (result_pointer & mask); | ||||||
|  |  | ||||||
|  | 	return alignment_offset; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #pragma push_macro("check") | ||||||
|  | #undef check | ||||||
|  | inline | ||||||
|  | void check(Arena& arena) | ||||||
|  | { | ||||||
|  |     GEN_ASSERT(arena.TempCount == 0); | ||||||
|  | } | ||||||
|  | #pragma pop_macro("check") | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void free(Arena& arena) | ||||||
|  | { | ||||||
|  | 	if (arena.Backing.Proc) | ||||||
|  | 	{ | ||||||
|  | 		GEN_NS free(arena.Backing, arena.PhysicalStart); | ||||||
|  | 		arena.PhysicalStart = nullptr; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | ssize size_remaining(Arena& arena, ssize alignment) | ||||||
|  | { | ||||||
|  | 	ssize result = arena.TotalSize - (arena.TotalUsed + alignment_of(arena, alignment)); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | #pragma endregion Arena | ||||||
|  |  | ||||||
|  | #pragma region FixedArena | ||||||
|  | template<s32 Size> | ||||||
|  | struct FixedArena; | ||||||
|  |  | ||||||
|  | template<s32 Size> AllocatorInfo    allocator_info( FixedArena<Size>& fixed_arena ); | ||||||
|  | template<s32 Size> FixedArena<Size> fixed_arena_init(); | ||||||
|  | template<s32 Size> ssize            size_remaining(FixedArena<Size>& fixed_arena, ssize alignment); | ||||||
|  |  | ||||||
|  | // Just a wrapper around using an arena with memory associated with its scope instead of from an allocator. | ||||||
|  | // Used for static segment or stack allocations. | ||||||
|  | template< s32 Size > | ||||||
|  | struct FixedArena | ||||||
|  | { | ||||||
|  | 	char  memory[Size]; | ||||||
|  | 	Arena arena; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline operator AllocatorInfo() { return GEN_NS allocator_info(* this); } | ||||||
|  |  | ||||||
|  | 	forceinline static FixedArena init()                          { FixedArena result; GEN_NS fixed_arena_init<Size>(result); return result; } | ||||||
|  | 	forceinline ssize             size_remaining(ssize alignment) { GEN_NS size_remaining(*this, alignment); } | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | AllocatorInfo allocator_info( FixedArena<Size>& fixed_arena ) { return { arena_allocator_proc, & fixed_arena.arena }; } | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | void fixed_arena_init(FixedArena<Size>& result) { | ||||||
|  |     zero_size(& result.memory[0], Size); | ||||||
|  |     result.arena = arena_init_from_memory(& result.memory[0], Size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<s32 Size> inline | ||||||
|  | ssize size_remaining(FixedArena<Size>& fixed_arena, ssize alignment) { | ||||||
|  |     return size_remaining(fixed_arena.arena, alignment); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | using Arena_1KB   = FixedArena< kilobytes( 1 ) >; | ||||||
|  | using Arena_4KB   = FixedArena< kilobytes( 4 ) >; | ||||||
|  | using Arena_8KB   = FixedArena< kilobytes( 8 ) >; | ||||||
|  | using Arena_16KB  = FixedArena< kilobytes( 16 ) >; | ||||||
|  | using Arena_32KB  = FixedArena< kilobytes( 32 ) >; | ||||||
|  | using Arena_64KB  = FixedArena< kilobytes( 64 ) >; | ||||||
|  | using Arena_128KB = FixedArena< kilobytes( 128 ) >; | ||||||
|  | using Arena_256KB = FixedArena< kilobytes( 256 ) >; | ||||||
|  | using Arena_512KB = FixedArena< kilobytes( 512 ) >; | ||||||
|  | using Arena_1MB   = FixedArena< megabytes( 1 ) >; | ||||||
|  | using Arena_2MB   = FixedArena< megabytes( 2 ) >; | ||||||
|  | using Arena_4MB   = FixedArena< megabytes( 4 ) >; | ||||||
|  | #pragma endregion FixedArena | ||||||
|  |  | ||||||
|  | #pragma region Pool | ||||||
|  | struct Pool; | ||||||
|  |  | ||||||
|  | AllocatorInfo allocator_info(Pool& pool); | ||||||
|  | void*         pool_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags); | ||||||
|  | Pool          pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size); | ||||||
|  | Pool          pool_init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align); | ||||||
|  | void          clear(Pool& pool); | ||||||
|  | void          free(Pool& pool); | ||||||
|  |  | ||||||
|  | struct Pool | ||||||
|  | { | ||||||
|  | 	AllocatorInfo Backing; | ||||||
|  | 	void*         PhysicalStart; | ||||||
|  | 	void*         FreeList; | ||||||
|  | 	ssize         BlockSize; | ||||||
|  | 	ssize         BlockAlign; | ||||||
|  | 	ssize         TotalSize; | ||||||
|  | 	ssize         NumBlocks; | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  |     forceinline operator AllocatorInfo() { return GEN_NS allocator_info(* this); } | ||||||
|  |  | ||||||
|  |     forceinline static void* allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags) { return GEN_NS pool_allocator_proc(allocator_data, type, size, alignment, old_memory, old_size, flags); } | ||||||
|  |     forceinline static Pool  init(AllocatorInfo backing, ssize num_blocks, ssize block_size)                                                                { return GEN_NS pool_init(backing, num_blocks, block_size); } | ||||||
|  |     forceinline static Pool  init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align)                                       { return GEN_NS pool_init_align(backing, num_blocks, block_size, block_align); } | ||||||
|  |     forceinline        void  clear() { GEN_NS clear(* this); } | ||||||
|  |     forceinline        void  free()  { GEN_NS free(* this); } | ||||||
|  | #pragma endregion | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | AllocatorInfo allocator_info(Pool& pool) { | ||||||
|  |    return { pool_allocator_proc, &pool }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size) { | ||||||
|  |    return pool_init_align(backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void free(Pool& pool) { | ||||||
|  |    if(pool.Backing.Proc) { | ||||||
|  |        GEN_NS free(pool.Backing, pool.PhysicalStart); | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | #pragma endregion Pool | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | b32 is_power_of_two( ssize x ) { | ||||||
| 	if ( x <= 0 ) | 	if ( x <= 0 ) | ||||||
| 		return false; | 		return false; | ||||||
| 	return ! ( x & ( x - 1 ) ); | 	return ! ( x & ( x - 1 ) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* align_forward( void* ptr, sw alignment ) | inline | ||||||
|  | mem_ptr align_forward( void* ptr, ssize alignment ) | ||||||
| { | { | ||||||
| 	uptr p; |  | ||||||
|  |  | ||||||
| 	GEN_ASSERT( is_power_of_two( alignment ) ); | 	GEN_ASSERT( is_power_of_two( alignment ) ); | ||||||
|  | 	uptr p       = to_uptr(ptr); | ||||||
|  | 	uptr forward = (p + ( alignment - 1 ) ) & ~( alignment - 1 ); | ||||||
|  |  | ||||||
| 	p = zpl_cast( uptr ) ptr; | 	return to_mem_ptr(forward); | ||||||
| 	return zpl_cast( void* )( ( p + ( alignment - 1 ) ) & ~( alignment - 1 ) ); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s64 align_forward_i64( s64 value, sw alignment ) | inline s64 align_forward_i64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; } | ||||||
| { |  | ||||||
| 	return value + ( alignment - value % alignment ) % alignment; | inline void*       pointer_add      ( void*       ptr, ssize bytes ) { return rcast(void*,       rcast( u8*,        ptr) + bytes ); } | ||||||
|  | inline void const* pointer_add_const( void const* ptr, ssize bytes ) { return rcast(void const*, rcast( u8 const*,  ptr) + bytes ); } | ||||||
|  |  | ||||||
|  | inline sptr pointer_diff( mem_ptr_const begin, mem_ptr_const end ) { | ||||||
|  | 	return scast( ssize, rcast( u8 const*, end) - rcast(u8 const*, begin) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* pointer_add( void* ptr, sw bytes ) | inline | ||||||
|  | void* mem_move( void* destination, void const* source, ssize byte_count ) | ||||||
| { | { | ||||||
| 	return zpl_cast( void* )( zpl_cast( u8* ) ptr + bytes ); | 	if ( destination == NULL ) | ||||||
| } |  | ||||||
|  |  | ||||||
| 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 ) |  | ||||||
| { |  | ||||||
| 	if ( dest == NULL ) |  | ||||||
| 	{ | 	{ | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	u8*       d = zpl_cast( u8* ) dest; | 	u8*       dest_ptr = rcast( u8*, destination); | ||||||
| 	u8 const* s = zpl_cast( u8 const* ) source; | 	u8 const* src_ptr  = rcast( u8 const*, source); | ||||||
|  |  | ||||||
| 	if ( d == s ) | 	if ( dest_ptr == src_ptr ) | ||||||
| 		return d; | 		return dest_ptr; | ||||||
| 	if ( s + n <= d || d + n <= s )    // NOTE: Non-overlapping |  | ||||||
| 		return mem_copy( d, s, n ); |  | ||||||
|  |  | ||||||
| 	if ( d < s ) | 	if ( src_ptr + byte_count <= dest_ptr || dest_ptr + byte_count <= src_ptr )    // NOTE: Non-overlapping | ||||||
|  | 		return mem_copy( dest_ptr, src_ptr, byte_count ); | ||||||
|  |  | ||||||
|  | 	if ( dest_ptr < src_ptr ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( zpl_cast( uptr ) s % size_of( sw ) == zpl_cast( uptr ) d % size_of( sw ) ) | 		if ( to_uptr(src_ptr) % size_of( ssize ) == to_uptr(dest_ptr) % size_of( ssize ) ) | ||||||
| 		{ | 		{ | ||||||
| 			while ( zpl_cast( uptr ) d % size_of( sw ) ) | 			while ( pcast( uptr, dest_ptr) % size_of( ssize ) ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( ! n-- ) | 				if ( ! byte_count-- ) | ||||||
| 					return dest; | 					return destination; | ||||||
| 				*d++ = *s++; |  | ||||||
|  | 				*dest_ptr++ = *src_ptr++; | ||||||
| 			} | 			} | ||||||
| 			while ( n >= size_of( sw ) ) | 			while ( byte_count >= size_of( ssize ) ) | ||||||
| 			{ | 			{ | ||||||
| 				*zpl_cast( sw* ) d  = *zpl_cast( sw* ) s; | 				* rcast(ssize*, dest_ptr)  = * rcast(ssize const*, src_ptr); | ||||||
| 				n                  -= size_of( sw ); | 				byte_count -= size_of( ssize ); | ||||||
| 				d                  += size_of( sw ); | 				dest_ptr   += size_of( ssize ); | ||||||
| 				s                  += size_of( sw ); | 				src_ptr    += size_of( ssize ); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		for ( ; n; n-- ) | 		for ( ; byte_count; byte_count-- ) | ||||||
| 			*d++ = *s++; | 			*dest_ptr++ = *src_ptr++; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if ( ( zpl_cast( uptr ) s % size_of( sw ) ) == ( zpl_cast( uptr ) d % size_of( sw ) ) ) | 		if ( ( to_uptr(src_ptr) % size_of( ssize ) ) == ( to_uptr(dest_ptr) % size_of( ssize ) ) ) | ||||||
| 		{ | 		{ | ||||||
| 			while ( zpl_cast( uptr )( d + n ) % size_of( sw ) ) | 			while ( to_uptr( dest_ptr + byte_count ) % size_of( ssize ) ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( ! n-- ) | 				if ( ! byte_count-- ) | ||||||
| 					return dest; | 					return destination; | ||||||
| 				d[ n ] = s[ n ]; |  | ||||||
|  | 				dest_ptr[ byte_count ] = src_ptr[ byte_count ]; | ||||||
| 			} | 			} | ||||||
| 			while ( n >= size_of( sw ) ) | 			while ( byte_count >= size_of( ssize ) ) | ||||||
| 			{ | 			{ | ||||||
| 				n                         -= size_of( sw ); | 				byte_count                              -= size_of( ssize ); | ||||||
| 				*zpl_cast( sw* )( d + n )  = *zpl_cast( sw* )( s + n ); | 				* rcast(ssize*, dest_ptr + byte_count )  = * rcast( ssize const*, src_ptr + byte_count ); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		while ( n ) | 		while ( byte_count ) | ||||||
| 			n--, d[ n ] = s[ n ]; | 			byte_count--, dest_ptr[ byte_count ] = src_ptr[ byte_count ]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return dest; | 	return destination; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* mem_set( void* dest, u8 c, sw n ) | inline | ||||||
|  | void* mem_set( void* destination, u8 fill_byte, ssize byte_count ) | ||||||
| { | { | ||||||
| 	if ( dest == NULL ) | 	if ( destination == NULL ) | ||||||
| 	{ | 	{ | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	u8* s = zpl_cast( u8* ) dest; | 	ssize align_offset; | ||||||
| 	sw  k; | 	u8*   dest_ptr  = rcast( u8*, destination); | ||||||
| 	u32 c32 = ( ( u32 )-1 ) / 255 * c; | 	u32   fill_word = ( ( u32 )-1 ) / 255 * fill_byte; | ||||||
|  |  | ||||||
| 	if ( n == 0 ) | 	if ( byte_count == 0 ) | ||||||
| 		return dest; | 		return destination; | ||||||
| 	s[ 0 ] = s[ n - 1 ] = c; |  | ||||||
| 	if ( n < 3 ) |  | ||||||
| 		return dest; |  | ||||||
| 	s[ 1 ] = s[ n - 2 ] = c; |  | ||||||
| 	s[ 2 ] = s[ n - 3 ] = c; |  | ||||||
| 	if ( n < 7 ) |  | ||||||
| 		return dest; |  | ||||||
| 	s[ 3 ] = s[ n - 4 ] = c; |  | ||||||
| 	if ( n < 9 ) |  | ||||||
| 		return dest; |  | ||||||
|  |  | ||||||
| 	k  = -zpl_cast( sptr ) s & 3; | 	dest_ptr[ 0 ] = dest_ptr[ byte_count - 1 ] = fill_byte; | ||||||
| 	s += k; | 	if ( byte_count < 3 ) | ||||||
| 	n -= k; | 		return destination; | ||||||
| 	n &= -4; |  | ||||||
|  |  | ||||||
| 	*zpl_cast( u32* )( s + 0 )     = c32; | 	dest_ptr[ 1 ] = dest_ptr[ byte_count - 2 ] = fill_byte; | ||||||
| 	*zpl_cast( u32* )( s + n - 4 ) = c32; | 	dest_ptr[ 2 ] = dest_ptr[ byte_count - 3 ] = fill_byte; | ||||||
| 	if ( n < 9 ) | 	if ( byte_count < 7 ) | ||||||
| 		return dest; | 		return destination; | ||||||
| 	*zpl_cast( u32* )( s + 4 )      = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + 8 )      = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 12 ) = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 8 )  = c32; |  | ||||||
| 	if ( n < 25 ) |  | ||||||
| 		return dest; |  | ||||||
| 	*zpl_cast( u32* )( s + 12 )     = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + 16 )     = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + 20 )     = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + 24 )     = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 28 ) = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 24 ) = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 20 ) = c32; |  | ||||||
| 	*zpl_cast( u32* )( s + n - 16 ) = c32; |  | ||||||
|  |  | ||||||
| 	k  = 24 + ( zpl_cast( uptr ) s & 4 ); | 	dest_ptr[ 3 ] = dest_ptr[ byte_count - 4 ] = fill_byte; | ||||||
| 	s += k; | 	if ( byte_count < 9 ) | ||||||
| 	n -= k; | 		return destination; | ||||||
|  |  | ||||||
|  | 	align_offset  = -to_sptr( dest_ptr ) & 3; | ||||||
|  | 	dest_ptr     += align_offset; | ||||||
|  | 	byte_count   -= align_offset; | ||||||
|  | 	byte_count   &= -4; | ||||||
|  |  | ||||||
|  | 	* rcast( u32*, ( dest_ptr + 0              ) ) = fill_word; | ||||||
|  | 	* rcast( u32*, ( dest_ptr + byte_count - 4 ) ) = fill_word; | ||||||
|  | 	if ( byte_count < 9 ) | ||||||
|  | 		return destination; | ||||||
|  |  | ||||||
|  | 	* rcast( u32*, dest_ptr + 4 )               = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + 8 )               = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 12 ) = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 8 )  = fill_word; | ||||||
|  | 	if ( byte_count < 25 ) | ||||||
|  | 		return destination; | ||||||
|  |  | ||||||
|  | 	* rcast( u32*, dest_ptr + 12 )              = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + 16 )              = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + 20 )              = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + 24 )              = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 28 ) = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 24 ) = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 20 ) = fill_word; | ||||||
|  | 	* rcast( u32*, dest_ptr + byte_count - 16 ) = fill_word; | ||||||
|  |  | ||||||
|  | 	align_offset  = 24 + to_uptr( dest_ptr ) & 4; | ||||||
|  | 	dest_ptr     += align_offset; | ||||||
|  | 	byte_count   -= align_offset; | ||||||
|  |  | ||||||
| 	{ | 	{ | ||||||
| 		u64 c64 = ( zpl_cast( u64 ) c32 << 32 ) | c32; | 		u64 fill_doubleword = ( scast( u64, fill_word) << 32 ) | fill_word; | ||||||
| 		while ( n > 31 ) | 		while ( byte_count > 31 ) | ||||||
| 		{ | 		{ | ||||||
| 			*zpl_cast( u64* )( s + 0 )  = c64; | 			* rcast( u64*, dest_ptr + 0 )  = fill_doubleword; | ||||||
| 			*zpl_cast( u64* )( s + 8 )  = c64; | 			* rcast( u64*, dest_ptr + 8 )  = fill_doubleword; | ||||||
| 			*zpl_cast( u64* )( s + 16 ) = c64; | 			* rcast( u64*, dest_ptr + 16 ) = fill_doubleword; | ||||||
| 			*zpl_cast( u64* )( s + 24 ) = c64; | 			* rcast( u64*, dest_ptr + 24 ) = fill_doubleword; | ||||||
|  |  | ||||||
| 			n -= 32; | 			byte_count -= 32; | ||||||
| 			s += 32; | 			dest_ptr += 32; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return dest; | 	return destination; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* alloc_align( AllocatorInfo a, sw size, sw alignment ) | inline | ||||||
| { | void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ) { | ||||||
| 	return a.Proc( a.Data, EAllocation_ALLOC, size, alignment, nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | 	return a.Proc( a.Data, EAllocation_ALLOC, size, alignment, nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* alloc( AllocatorInfo a, sw size ) | inline | ||||||
| { | void* alloc( AllocatorInfo a, ssize size ) { | ||||||
| 	return alloc_align( a, size, GEN_DEFAULT_MEMORY_ALIGNMENT ); | 	return alloc_align( a, size, GEN_DEFAULT_MEMORY_ALIGNMENT ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void free( AllocatorInfo a, void* ptr ) | inline | ||||||
| { | void free( AllocatorInfo a, void* ptr ) { | ||||||
| 	if ( ptr != nullptr ) | 	if ( ptr != nullptr ) | ||||||
| 		a.Proc( a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | 		a.Proc( a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void free_all( AllocatorInfo a ) | inline | ||||||
| { | void free_all( AllocatorInfo a ) { | ||||||
| 	a.Proc( a.Data, EAllocation_FREE_ALL, 0, 0, nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | 	a.Proc( a.Data, EAllocation_FREE_ALL, 0, 0, nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* resize( AllocatorInfo a, void* ptr, sw old_size, sw new_size ) | inline | ||||||
| { | void* resize( AllocatorInfo a, void* ptr, ssize old_size, ssize new_size ) { | ||||||
| 	return resize_align( a, ptr, old_size, new_size, GEN_DEFAULT_MEMORY_ALIGNMENT ); | 	return resize_align( a, ptr, old_size, new_size, GEN_DEFAULT_MEMORY_ALIGNMENT ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* resize_align( AllocatorInfo a, void* ptr, sw old_size, sw new_size, sw alignment ) | inline | ||||||
| { | void* resize_align( AllocatorInfo a, void* ptr, ssize old_size, ssize new_size, ssize alignment ) { | ||||||
| 	return a.Proc( a.Data, EAllocation_RESIZE, new_size, alignment, ptr, old_size, GEN_DEFAULT_ALLOCATOR_FLAGS ); | 	return a.Proc( a.Data, EAllocation_RESIZE, new_size, alignment, ptr, old_size, GEN_DEFAULT_ALLOCATOR_FLAGS ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void* default_resize_align( AllocatorInfo a, void* old_memory, sw old_size, sw new_size, sw alignment ) | inline | ||||||
|  | void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, ssize new_size, ssize alignment ) | ||||||
| { | { | ||||||
| 	if ( ! old_memory ) | 	if ( ! old_memory ) | ||||||
| 		return alloc_align( a, new_size, alignment ); | 		return alloc_align( a, new_size, alignment ); | ||||||
| @@ -351,207 +619,19 @@ GEN_IMPL_INLINE void* default_resize_align( AllocatorInfo a, void* old_memory, s | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		void* new_memory = alloc_align( a, new_size, alignment ); | 		void*  new_memory = alloc_align( a, new_size, alignment ); | ||||||
| 		if ( ! new_memory ) | 		if ( ! new_memory ) | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
|  |  | ||||||
| 		mem_move( new_memory, old_memory, min( new_size, old_size ) ); | 		mem_move( new_memory, old_memory, min( new_size, old_size ) ); | ||||||
| 		free( a, old_memory ); | 		free( a, old_memory ); | ||||||
| 		return new_memory; | 		return new_memory; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void zero_size( void* ptr, sw size ) | inline | ||||||
| { | void zero_size( void* ptr, ssize size ) { | ||||||
| 	mem_set( ptr, 0, size ); | 	mem_set( ptr, 0, size ); | ||||||
| } | } | ||||||
|  |  | ||||||
| struct VirtualMemory |  | ||||||
| { |  | ||||||
| 	void*  data; |  | ||||||
| 	sw size; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| //! Initialize virtual memory from existing data. |  | ||||||
| VirtualMemory vm_from_memory( void* data, sw size ); |  | ||||||
|  |  | ||||||
| //! Allocate virtual memory at address with size. |  | ||||||
|  |  | ||||||
| //! @param addr The starting address of the region to reserve. If NULL, it lets operating system to decide where to allocate it. |  | ||||||
| //! @param size The size to serve. |  | ||||||
| VirtualMemory vm_alloc( void* addr, sw size ); |  | ||||||
|  |  | ||||||
| //! Release the virtual memory. |  | ||||||
| b32 vm_free( VirtualMemory vm ); |  | ||||||
|  |  | ||||||
| //! Trim virtual memory. |  | ||||||
| VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size ); |  | ||||||
|  |  | ||||||
| //! Purge virtual memory. |  | ||||||
| b32 gen_vm_purge( VirtualMemory vm ); |  | ||||||
|  |  | ||||||
| //! Retrieve VM's page size and alignment. |  | ||||||
| sw gen_virtual_memory_page_size( sw* alignment_out ); |  | ||||||
|  |  | ||||||
| struct Arena |  | ||||||
| { |  | ||||||
| 	static |  | ||||||
| 	void* allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ); |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Arena init_from_memory( void* start, sw size ) |  | ||||||
| 	{ |  | ||||||
| 		return |  | ||||||
| 		{ |  | ||||||
| 			{ nullptr, nullptr }, |  | ||||||
| 			start, |  | ||||||
| 			size, |  | ||||||
| 			0, |  | ||||||
| 			0 |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Arena init_from_allocator( AllocatorInfo backing, sw size ) |  | ||||||
| 	{ |  | ||||||
| 		Arena result = |  | ||||||
| 		{ |  | ||||||
| 		backing, |  | ||||||
| 		alloc( backing, size), |  | ||||||
| 		size, |  | ||||||
| 		0, |  | ||||||
| 		0 |  | ||||||
| 		}; |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Arena init_sub( Arena& parent, sw size ) |  | ||||||
| 	{ |  | ||||||
| 		return init_from_allocator( parent.Backing, size ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sw alignment_of( sw alignment ) |  | ||||||
| 	{ |  | ||||||
| 		sw alignment_offset, result_pointer, mask; |  | ||||||
| 		GEN_ASSERT( is_power_of_two( alignment ) ); |  | ||||||
|  |  | ||||||
| 		alignment_offset = 0; |  | ||||||
| 		result_pointer   = (sw) PhysicalStart + TotalUsed; |  | ||||||
| 		mask             = alignment - 1; |  | ||||||
|  |  | ||||||
| 		if ( result_pointer & mask ) |  | ||||||
| 			alignment_offset = alignment - ( result_pointer & mask ); |  | ||||||
|  |  | ||||||
| 		return alignment_offset; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void check() |  | ||||||
| 	{ |  | ||||||
| 		GEN_ASSERT( TempCount == 0 ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void free() |  | ||||||
| 	{ |  | ||||||
| 		if ( Backing.Proc ) |  | ||||||
| 		{ |  | ||||||
| 			gen::free( Backing, PhysicalStart ); |  | ||||||
| 			PhysicalStart = nullptr; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sw size_remaining( sw alignment ) |  | ||||||
| 	{ |  | ||||||
| 		sw result = TotalSize - ( TotalUsed + alignment_of( alignment ) ); |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	AllocatorInfo Backing; |  | ||||||
| 	void*         PhysicalStart; |  | ||||||
| 	sw            TotalSize; |  | ||||||
| 	sw            TotalUsed; |  | ||||||
| 	sw            TempCount; |  | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() |  | ||||||
| 	{ |  | ||||||
| 		return { allocator_proc, this }; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| // Just a wrapper around using an arena with memory associated with its scope instead of from an allocator. |  | ||||||
| // Used for static segment or stack allocations. |  | ||||||
| template< s32 Size > |  | ||||||
| struct FixedArena |  | ||||||
| { |  | ||||||
| 	static |  | ||||||
| 	FixedArena init() |  | ||||||
| 	{ |  | ||||||
| 		FixedArena result = { Arena::init_from_memory( result.memory, Size ), {0} }; |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sw size_remaining( sw alignment ) |  | ||||||
| 	{ |  | ||||||
| 		return arena.size_remaining( alignment ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() |  | ||||||
| 	{ |  | ||||||
| 		return { Arena::allocator_proc, &arena }; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Arena arena; |  | ||||||
| 	char  memory[ Size ]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| using Arena_1KB   = FixedArena< kilobytes( 1 ) >; |  | ||||||
| using Arena_4KB   = FixedArena< kilobytes( 4 ) >; |  | ||||||
| using Arena_8KB   = FixedArena< kilobytes( 8 ) >; |  | ||||||
| using Arena_16KB  = FixedArena< kilobytes( 16 ) >; |  | ||||||
| using Arena_32KB  = FixedArena< kilobytes( 32 ) >; |  | ||||||
| using Arena_64KB  = FixedArena< kilobytes( 64 ) >; |  | ||||||
| using Arena_128KB = FixedArena< kilobytes( 128 ) >; |  | ||||||
| using Arena_256KB = FixedArena< kilobytes( 256 ) >; |  | ||||||
| using Arena_512KB = FixedArena< kilobytes( 512 ) >; |  | ||||||
| using Arena_1MB   = FixedArena< megabytes( 1 ) >; |  | ||||||
| using Arena_2MB   = FixedArena< megabytes( 2 ) >; |  | ||||||
| using Arena_4MB   = FixedArena< megabytes( 4 ) >; |  | ||||||
|  |  | ||||||
| struct Pool |  | ||||||
| { |  | ||||||
| 	static |  | ||||||
| 	void* allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags ); |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Pool init( AllocatorInfo backing, sw num_blocks, sw block_size ) |  | ||||||
| 	{ |  | ||||||
| 		return init_align( backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	Pool init_align( AllocatorInfo backing, sw num_blocks, sw block_size, sw block_align ); |  | ||||||
|  |  | ||||||
| 	void clear(); |  | ||||||
|  |  | ||||||
| 	void free() |  | ||||||
| 	{ |  | ||||||
| 		if ( Backing.Proc ) |  | ||||||
| 		{ |  | ||||||
| 			gen::free( Backing, PhysicalStart ); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	AllocatorInfo Backing; |  | ||||||
| 	void*         PhysicalStart; |  | ||||||
| 	void*         FreeList; |  | ||||||
| 	sw            BlockSize; |  | ||||||
| 	sw            BlockAlign; |  | ||||||
| 	sw            TotalSize; |  | ||||||
| 	sw            NumBlocks; |  | ||||||
|  |  | ||||||
| 	operator AllocatorInfo() |  | ||||||
| 	{ |  | ||||||
| 		return { allocator_proc, this }; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #pragma endregion Memory | #pragma endregion Memory | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ u8 adt_make_branch( ADT_Node* node, AllocatorInfo backing, char const* name, b32 | |||||||
| 	node->type   = type; | 	node->type   = type; | ||||||
| 	node->name   = name; | 	node->name   = name; | ||||||
| 	node->parent = parent; | 	node->parent = parent; | ||||||
| 	node->nodes  = Array<ADT_Node>::init( backing ); | 	node->nodes  = array_init<ADT_Node>( backing ); | ||||||
|  |  | ||||||
| 	if ( ! node->nodes ) | 	if ( ! node->nodes ) | ||||||
| 		return EADT_ERROR_OUT_OF_MEMORY; | 		return EADT_ERROR_OUT_OF_MEMORY; | ||||||
| @@ -36,12 +36,12 @@ u8 adt_destroy_branch( ADT_Node* node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes ) | 	if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( sw i = 0; i < node->nodes.num(); ++i ) | 		for ( ssize i = 0; i < scast(ssize, num(node->nodes)); ++i ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_destroy_branch( node->nodes + i ); | 			adt_destroy_branch( node->nodes + i ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		node->nodes.free(); | 		free(node->nodes); | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @@ -66,7 +66,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search ) | |||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( sw i = 0; i < node->nodes.num(); i++ ) | 	for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | ||||||
| 		{ | 		{ | ||||||
| @@ -76,7 +76,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search ) | |||||||
|  |  | ||||||
| 	if ( deep_search ) | 	if ( deep_search ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( sw i = 0; i < node->nodes.num(); i++ ) | 		for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			ADT_Node* res = adt_find( node->nodes + i, name, deep_search ); | 			ADT_Node* res = adt_find( node->nodes + i, name, deep_search ); | ||||||
|  |  | ||||||
| @@ -111,7 +111,7 @@ internal ADT_Node* _adt_get_value( ADT_Node* node, char const* value ) | |||||||
| 				file_stream_open( &tmp, heap(), ( u8* )back, size_of( back ), EFileStream_WRITABLE ); | 				file_stream_open( &tmp, heap(), ( u8* )back, size_of( back ), EFileStream_WRITABLE ); | ||||||
| 				adt_print_number( &tmp, node ); | 				adt_print_number( &tmp, node ); | ||||||
|  |  | ||||||
| 				sw  fsize = 0; | 				ssize  fsize = 0; | ||||||
| 				u8* buf   = file_stream_buf( &tmp, &fsize ); | 				u8* buf   = file_stream_buf( &tmp, &fsize ); | ||||||
|  |  | ||||||
| 				if ( ! str_compare( ( char const* )buf, value ) ) | 				if ( ! str_compare( ( char const* )buf, value ) ) | ||||||
| @@ -132,7 +132,7 @@ internal ADT_Node* _adt_get_value( ADT_Node* node, char const* value ) | |||||||
|  |  | ||||||
| internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value ) | internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value ) | ||||||
| { | { | ||||||
| 	for ( sw i = 0; i < node->nodes.num(); i++ ) | 	for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | 		if ( ! str_compare( node->nodes[ i ].name, name ) ) | ||||||
| 		{ | 		{ | ||||||
| @@ -207,7 +207,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 			/* run a value comparison against any child that is an object node */ | 			/* run a value comparison against any child that is an object node */ | ||||||
| 			else if ( node->type == EADT_TYPE_ARRAY ) | 			else if ( node->type == EADT_TYPE_ARRAY ) | ||||||
| 			{ | 			{ | ||||||
| 				for ( sw i = 0; i < node->nodes.num(); i++ ) | 				for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | ||||||
| 				{ | 				{ | ||||||
| 					ADT_Node* child = &node->nodes[ i ]; | 					ADT_Node* child = &node->nodes[ i ]; | ||||||
| 					if ( child->type != EADT_TYPE_OBJECT ) | 					if ( child->type != EADT_TYPE_OBJECT ) | ||||||
| @@ -225,7 +225,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 		/* [value] */ | 		/* [value] */ | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			for ( sw i = 0; i < node->nodes.num(); i++ ) | 			for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | ||||||
| 			{ | 			{ | ||||||
| 				ADT_Node* child = &node->nodes[ i ]; | 				ADT_Node* child = &node->nodes[ i ]; | ||||||
| 				if ( _adt_get_value( child, l_b2 ) ) | 				if ( _adt_get_value( child, l_b2 ) ) | ||||||
| @@ -256,8 +256,8 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 	/* handle array index lookup */ | 	/* handle array index lookup */ | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		sw idx = ( sw )str_to_i64( buf, NULL, 10 ); | 		ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); | ||||||
| 		if ( idx >= 0 && idx < node->nodes.num() ) | 		if ( idx >= 0 && idx < scast(ssize, num(node->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			found_node = &node->nodes[ idx ]; | 			found_node = &node->nodes[ idx ]; | ||||||
|  |  | ||||||
| @@ -272,7 +272,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 	return found_node; | 	return found_node; | ||||||
| } | } | ||||||
|  |  | ||||||
| ADT_Node* adt_alloc_at( ADT_Node* parent, sw index ) | ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index ) | ||||||
| { | { | ||||||
| 	if ( ! parent || ( parent->type != EADT_TYPE_OBJECT && parent->type != EADT_TYPE_ARRAY ) ) | 	if ( ! parent || ( parent->type != EADT_TYPE_OBJECT && parent->type != EADT_TYPE_ARRAY ) ) | ||||||
| 	{ | 	{ | ||||||
| @@ -282,12 +282,12 @@ ADT_Node* adt_alloc_at( ADT_Node* parent, sw index ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	if ( index < 0 || index > parent->nodes.num() ) | 	if ( index < 0 || index > scast(ssize, num(parent->nodes)) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	ADT_Node o = { 0 }; | 	ADT_Node o = { 0 }; | ||||||
| 	o.parent   = parent; | 	o.parent   = parent; | ||||||
| 	if ( ! parent->nodes.append_at( o, index ) ) | 	if ( ! append_at( parent->nodes, o, index ) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	return parent->nodes + index; | 	return parent->nodes + index; | ||||||
| @@ -303,7 +303,7 @@ ADT_Node* adt_alloc( ADT_Node* parent ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	return adt_alloc_at( parent, parent->nodes.num() ); | 	return adt_alloc_at( parent, num(parent->nodes) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing ) | b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing ) | ||||||
| @@ -337,7 +337,7 @@ b8 adt_set_int( ADT_Node* obj, char const* name, s64 value ) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, sw index ) | ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, ssize index ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	GEN_ASSERT_NOT_NULL( new_parent ); | 	GEN_ASSERT_NOT_NULL( new_parent ); | ||||||
| @@ -357,7 +357,7 @@ ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	GEN_ASSERT_NOT_NULL( new_parent ); | 	GEN_ASSERT_NOT_NULL( new_parent ); | ||||||
| 	GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT ); | 	GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT ); | ||||||
| 	return adt_move_node_at( node, new_parent, new_parent->nodes.num() ); | 	return adt_move_node_at( node, new_parent, num(new_parent->nodes) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) | void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) | ||||||
| @@ -366,8 +366,8 @@ void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( other_node ); | 	GEN_ASSERT_NOT_NULL( other_node ); | ||||||
| 	ADT_Node* parent                     = node->parent; | 	ADT_Node* parent                     = node->parent; | ||||||
| 	ADT_Node* other_parent               = other_node->parent; | 	ADT_Node* other_parent               = other_node->parent; | ||||||
| 	sw        index                      = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | 	ssize        index                      = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | ||||||
| 	sw        index2                     = ( pointer_diff( other_parent->nodes, other_node ) / size_of( ADT_Node ) ); | 	ssize        index2                     = ( pointer_diff( other_parent->nodes, other_node ) / size_of( ADT_Node ) ); | ||||||
| 	ADT_Node  temp                       = parent->nodes[ index ]; | 	ADT_Node  temp                       = parent->nodes[ index ]; | ||||||
| 	temp.parent                          = other_parent; | 	temp.parent                          = other_parent; | ||||||
| 	other_parent->nodes[ index2 ].parent = parent; | 	other_parent->nodes[ index2 ].parent = parent; | ||||||
| @@ -380,8 +380,8 @@ void adt_remove_node( ADT_Node* node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node ); | 	GEN_ASSERT_NOT_NULL( node ); | ||||||
| 	GEN_ASSERT_NOT_NULL( node->parent ); | 	GEN_ASSERT_NOT_NULL( node->parent ); | ||||||
| 	ADT_Node* parent = node->parent; | 	ADT_Node* parent = node->parent; | ||||||
| 	sw        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | 	ssize        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | ||||||
| 	parent->nodes.remove_at( index ); | 	remove_at( parent->nodes, index ); | ||||||
| } | } | ||||||
|  |  | ||||||
| ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | ||||||
| @@ -389,7 +389,7 @@ ADT_Node* adt_append_obj( ADT_Node* parent, char const* name ) | |||||||
| 	ADT_Node* o = adt_alloc( parent ); | 	ADT_Node* o = adt_alloc( parent ); | ||||||
| 	if ( ! o ) | 	if ( ! o ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if ( adt_set_obj( o, name, parent->nodes.get_header()->Allocator ) ) | 	if ( adt_set_obj( o, name, get_header(parent->nodes)->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -402,7 +402,7 @@ ADT_Node* adt_append_arr( ADT_Node* parent, char const* name ) | |||||||
| 	ADT_Node* o = adt_alloc( parent ); | 	ADT_Node* o = adt_alloc( parent ); | ||||||
| 	if ( ! o ) | 	if ( ! o ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	if ( adt_set_arr( o, name, parent->nodes.get_header()->Allocator ) ) | 	if ( adt_set_arr( o, name, get_header(parent->nodes)->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -447,7 +447,7 @@ char* adt_parse_number_strict( ADT_Node* node, char* base_str ) | |||||||
| 	while ( *e ) | 	while ( *e ) | ||||||
| 		++e; | 		++e; | ||||||
|  |  | ||||||
| 	while ( *p && ( str_find( "eE.+-", *p ) || char_is_hex_digit( *p ) ) ) | 	while ( *p && ( char_first_occurence( "eE.+-", *p ) || char_is_hex_digit( *p ) ) ) | ||||||
| 	{ | 	{ | ||||||
| 		++p; | 		++p; | ||||||
| 	} | 	} | ||||||
| @@ -476,7 +476,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	u8        node_props = 0; | 	u8        node_props = 0; | ||||||
|  |  | ||||||
| 	/* skip false positives and special cases */ | 	/* skip false positives and special cases */ | ||||||
| 	if ( ! ! str_find( "eE", *p ) || ( ! ! str_find( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) ) | 	if ( ! ! char_first_occurence( "eE", *p ) || ( ! ! char_first_occurence( ".+-", *p ) && ! char_is_hex_digit( *( p + 1 ) ) && *( p + 1 ) != '.' ) ) | ||||||
| 	{ | 	{ | ||||||
| 		return ++base_str; | 		return ++base_str; | ||||||
| 	} | 	} | ||||||
| @@ -484,7 +484,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	node_type = EADT_TYPE_INTEGER; | 	node_type = EADT_TYPE_INTEGER; | ||||||
| 	neg_zero  = false; | 	neg_zero  = false; | ||||||
|  |  | ||||||
| 	sw   ib        = 0; | 	ssize   ib        = 0; | ||||||
| 	char buf[ 48 ] = { 0 }; | 	char buf[ 48 ] = { 0 }; | ||||||
|  |  | ||||||
| 	if ( *e == '+' ) | 	if ( *e == '+' ) | ||||||
| @@ -550,9 +550,9 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
|  |  | ||||||
| 	f32  eb          = 10; | 	f32  eb          = 10; | ||||||
| 	char expbuf[ 6 ] = { 0 }; | 	char expbuf[ 6 ] = { 0 }; | ||||||
| 	sw   expi        = 0; | 	ssize   expi        = 0; | ||||||
|  |  | ||||||
| 	if ( *e && ! ! str_find( "eE", *e ) ) | 	if ( *e && ! ! char_first_occurence( "eE", *e ) ) | ||||||
| 	{ | 	{ | ||||||
| 		++e; | 		++e; | ||||||
| 		if ( *e == '+' || *e == '-' || char_is_digit( *e ) ) | 		if ( *e == '+' || *e == '-' || char_is_digit( *e ) ) | ||||||
| @@ -595,7 +595,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
|  |  | ||||||
| #ifndef GEN_PARSER_DISABLE_ANALYSIS | #ifndef GEN_PARSER_DISABLE_ANALYSIS | ||||||
| 		char *q = buf, *base_string = q, *base_string2 = q; | 		char *q = buf, *base_string = q, *base_string2 = q; | ||||||
| 		base_string           = zpl_cast( char* ) str_skip( base_string, '.' ); | 		base_string           = ccast( char*, str_skip( base_string, '.' )); | ||||||
| 		*base_string          = '\0'; | 		*base_string          = '\0'; | ||||||
| 		base_string2          = base_string + 1; | 		base_string2          = base_string + 1; | ||||||
| 		char* base_string_off = base_string2; | 		char* base_string_off = base_string2; | ||||||
| @@ -748,7 +748,7 @@ ADT_Error adt_print_string( FileInfo* file, ADT_Node* node, char const* escaped_ | |||||||
| 	{ | 	{ | ||||||
| 		p = str_skip_any( p, escaped_chars ); | 		p = str_skip_any( p, escaped_chars ); | ||||||
| 		_adt_fprintf( file, "%.*s", pointer_diff( b, p ), b ); | 		_adt_fprintf( file, "%.*s", pointer_diff( b, p ), b ); | ||||||
| 		if ( *p && ! ! str_find( escaped_chars, *p ) ) | 		if ( *p && ! ! char_first_occurence( escaped_chars, *p ) ) | ||||||
| 		{ | 		{ | ||||||
| 			_adt_fprintf( file, "%s%c", escape_symbol, *p ); | 			_adt_fprintf( file, "%s%c", escape_symbol, *p ); | ||||||
| 			p++; | 			p++; | ||||||
| @@ -816,13 +816,13 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	char* beginChar; | 	char* beginChar; | ||||||
| 	char* endChar; | 	char* endChar; | ||||||
|  |  | ||||||
| 	sw columnIndex       = 0; | 	ssize columnIndex       = 0; | ||||||
| 	sw totalColumnIndex = 0; | 	ssize totalColumnIndex = 0; | ||||||
|  |  | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		char delimiter = 0; | 		char delimiter = 0; | ||||||
| 		currentChar = zpl_cast( char* ) str_trim( currentChar, false ); | 		currentChar = ccast( char*, str_trim( currentChar, false )); | ||||||
|  |  | ||||||
| 		if ( *currentChar == 0 ) | 		if ( *currentChar == 0 ) | ||||||
| 			break; | 			break; | ||||||
| @@ -846,7 +846,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 		#endif | 		#endif | ||||||
| 			do | 			do | ||||||
| 			{ | 			{ | ||||||
| 				endChar = zpl_cast( char* ) str_skip( endChar, '"' ); | 				endChar = ccast( char*, str_skip( endChar, '"' )); | ||||||
|  |  | ||||||
| 				if ( *endChar && *( endChar + 1 ) == '"' ) | 				if ( *endChar && *( endChar + 1 ) == '"' ) | ||||||
| 				{ | 				{ | ||||||
| @@ -865,7 +865,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			*endChar    = 0; | 			*endChar    = 0; | ||||||
| 			currentChar = zpl_cast( char* ) str_trim( endChar + 1, true ); | 			currentChar = ccast( char*, str_trim( endChar + 1, true )); | ||||||
| 			delimiter   = * currentChar; | 			delimiter   = * currentChar; | ||||||
|  |  | ||||||
| 			/* unescape escaped quotes (so that unescaped text escapes :) */ | 			/* unescape escaped quotes (so that unescaped text escapes :) */ | ||||||
| @@ -902,7 +902,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
|  |  | ||||||
| 			if ( * endChar ) | 			if ( * endChar ) | ||||||
| 			{ | 			{ | ||||||
| 				currentChar = zpl_cast( char* ) str_trim( endChar, true ); | 				currentChar = ccast( char*, str_trim( endChar, true )); | ||||||
|  |  | ||||||
| 				while ( char_is_space( *( endChar - 1 ) ) ) | 				while ( char_is_space( *( endChar - 1 ) ) ) | ||||||
| 				{ | 				{ | ||||||
| @@ -946,12 +946,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( columnIndex >= root->nodes.num() ) | 		if ( columnIndex >= scast(ssize, num(root->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_append_arr( root, NULL ); | 			adt_append_arr( root, NULL ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		root->nodes[ columnIndex ].nodes.append( rowItem ); | 		append(root->nodes[ columnIndex ].nodes, rowItem ); | ||||||
|  |  | ||||||
| 		if ( delimiter == delim ) | 		if ( delimiter == delim ) | ||||||
| 		{ | 		{ | ||||||
| @@ -979,7 +979,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	} | 	} | ||||||
| 	while ( *currentChar ); | 	while ( *currentChar ); | ||||||
|  |  | ||||||
| 	if ( root->nodes.num() == 0 ) | 	if (num( root->nodes) == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		GEN_CSV_ASSERT( "unexpected end of input. stream is empty." ); | 		GEN_CSV_ASSERT( "unexpected end of input. stream is empty." ); | ||||||
| 		error = ECSV_Error__UNEXPECTED_END_OF_INPUT; | 		error = ECSV_Error__UNEXPECTED_END_OF_INPUT; | ||||||
| @@ -989,12 +989,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	/* consider first row as a header. */ | 	/* consider first row as a header. */ | ||||||
| 	if ( has_header ) | 	if ( has_header ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( sw i = 0; i < root->nodes.num(); i++ ) | 		for ( ssize i = 0; i < scast(ssize, num(root->nodes)); i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			CSV_Object* col = root->nodes + i; | 			CSV_Object* col = root->nodes + i; | ||||||
| 			CSV_Object* hdr = col->nodes; | 			CSV_Object* hdr = col->nodes; | ||||||
| 			col->name       = hdr->string; | 			col->name       = hdr->string; | ||||||
| 			col->nodes.remove_at( 0 ); | 			remove_at(col->nodes, 0 ); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1057,11 +1057,11 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter ) | |||||||
| 	GEN_ASSERT_NOT_NULL( file ); | 	GEN_ASSERT_NOT_NULL( file ); | ||||||
| 	GEN_ASSERT_NOT_NULL( obj ); | 	GEN_ASSERT_NOT_NULL( obj ); | ||||||
| 	GEN_ASSERT( obj->nodes ); | 	GEN_ASSERT( obj->nodes ); | ||||||
| 	sw cols = obj->nodes.num(); | 	ssize cols = num(obj->nodes); | ||||||
| 	if ( cols == 0 ) | 	if ( cols == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	sw rows = obj->nodes[ 0 ].nodes.num(); | 	ssize rows = num(obj->nodes[ 0 ].nodes); | ||||||
| 	if ( rows == 0 ) | 	if ( rows == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| @@ -1069,7 +1069,7 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter ) | |||||||
|  |  | ||||||
| 	if ( has_headers ) | 	if ( has_headers ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( sw i = 0; i < cols; i++ ) | 		for ( ssize i = 0; i < cols; i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			_csv_write_header( file, &obj->nodes[ i ] ); | 			_csv_write_header( file, &obj->nodes[ i ] ); | ||||||
| 			if ( i + 1 != cols ) | 			if ( i + 1 != cols ) | ||||||
| @@ -1080,9 +1080,9 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter ) | |||||||
| 		str_fmt_file( file, "\n" ); | 		str_fmt_file( file, "\n" ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( sw r = 0; r < rows; r++ ) | 	for ( ssize r = 0; r < rows; r++ ) | ||||||
| 	{ | 	{ | ||||||
| 		for ( sw i = 0; i < cols; i++ ) | 		for ( ssize i = 0; i < cols; i++ ) | ||||||
| 		{ | 		{ | ||||||
| 			_csv_write_record( file, &obj->nodes[ i ].nodes[ r ] ); | 			_csv_write_record( file, &obj->nodes[ i ].nodes[ r ] ); | ||||||
| 			if ( i + 1 != cols ) | 			if ( i + 1 != cols ) | ||||||
| @@ -1099,9 +1099,10 @@ String csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delimi | |||||||
| 	FileInfo tmp; | 	FileInfo tmp; | ||||||
| 	file_stream_new( &tmp, a ); | 	file_stream_new( &tmp, a ); | ||||||
| 	csv_write_delimiter( &tmp, obj, delimiter ); | 	csv_write_delimiter( &tmp, obj, delimiter ); | ||||||
| 	sw     fsize; |  | ||||||
|  | 	ssize  fsize; | ||||||
| 	u8*    buf    = file_stream_buf( &tmp, &fsize ); | 	u8*    buf    = file_stream_buf( &tmp, &fsize ); | ||||||
| 	String output = String::make_length( a, ( char* )buf, fsize ); | 	String output = string_make_length( a, ( char* )buf, fsize ); | ||||||
| 	file_close( &tmp ); | 	file_close( &tmp ); | ||||||
| 	return output; | 	return output; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -178,7 +178,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search ); | |||||||
| 	* @param index | 	* @param index | ||||||
| 	* @return zpl_adt_node * node | 	* @return zpl_adt_node * node | ||||||
| 	*/ | 	*/ | ||||||
| ADT_Node* adt_alloc_at( ADT_Node* parent, sw index ); | ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* @brief Allocate an unitialised node within a container. | 	* @brief Allocate an unitialised node within a container. | ||||||
| @@ -196,7 +196,7 @@ ADT_Node* adt_alloc( ADT_Node* parent ); | |||||||
| 	* @param index | 	* @param index | ||||||
| 	* @return zpl_adt_node * node | 	* @return zpl_adt_node * node | ||||||
| 	*/ | 	*/ | ||||||
| ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, sw index ); | ADT_Node* adt_move_node_at( ADT_Node* node, ADT_Node* new_parent, ssize index ); | ||||||
|  |  | ||||||
| /** | /** | ||||||
| 	* @brief Move an existing node to a new container. | 	* @brief Move an existing node to a new container. | ||||||
| @@ -400,31 +400,33 @@ enum CSV_Error : u32 | |||||||
|  |  | ||||||
| typedef ADT_Node CSV_Object; | typedef ADT_Node CSV_Object; | ||||||
|  |  | ||||||
| GEN_DEF_INLINE u8 csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header ); | u8   csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header ); | ||||||
| u8                csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header, char delim ); | u8   csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header, char delim ); | ||||||
| void              csv_free( CSV_Object* obj ); | void csv_free( CSV_Object* obj ); | ||||||
|  |  | ||||||
| GEN_DEF_INLINE void   csv_write( FileInfo* file, CSV_Object* obj ); | void   csv_write( FileInfo* file, CSV_Object* obj ); | ||||||
| GEN_DEF_INLINE String csv_write_string( AllocatorInfo a, CSV_Object* obj ); | String csv_write_string( AllocatorInfo a, CSV_Object* obj ); | ||||||
| void                  csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delim ); | void   csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delim ); | ||||||
| String                csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delim ); | String csv_write_string_delimiter( AllocatorInfo a, CSV_Object* obj, char delim ); | ||||||
|  |  | ||||||
| /* inline */ | /* inline */ | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE u8 csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header ) | inline | ||||||
|  | u8 csv_parse( CSV_Object* root, char* text, AllocatorInfo allocator, b32 has_header ) | ||||||
| { | { | ||||||
| 	return csv_parse_delimiter( root, text, allocator, has_header, ',' ); | 	return csv_parse_delimiter( root, text, allocator, has_header, ',' ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void csv_write( FileInfo* file, CSV_Object* obj ) | inline | ||||||
|  | void csv_write( FileInfo* file, CSV_Object* obj ) | ||||||
| { | { | ||||||
| 	csv_write_delimiter( file, obj, ',' ); | 	csv_write_delimiter( file, obj, ',' ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE String csv_write_string( AllocatorInfo a, CSV_Object* obj ) | inline | ||||||
|  | String csv_write_string( AllocatorInfo a, CSV_Object* obj ) | ||||||
| { | { | ||||||
| 	return csv_write_string_delimiter( a, obj, ',' ); | 	return csv_write_string_delimiter( a, obj, ',' ); | ||||||
| } | } | ||||||
|  |  | ||||||
| #pragma endregion CSV | #pragma endregion CSV | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,6 @@ | |||||||
| #pragma once | #ifdef GEN_INTELLISENSE_DIRECTIVES | ||||||
|  | #	pragma once | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #pragma region Platform Detection | #pragma region Platform Detection | ||||||
| 
 | 
 | ||||||
| @@ -74,13 +76,18 @@ | |||||||
| /* Platform compiler */ | /* Platform compiler */ | ||||||
| 
 | 
 | ||||||
| #if defined( _MSC_VER ) | #if defined( _MSC_VER ) | ||||||
| #	define GEN_COMPILER_MSVC 1 | #	define GEN_COMPILER_CLANG 0 | ||||||
|  | #	define GEN_COMPILER_MSVC  1 | ||||||
|  | #	define GEN_COMPILER_GCC   0 | ||||||
| #elif defined( __GNUC__ ) | #elif defined( __GNUC__ ) | ||||||
| #	define GEN_COMPILER_GCC 1 | #	define GEN_COMPILER_CLANG 0 | ||||||
|  | #	define GEN_COMPILER_MSVC  0 | ||||||
|  | #	define GEN_COMPILER_GCC   1 | ||||||
| #elif defined( __clang__ ) | #elif defined( __clang__ ) | ||||||
| #	define GEN_COMPILER_CLANG 1 | #	define GEN_COMPILER_CLANG 1 | ||||||
| #elif defined( __MINGW32__ ) | #	define GEN_COMPILER_MSVC  0 | ||||||
| #	define GEN_COMPILER_MINGW 1 | #	define GEN_COMPILER_GCC   1 | ||||||
|  | #else | ||||||
| #	error Unknown compiler | #	error Unknown compiler | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| @@ -99,8 +106,13 @@ | |||||||
| #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #define GEN_DEF_INLINE  static | #ifndef GEN_COMPILER_C | ||||||
| #define GEN_IMPL_INLINE static inline | #	if defined(__STDC_VERSION__) | ||||||
|  | #		define GEN_COMPILER_C 1 | ||||||
|  | #	else | ||||||
|  | #		define GEN_COMPILER_C 0 | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #pragma endregion Platform Detection | #pragma endregion Platform Detection | ||||||
| 
 | 
 | ||||||
| @@ -115,11 +127,23 @@ | |||||||
| 
 | 
 | ||||||
| #pragma endregion Mandatory Includes | #pragma endregion Mandatory Includes | ||||||
| 
 | 
 | ||||||
| #ifdef GEN_DONT_USE_NAMESPACE | #if GEN_DONT_USE_NAMESPACE | ||||||
| #	define GEN_NS | #	if GEN_COMPILER_C | ||||||
| #	define GEN_NS_BEGIN | #		define GEN_NS_ENUM_BEGIN | ||||||
| #	define GEN_NS_END | #		define GEN_NS_ENUM_END | ||||||
|  | #		define GEN_NS | ||||||
|  | #		define GEN_NS_BEGIN | ||||||
|  | #		define GEN_NS_END | ||||||
|  | #	else | ||||||
|  | #		define GEN_NS_ENUM_BEGIN namespace gen_internal_enums { | ||||||
|  | #		define GEN_NS_ENUM_END   } | ||||||
|  | #		define GEN_NS       :: | ||||||
|  | #		define GEN_NS_BEGIN | ||||||
|  | #		define GEN_NS_END | ||||||
|  | #	endif | ||||||
| #else | #else | ||||||
|  | #	define GEN_NS_ENUM_BEGIN namespace gen_internal_enums { | ||||||
|  | #	define GEN_NS_ENUM_END   } | ||||||
| #	define GEN_NS       gen:: | #	define GEN_NS       gen:: | ||||||
| #	define GEN_NS_BEGIN namespace gen { | #	define GEN_NS_BEGIN namespace gen { | ||||||
| #	define GEN_NS_END   } | #	define GEN_NS_END   } | ||||||
| @@ -41,10 +41,10 @@ struct _format_info | |||||||
| 	s32 precision; | 	s32 precision; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| internal sw _print_string( char* text, sw max_len, _format_info* info, char const* str ) | internal ssize _print_string( char* text, ssize max_len, _format_info* info, char const* str ) | ||||||
| { | { | ||||||
| 	sw    res = 0, len = 0; | 	ssize    res = 0, len = 0; | ||||||
| 	sw    remaining = max_len; | 	ssize    remaining = max_len; | ||||||
| 	char* begin     = text; | 	char* begin     = text; | ||||||
|  |  | ||||||
| 	if ( str == NULL && max_len >= 6 ) | 	if ( str == NULL && max_len >= 6 ) | ||||||
| @@ -75,7 +75,7 @@ internal sw _print_string( char* text, sw max_len, _format_info* info, char cons | |||||||
|  |  | ||||||
| 		if ( info->width > res ) | 		if ( info->width > res ) | ||||||
| 		{ | 		{ | ||||||
| 			sw padding = info->width - len; | 			ssize padding = info->width - len; | ||||||
|  |  | ||||||
| 			char pad = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; | 			char pad = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; | ||||||
| 			while ( padding-- > 0 && remaining-- > 0 ) | 			while ( padding-- > 0 && remaining-- > 0 ) | ||||||
| @@ -86,7 +86,7 @@ internal sw _print_string( char* text, sw max_len, _format_info* info, char cons | |||||||
| 	{ | 	{ | ||||||
| 		if ( info && ( info->width > res ) ) | 		if ( info && ( info->width > res ) ) | ||||||
| 		{ | 		{ | ||||||
| 			sw   padding = info->width - len; | 			ssize   padding = info->width - len; | ||||||
| 			char pad     = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; | 			char pad     = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; | ||||||
| 			while ( padding-- > 0 && remaining-- > 0 ) | 			while ( padding-- > 0 && remaining-- > 0 ) | ||||||
| 				*text++ = pad, res++; | 				*text++ = pad, res++; | ||||||
| @@ -108,16 +108,16 @@ internal sw _print_string( char* text, sw max_len, _format_info* info, char cons | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal sw _print_char( char* text, sw max_len, _format_info* info, char arg ) | internal ssize _print_char( char* text, ssize max_len, _format_info* info, char arg ) | ||||||
| { | { | ||||||
| 	char str[ 2 ] = ""; | 	char str[ 2 ] = ""; | ||||||
| 	str[ 0 ]      = arg; | 	str[ 0 ]      = arg; | ||||||
| 	return _print_string( text, max_len, info, str ); | 	return _print_string( text, max_len, info, str ); | ||||||
| } | } | ||||||
|  |  | ||||||
| internal sw _print_repeated_char( char* text, sw max_len, _format_info* info, char arg ) | internal ssize _print_repeated_char( char* text, ssize max_len, _format_info* info, char arg ) | ||||||
| { | { | ||||||
| 	sw  res = 0; | 	ssize  res = 0; | ||||||
| 	s32 rem = ( info ) ? ( info->width > 0 ) ? info->width : 1 : 1; | 	s32 rem = ( info ) ? ( info->width > 0 ) ? info->width : 1 : 1; | ||||||
| 	res     = rem; | 	res     = rem; | ||||||
| 	while ( rem-- > 0 ) | 	while ( rem-- > 0 ) | ||||||
| @@ -126,24 +126,24 @@ internal sw _print_repeated_char( char* text, sw max_len, _format_info* info, ch | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| internal sw _print_i64( char* text, sw max_len, _format_info* info, s64 value ) | internal ssize _print_i64( char* text, ssize max_len, _format_info* info, s64 value ) | ||||||
| { | { | ||||||
| 	char num[ 130 ]; | 	char num[ 130 ]; | ||||||
| 	i64_to_str( value, num, info ? info->base : 10 ); | 	i64_to_str( value, num, info ? info->base : 10 ); | ||||||
| 	return _print_string( text, max_len, info, num ); | 	return _print_string( text, max_len, info, num ); | ||||||
| } | } | ||||||
|  |  | ||||||
| internal sw _print_u64( char* text, sw max_len, _format_info* info, u64 value ) | internal ssize _print_u64( char* text, ssize max_len, _format_info* info, u64 value ) | ||||||
| { | { | ||||||
| 	char num[ 130 ]; | 	char num[ 130 ]; | ||||||
| 	u64_to_str( value, num, info ? info->base : 10 ); | 	u64_to_str( value, num, info ? info->base : 10 ); | ||||||
| 	return _print_string( text, max_len, info, num ); | 	return _print_string( text, max_len, info, num ); | ||||||
| } | } | ||||||
|  |  | ||||||
| internal sw _print_f64( char* text, sw max_len, _format_info* info, b32 is_hexadecimal, f64 arg ) | internal ssize _print_f64( char* text, ssize max_len, _format_info* info, b32 is_hexadecimal, f64 arg ) | ||||||
| { | { | ||||||
| 	// TODO: Handle exponent notation | 	// TODO: Handle exponent notation | ||||||
| 	sw    width, len, remaining = max_len; | 	ssize    width, len, remaining = max_len; | ||||||
| 	char* text_begin = text; | 	char* text_begin = text; | ||||||
|  |  | ||||||
| 	if ( arg ) | 	if ( arg ) | ||||||
| @@ -163,7 +163,7 @@ internal sw _print_f64( char* text, sw max_len, _format_info* info, b32 is_hexad | |||||||
| 			text++; | 			text++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		value  = zpl_cast( u64 ) arg; | 		value  = scast( u64, arg); | ||||||
| 		len    = _print_u64( text, remaining, NULL, value ); | 		len    = _print_u64( text, remaining, NULL, value ); | ||||||
| 		text  += len; | 		text  += len; | ||||||
|  |  | ||||||
| @@ -184,14 +184,14 @@ internal sw _print_f64( char* text, sw max_len, _format_info* info, b32 is_hexad | |||||||
| 			text++; | 			text++; | ||||||
| 			while ( info->precision-- > 0 ) | 			while ( info->precision-- > 0 ) | ||||||
| 			{ | 			{ | ||||||
| 				value  = zpl_cast( u64 )( arg * mult ); | 				value  = scast( u64, arg * mult ); | ||||||
| 				len    = _print_u64( text, remaining, NULL, value ); | 				len    = _print_u64( text, remaining, NULL, value ); | ||||||
| 				text  += len; | 				text  += len; | ||||||
| 				if ( len >= remaining ) | 				if ( len >= remaining ) | ||||||
| 					remaining = min( remaining, 1 ); | 					remaining = min( remaining, 1 ); | ||||||
| 				else | 				else | ||||||
| 					remaining -= len; | 					remaining -= len; | ||||||
| 				arg  -= zpl_cast( f64 ) value / mult; | 				arg  -= scast( f64, value / mult); | ||||||
| 				mult *= 10; | 				mult *= 10; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -239,15 +239,15 @@ internal sw _print_f64( char* text, sw max_len, _format_info* info, b32 is_hexad | |||||||
| 	return ( text - text_begin ); | 	return ( text - text_begin ); | ||||||
| } | } | ||||||
|  |  | ||||||
| neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_list va ) | ||||||
| { | { | ||||||
| 	char const* text_begin = text; | 	char const* text_begin = text; | ||||||
| 	sw          remaining  = max_len, res; | 	ssize          remaining  = max_len, res; | ||||||
|  |  | ||||||
| 	while ( *fmt ) | 	while ( *fmt ) | ||||||
| 	{ | 	{ | ||||||
| 		_format_info info = { 0 }; | 		_format_info info = { 0 }; | ||||||
| 		sw           len  = 0; | 		ssize           len  = 0; | ||||||
| 		info.precision    = -1; | 		info.precision    = -1; | ||||||
|  |  | ||||||
| 		while ( *fmt && *fmt != '%' && remaining ) | 		while ( *fmt && *fmt != '%' && remaining ) | ||||||
| @@ -311,7 +311,7 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			info.width = zpl_cast( s32 ) str_to_i64( fmt, zpl_cast( char** ) & fmt, 10 ); | 			info.width = scast( s32, str_to_i64( fmt, ccast( char**, & fmt), 10 )); | ||||||
| 			if ( info.width != 0 ) | 			if ( info.width != 0 ) | ||||||
| 			{ | 			{ | ||||||
| 				info.flags |= GEN_FMT_WIDTH; | 				info.flags |= GEN_FMT_WIDTH; | ||||||
| @@ -329,7 +329,7 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				info.precision = zpl_cast( s32 ) str_to_i64( fmt, zpl_cast( char** ) & fmt, 10 ); | 				info.precision = scast( s32, str_to_i64( fmt, ccast( char**, & fmt), 10 )); | ||||||
| 			} | 			} | ||||||
| 			info.flags &= ~GEN_FMT_ZERO; | 			info.flags &= ~GEN_FMT_ZERO; | ||||||
| 		} | 		} | ||||||
| @@ -411,7 +411,7 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			case 'c' : | 			case 'c' : | ||||||
| 				len = _print_char( text, remaining, &info, zpl_cast( char ) va_arg( va, int ) ); | 				len = _print_char( text, remaining, &info, scast( char, va_arg( va, int ) )); | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| 			case 's' : | 			case 's' : | ||||||
| @@ -422,7 +422,7 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 			{ | 			{ | ||||||
| 				String gen_str = String { va_arg( va, char*) }; | 				String gen_str = String { va_arg( va, char*) }; | ||||||
|  |  | ||||||
| 				info.precision = gen_str.length(); | 				info.precision = length(gen_str); | ||||||
| 				len            = _print_string( text, remaining, &info, gen_str ); | 				len            = _print_string( text, remaining, &info, gen_str ); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| @@ -455,25 +455,25 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 				switch ( info.flags & GEN_FMT_INTS ) | 				switch ( info.flags & GEN_FMT_INTS ) | ||||||
| 				{ | 				{ | ||||||
| 					case GEN_FMT_CHAR : | 					case GEN_FMT_CHAR : | ||||||
| 						value = zpl_cast( u64 ) zpl_cast( u8 ) va_arg( va, int ); | 						value = scast( u64, scast( u8, va_arg( va, int ))); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_SHORT : | 					case GEN_FMT_SHORT : | ||||||
| 						value = zpl_cast( u64 ) zpl_cast( u16 ) va_arg( va, int ); | 						value = scast( u64, scast( u16, va_arg( va, int ))); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_LONG : | 					case GEN_FMT_LONG: | ||||||
| 						value = zpl_cast( u64 ) va_arg( va, unsigned long ); | 						value = scast( u64, va_arg( va, unsigned long )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_LLONG : | 					case GEN_FMT_LLONG : | ||||||
| 						value = zpl_cast( u64 ) va_arg( va, unsigned long long ); | 						value = scast( u64, va_arg( va, unsigned long long )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_SIZE : | 					case GEN_FMT_SIZE : | ||||||
| 						value = zpl_cast( u64 ) va_arg( va, uw ); | 						value = scast( u64, va_arg( va, usize )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_INTPTR : | 					case GEN_FMT_INTPTR : | ||||||
| 						value = zpl_cast( u64 ) va_arg( va, uptr ); | 						value = scast( u64, va_arg( va, uptr )); | ||||||
| 						break; | 						break; | ||||||
| 					default : | 					default : | ||||||
| 						value = zpl_cast( u64 ) va_arg( va, unsigned int ); | 						value = scast( u64, va_arg( va, unsigned int )); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -485,25 +485,25 @@ neverinline sw str_fmt_va( char* text, sw max_len, char const* fmt, va_list va ) | |||||||
| 				switch ( info.flags & GEN_FMT_INTS ) | 				switch ( info.flags & GEN_FMT_INTS ) | ||||||
| 				{ | 				{ | ||||||
| 					case GEN_FMT_CHAR : | 					case GEN_FMT_CHAR : | ||||||
| 						value = zpl_cast( s64 ) zpl_cast( s8 ) va_arg( va, int ); | 						value = scast( s64, scast( s8, va_arg( va, int ))); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_SHORT : | 					case GEN_FMT_SHORT : | ||||||
| 						value = zpl_cast( s64 ) zpl_cast( s16 ) va_arg( va, int ); | 						value = scast( s64, scast( s16, va_arg( va, int ))); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_LONG : | 					case GEN_FMT_LONG : | ||||||
| 						value = zpl_cast( s64 ) va_arg( va, long ); | 						value = scast( s64, va_arg( va, long )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_LLONG : | 					case GEN_FMT_LLONG : | ||||||
| 						value = zpl_cast( s64 ) va_arg( va, long long ); | 						value = scast( s64, va_arg( va, long long )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_SIZE : | 					case GEN_FMT_SIZE : | ||||||
| 						value = zpl_cast( s64 ) va_arg( va, uw ); | 						value = scast( s64, va_arg( va, usize )); | ||||||
| 						break; | 						break; | ||||||
| 					case GEN_FMT_INTPTR : | 					case GEN_FMT_INTPTR : | ||||||
| 						value = zpl_cast( s64 ) va_arg( va, uptr ); | 						value = scast( s64, va_arg( va, uptr )); | ||||||
| 						break; | 						break; | ||||||
| 					default : | 					default : | ||||||
| 						value = zpl_cast( s64 ) va_arg( va, int ); | 						value = scast( s64, va_arg( va, int )); | ||||||
| 						break; | 						break; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -540,17 +540,17 @@ char* str_fmt_buf( char const* fmt, ... ) | |||||||
| 	return str; | 	return str; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt_file_va( struct FileInfo* f, char const* fmt, va_list va ) | ssize str_fmt_file_va( struct FileInfo* f, char const* fmt, va_list va ) | ||||||
| { | { | ||||||
| 	local_persist thread_local char buf[ GEN_PRINTF_MAXLEN ]; | 	local_persist thread_local char buf[ GEN_PRINTF_MAXLEN ]; | ||||||
| 	sw                              len = str_fmt_va( buf, size_of( buf ), fmt, va ); | 	ssize                              len = str_fmt_va( buf, size_of( buf ), fmt, va ); | ||||||
| 	b32                             res = file_write( f, buf, len - 1 );    // NOTE: prevent extra whitespace | 	b32                             res = file_write( f, buf, len - 1 );    // NOTE: prevent extra whitespace | ||||||
| 	return res ? len : -1; | 	return res ? len : -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt_file( struct FileInfo* f, char const* fmt, ... ) | ssize str_fmt_file( struct FileInfo* f, char const* fmt, ... ) | ||||||
| { | { | ||||||
| 	sw      res; | 	ssize      res; | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start( va, fmt ); | 	va_start( va, fmt ); | ||||||
| 	res = str_fmt_file_va( f, fmt, va ); | 	res = str_fmt_file_va( f, fmt, va ); | ||||||
| @@ -558,9 +558,9 @@ sw str_fmt_file( struct FileInfo* f, char const* fmt, ... ) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt( char* str, sw n, char const* fmt, ... ) | ssize str_fmt( char* str, ssize n, char const* fmt, ... ) | ||||||
| { | { | ||||||
| 	sw      res; | 	ssize      res; | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start( va, fmt ); | 	va_start( va, fmt ); | ||||||
| 	res = str_fmt_va( str, n, fmt, va ); | 	res = str_fmt_va( str, n, fmt, va ); | ||||||
| @@ -568,19 +568,19 @@ sw str_fmt( char* str, sw n, char const* fmt, ... ) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt_out_va( char const* fmt, va_list va ) | ssize str_fmt_out_va( char const* fmt, va_list va ) | ||||||
| { | { | ||||||
| 	return str_fmt_file_va( file_get_standard( EFileStandard_OUTPUT ), fmt, va ); | 	return str_fmt_file_va( file_get_standard( EFileStandard_OUTPUT ), fmt, va ); | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt_out_err_va( char const* fmt, va_list va ) | ssize str_fmt_out_err_va( char const* fmt, va_list va ) | ||||||
| { | { | ||||||
| 	return str_fmt_file_va( file_get_standard( EFileStandard_ERROR ), fmt, va ); | 	return str_fmt_file_va( file_get_standard( EFileStandard_ERROR ), fmt, va ); | ||||||
| } | } | ||||||
|  |  | ||||||
| sw str_fmt_out_err( char const* fmt, ... ) | ssize str_fmt_out_err( char const* fmt, ... ) | ||||||
| { | { | ||||||
| 	sw      res; | 	ssize      res; | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start( va, fmt ); | 	va_start( va, fmt ); | ||||||
| 	res = str_fmt_out_err_va( fmt, va ); | 	res = str_fmt_out_err_va( fmt, va ); | ||||||
|   | |||||||
| @@ -12,23 +12,23 @@ struct FileInfo; | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // NOTE: A locally persisting buffer is used internally | // NOTE: A locally persisting buffer is used internally | ||||||
| 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           ( char* str, sw n, char const* fmt, ... ); | ssize  str_fmt           ( char* str, ssize n, char const* fmt, ... ); | ||||||
| sw    str_fmt_va        ( char* str, sw n, char const* fmt, va_list va ); | ssize  str_fmt_va        ( char* str, ssize n, char const* fmt, va_list va ); | ||||||
| sw    str_fmt_out_va    ( char const* fmt, va_list va ); | ssize  str_fmt_out_va    ( char const* fmt, va_list va ); | ||||||
| sw    str_fmt_out_err   ( char const* fmt, ... ); | ssize  str_fmt_out_err   ( char const* fmt, ... ); | ||||||
| sw    str_fmt_out_err_va( char const* fmt, va_list va ); | ssize  str_fmt_out_err_va( char const* fmt, va_list va ); | ||||||
| sw    str_fmt_file      ( FileInfo* f, char const* fmt, ... ); | ssize  str_fmt_file      ( FileInfo* f, char const* fmt, ... ); | ||||||
| sw    str_fmt_file_va   ( FileInfo* f, char const* fmt, va_list va ); | ssize  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"; | ||||||
|  |  | ||||||
| inline | inline | ||||||
| sw log_fmt(char const* fmt, ...) | ssize log_fmt(char const* fmt, ...) | ||||||
| { | { | ||||||
| 	sw res; | 	ssize res; | ||||||
| 	va_list va; | 	va_list va; | ||||||
|  |  | ||||||
| 	va_start(va, fmt); | 	va_start(va, fmt); | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| #pragma region String Ops | #pragma region String Ops | ||||||
|  |  | ||||||
| internal | internal | ||||||
| sw _scan_zpl_i64( const char* text, s32 base, s64* value ) | ssize _scan_zpl_i64( const char* text, s32 base, s64* value ) | ||||||
| { | { | ||||||
| 	const char* text_begin = text; | 	const char* text_begin = text; | ||||||
| 	s64         result     = 0; | 	s64         result     = 0; | ||||||
| @@ -56,7 +56,7 @@ global const char _num_to_char_table[] = | |||||||
|  |  | ||||||
| s64 str_to_i64( const char* str, char** end_ptr, s32 base ) | s64 str_to_i64( const char* str, char** end_ptr, s32 base ) | ||||||
| { | { | ||||||
| 	sw  len; | 	ssize  len; | ||||||
| 	s64 value; | 	s64 value; | ||||||
|  |  | ||||||
| 	if ( ! base ) | 	if ( ! base ) | ||||||
| @@ -85,7 +85,7 @@ void i64_to_str( s64 value, char* string, s32 base ) | |||||||
| 		value    = -value; | 		value    = -value; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v = zpl_cast( u64 ) value; | 	v = scast( u64, value); | ||||||
| 	if ( v != 0 ) | 	if ( v != 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		while ( v > 0 ) | 		while ( v > 0 ) | ||||||
| @@ -207,7 +207,7 @@ f64 str_to_f64( const char* str, char** end_ptr ) | |||||||
| 	result = sign * ( frac ? ( value / scale ) : ( value * scale ) ); | 	result = sign * ( frac ? ( value / scale ) : ( value * scale ) ); | ||||||
|  |  | ||||||
| 	if ( end_ptr ) | 	if ( end_ptr ) | ||||||
| 		*end_ptr = zpl_cast( char* ) str; | 		* end_ptr = rcast( char*, ccast(char*, str) ); | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,41 +5,41 @@ | |||||||
|  |  | ||||||
| #pragma region String Ops | #pragma region String Ops | ||||||
|  |  | ||||||
| GEN_DEF_INLINE const char* char_first_occurence( const char* str, char c ); | 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 ); | b32   char_is_alpha( char c ); | ||||||
| GEN_DEF_INLINE b32   char_is_alphanumeric( char c ); | b32   char_is_alphanumeric( char c ); | ||||||
| GEN_DEF_INLINE b32   char_is_digit( char c ); | b32   char_is_digit( char c ); | ||||||
| GEN_DEF_INLINE b32   char_is_hex_digit( char c ); | b32   char_is_hex_digit( char c ); | ||||||
| GEN_DEF_INLINE b32   char_is_space( char c ); | b32   char_is_space( char c ); | ||||||
| GEN_DEF_INLINE char  char_to_lower( char c ); | char  char_to_lower( char c ); | ||||||
| GEN_DEF_INLINE char  char_to_upper( char c ); | char  char_to_upper( char c ); | ||||||
|  |  | ||||||
| GEN_DEF_INLINE s32  digit_to_int( char c ); | s32  digit_to_int( char c ); | ||||||
| GEN_DEF_INLINE s32  hex_digit_to_int( char c ); | s32  hex_digit_to_int( char c ); | ||||||
|  |  | ||||||
| GEN_DEF_INLINE s32         str_compare( const char* s1, const char* s2 ); | s32         str_compare( const char* s1, const char* s2 ); | ||||||
| GEN_DEF_INLINE s32         str_compare( const char* s1, const char* s2, sw len ); | s32         str_compare( const char* s1, const char* s2, ssize len ); | ||||||
| GEN_DEF_INLINE char*       str_copy( char* dest, const char* source, sw len ); | char*       str_copy( char* dest, const char* source, ssize len ); | ||||||
| GEN_DEF_INLINE sw          str_copy_nulpad( char* dest, const char* source, sw len ); | ssize       str_copy_nulpad( char* dest, const char* source, ssize len ); | ||||||
| GEN_DEF_INLINE sw          str_len( const char* str ); | ssize       str_len( const char* str ); | ||||||
| GEN_DEF_INLINE sw          str_len( const char* str, sw max_len ); | ssize       str_len( const char* str, ssize max_len ); | ||||||
| GEN_DEF_INLINE char*       str_reverse( char* str );    // NOTE: ASCII only | char*       str_reverse( char* str );    // NOTE: ASCII only | ||||||
| GEN_DEF_INLINE char const* str_skip( char const* str, char c ); | char const* str_skip( char const* str, char c ); | ||||||
| GEN_DEF_INLINE char const* str_skip_any( char const* str, char const* char_list ); | char const* str_skip_any( char const* str, char const* char_list ); | ||||||
| GEN_DEF_INLINE char const* str_trim( char const* str, b32 catch_newline ); | char const* str_trim( char const* str, b32 catch_newline ); | ||||||
|  |  | ||||||
| // NOTE: ASCII only | // NOTE: ASCII only | ||||||
| GEN_DEF_INLINE void str_to_lower( char* str ); | void str_to_lower( char* str ); | ||||||
| GEN_DEF_INLINE void str_to_upper( char* str ); | void str_to_upper( char* str ); | ||||||
|  |  | ||||||
| s64  str_to_i64( const char* str, char** end_ptr, s32 base ); | 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 ); | f64  str_to_f64( const char* str, char** end_ptr ); | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE const char* char_first_occurence( const char* s, char c ) | inline | ||||||
|  | const char* char_first_occurence( const char* s, char c ) | ||||||
| { | { | ||||||
| 	char ch = c; | 	char ch = c; | ||||||
| 	for ( ; *s != ch; s++ ) | 	for ( ; *s != ch; s++ ) | ||||||
| @@ -50,59 +50,67 @@ GEN_IMPL_INLINE const char* char_first_occurence( const char* s, char c ) | |||||||
| 	return s; | 	return s; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 char_is_alpha( char c ) | inline | ||||||
|  | b32 char_is_alpha( char c ) | ||||||
| { | { | ||||||
| 	if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) ) | 	if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) ) | ||||||
| 		return true; | 		return true; | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 char_is_alphanumeric( char c ) | inline | ||||||
|  | b32 char_is_alphanumeric( char c ) | ||||||
| { | { | ||||||
| 	return char_is_alpha( c ) || char_is_digit( c ); | 	return char_is_alpha( c ) || char_is_digit( c ); | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 char_is_digit( char c ) | inline | ||||||
|  | b32 char_is_digit( char c ) | ||||||
| { | { | ||||||
| 	if ( c >= '0' && c <= '9' ) | 	if ( c >= '0' && c <= '9' ) | ||||||
| 		return true; | 		return true; | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 char_is_hex_digit( char c ) | inline | ||||||
|  | b32 char_is_hex_digit( char c ) | ||||||
| { | { | ||||||
| 	if ( char_is_digit( c ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) ) | 	if ( char_is_digit( c ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) ) | ||||||
| 		return true; | 		return true; | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE b32 char_is_space( char c ) | inline | ||||||
|  | b32 char_is_space( char c ) | ||||||
| { | { | ||||||
| 	if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' ) | 	if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' ) | ||||||
| 		return true; | 		return true; | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char char_to_lower( char c ) | inline | ||||||
|  | char char_to_lower( char c ) | ||||||
| { | { | ||||||
| 	if ( c >= 'A' && c <= 'Z' ) | 	if ( c >= 'A' && c <= 'Z' ) | ||||||
| 		return 'a' + ( c - 'A' ); | 		return 'a' + ( c - 'A' ); | ||||||
| 	return c; | 	return c; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char char_to_upper( char c ) | inline char char_to_upper( char c ) | ||||||
| { | { | ||||||
| 	if ( c >= 'a' && c <= 'z' ) | 	if ( c >= 'a' && c <= 'z' ) | ||||||
| 		return 'A' + ( c - 'a' ); | 		return 'A' + ( c - 'a' ); | ||||||
| 	return c; | 	return c; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s32 digit_to_int( char c ) | inline | ||||||
|  | s32 digit_to_int( char c ) | ||||||
| { | { | ||||||
| 	return char_is_digit( c ) ? c - '0' : c - 'W'; | 	return char_is_digit( c ) ? c - '0' : c - 'W'; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s32 hex_digit_to_int( char c ) | inline | ||||||
|  | s32 hex_digit_to_int( char c ) | ||||||
| { | { | ||||||
| 	if ( char_is_digit( c ) ) | 	if ( char_is_digit( c ) ) | ||||||
| 		return digit_to_int( c ); | 		return digit_to_int( c ); | ||||||
| @@ -113,7 +121,8 @@ GEN_IMPL_INLINE s32 hex_digit_to_int( char c ) | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s32 str_compare( const char* s1, const char* s2 ) | inline | ||||||
|  | s32 str_compare( const char* s1, const char* s2 ) | ||||||
| { | { | ||||||
| 	while ( *s1 && ( *s1 == *s2 ) ) | 	while ( *s1 && ( *s1 == *s2 ) ) | ||||||
| 	{ | 	{ | ||||||
| @@ -122,7 +131,8 @@ GEN_IMPL_INLINE s32 str_compare( const char* s1, const char* s2 ) | |||||||
| 	return *( u8* )s1 - *( u8* )s2; | 	return *( u8* )s1 - *( u8* )s2; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE s32 str_compare( const char* s1, const char* s2, sw len ) | inline | ||||||
|  | s32 str_compare( const char* s1, const char* s2, ssize len ) | ||||||
| { | { | ||||||
| 	for ( ; len > 0; s1++, s2++, len-- ) | 	for ( ; len > 0; s1++, s2++, len-- ) | ||||||
| 	{ | 	{ | ||||||
| @@ -134,7 +144,8 @@ GEN_IMPL_INLINE s32 str_compare( const char* s1, const char* s2, sw len ) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char* str_copy( char* dest, const char* source, sw len ) | inline | ||||||
|  | char* str_copy( char* dest, const char* source, ssize len ) | ||||||
| { | { | ||||||
| 	GEN_ASSERT_NOT_NULL( dest ); | 	GEN_ASSERT_NOT_NULL( dest ); | ||||||
| 	if ( source ) | 	if ( source ) | ||||||
| @@ -154,9 +165,10 @@ GEN_IMPL_INLINE char* str_copy( char* dest, const char* source, sw len ) | |||||||
| 	return dest; | 	return dest; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE sw str_copy_nulpad( char* dest, const char* source, sw len ) | inline | ||||||
|  | ssize str_copy_nulpad( char* dest, const char* source, ssize len ) | ||||||
| { | { | ||||||
| 	sw result = 0; | 	ssize result = 0; | ||||||
| 	GEN_ASSERT_NOT_NULL( dest ); | 	GEN_ASSERT_NOT_NULL( dest ); | ||||||
| 	if ( source ) | 	if ( source ) | ||||||
| 	{ | 	{ | ||||||
| @@ -178,7 +190,8 @@ GEN_IMPL_INLINE sw str_copy_nulpad( char* dest, const char* source, sw len ) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE sw str_len( const char* str ) | inline | ||||||
|  | ssize str_len( const char* str ) | ||||||
| { | { | ||||||
| 	if ( str == NULL ) | 	if ( str == NULL ) | ||||||
| 	{ | 	{ | ||||||
| @@ -190,17 +203,19 @@ GEN_IMPL_INLINE sw str_len( const char* str ) | |||||||
| 	return str - p; | 	return str - p; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE sw str_len( const char* str, sw max_len ) | inline | ||||||
|  | ssize str_len( const char* str, ssize max_len ) | ||||||
| { | { | ||||||
| 	const char* end = zpl_cast( const char* ) mem_find( str, 0, max_len ); | 	const char* end = rcast(const char*, mem_find( str, 0, max_len )); | ||||||
| 	if ( end ) | 	if ( end ) | ||||||
| 		return end - str; | 		return end - str; | ||||||
| 	return max_len; | 	return max_len; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char* str_reverse( char* str ) | inline | ||||||
|  | char* str_reverse( char* str ) | ||||||
| { | { | ||||||
| 	sw    len  = str_len( str ); | 	ssize    len  = str_len( str ); | ||||||
| 	char* a    = str + 0; | 	char* a    = str + 0; | ||||||
| 	char* b    = str + len - 1; | 	char* b    = str + len - 1; | ||||||
| 	len       /= 2; | 	len       /= 2; | ||||||
| @@ -212,7 +227,8 @@ GEN_IMPL_INLINE char* str_reverse( char* str ) | |||||||
| 	return str; | 	return str; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char const* str_skip( char const* str, char c ) | inline | ||||||
|  | char const* str_skip( char const* str, char c ) | ||||||
| { | { | ||||||
| 	while ( *str && *str != c ) | 	while ( *str && *str != c ) | ||||||
| 	{ | 	{ | ||||||
| @@ -221,11 +237,12 @@ GEN_IMPL_INLINE char const* str_skip( char const* str, char c ) | |||||||
| 	return str; | 	return str; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char const* str_skip_any( char const* str, char const* char_list ) | 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 ) ); | 	char const* closest_ptr     = rcast( char const*, pointer_add_const( rcast(void const*, str), str_len( str ) )); | ||||||
| 	sw          char_list_count = str_len( char_list ); | 	ssize       char_list_count = str_len( char_list ); | ||||||
| 	for ( sw i = 0; i < char_list_count; i++ ) | 	for ( ssize i = 0; i < char_list_count; i++ ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* p = str_skip( str, char_list[ i ] ); | 		char const* p = str_skip( str, char_list[ i ] ); | ||||||
| 		closest_ptr   = min( closest_ptr, p ); | 		closest_ptr   = min( closest_ptr, p ); | ||||||
| @@ -233,7 +250,8 @@ GEN_IMPL_INLINE char const* str_skip_any( char const* str, char const* char_list | |||||||
| 	return closest_ptr; | 	return closest_ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE char const* str_trim( char const* str, b32 catch_newline ) | inline | ||||||
|  | char const* str_trim( char const* str, b32 catch_newline ) | ||||||
| { | { | ||||||
| 	while ( *str && char_is_space( *str ) && ( ! catch_newline || ( catch_newline && *str != '\n' ) ) ) | 	while ( *str && char_is_space( *str ) && ( ! catch_newline || ( catch_newline && *str != '\n' ) ) ) | ||||||
| 	{ | 	{ | ||||||
| @@ -242,7 +260,8 @@ GEN_IMPL_INLINE char const* str_trim( char const* str, b32 catch_newline ) | |||||||
| 	return str; | 	return str; | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void str_to_lower( char* str ) | inline | ||||||
|  | void str_to_lower( char* str ) | ||||||
| { | { | ||||||
| 	if ( ! str ) | 	if ( ! str ) | ||||||
| 		return; | 		return; | ||||||
| @@ -253,7 +272,8 @@ GEN_IMPL_INLINE void str_to_lower( char* str ) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| GEN_IMPL_INLINE void str_to_upper( char* str ) | inline | ||||||
|  | void str_to_upper( char* str ) | ||||||
| { | { | ||||||
| 	if ( ! str ) | 	if ( ! str ) | ||||||
| 		return; | 		return; | ||||||
|   | |||||||
| @@ -4,20 +4,9 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #pragma region String | #pragma region String | ||||||
|  | String string_make_length( AllocatorInfo allocator, char const* str, ssize length ) | ||||||
| String String::fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... ) |  | ||||||
| { | { | ||||||
| 	va_list va; | 	constexpr ssize header_size = sizeof( StringHeader ); | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	str_fmt_va( buf, buf_size, fmt, va ); |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return make( allocator, buf ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| String String::make_length( AllocatorInfo allocator, char const* str, sw length ) |  | ||||||
| { |  | ||||||
| 	constexpr sw header_size = sizeof( Header ); |  | ||||||
|  |  | ||||||
| 	s32   alloc_size = header_size + length + 1; | 	s32   alloc_size = header_size + length + 1; | ||||||
| 	void* allocation = alloc( allocator, alloc_size ); | 	void* allocation = alloc( allocator, alloc_size ); | ||||||
| @@ -25,8 +14,8 @@ String String::make_length( AllocatorInfo allocator, char const* str, sw length | |||||||
| 	if ( allocation == nullptr ) | 	if ( allocation == nullptr ) | ||||||
| 		return { nullptr }; | 		return { nullptr }; | ||||||
|  |  | ||||||
| 	Header& | 	StringHeader& | ||||||
| 	header = * rcast(Header*, allocation); | 	header = * rcast(StringHeader*, allocation); | ||||||
| 	header = { allocator, length, length }; | 	header = { allocator, length, length }; | ||||||
|  |  | ||||||
| 	String  result = { rcast( char*, allocation) + header_size }; | 	String  result = { rcast( char*, allocation) + header_size }; | ||||||
| @@ -41,9 +30,9 @@ String String::make_length( AllocatorInfo allocator, char const* str, sw length | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| String String::make_reserve( AllocatorInfo allocator, sw capacity ) | String string_make_reserve( AllocatorInfo allocator, ssize capacity ) | ||||||
| { | { | ||||||
| 	constexpr sw header_size = sizeof( Header ); | 	constexpr ssize header_size = sizeof( StringHeader ); | ||||||
|  |  | ||||||
| 	s32   alloc_size = header_size + capacity + 1; | 	s32   alloc_size = header_size + capacity + 1; | ||||||
| 	void* allocation = alloc( allocator, alloc_size ); | 	void* allocation = alloc( allocator, alloc_size ); | ||||||
| @@ -53,8 +42,8 @@ String String::make_reserve( AllocatorInfo allocator, sw capacity ) | |||||||
|  |  | ||||||
| 	mem_set( allocation, 0, alloc_size ); | 	mem_set( allocation, 0, alloc_size ); | ||||||
|  |  | ||||||
| 	Header* | 	StringHeader* | ||||||
| 		header            = rcast(Header*, allocation); | 	header            = rcast(StringHeader*, allocation); | ||||||
| 	header->Allocator = allocator; | 	header->Allocator = allocator; | ||||||
| 	header->Capacity  = capacity; | 	header->Capacity  = capacity; | ||||||
| 	header->Length    = 0; | 	header->Length    = 0; | ||||||
| @@ -62,69 +51,4 @@ String String::make_reserve( AllocatorInfo allocator, sw capacity ) | |||||||
| 	String result = { rcast(char*, allocation) + header_size }; | 	String result = { rcast(char*, allocation) + header_size }; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| String String::fmt_buf( AllocatorInfo allocator, char const* fmt, ... ) |  | ||||||
| { |  | ||||||
| 	local_persist thread_local |  | ||||||
| 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; |  | ||||||
|  |  | ||||||
| 	va_list va; |  | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	str_fmt_va( buf, GEN_PRINTF_MAXLEN, fmt, va ); |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return make( allocator, buf ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool String::append_fmt( char const* fmt, ... ) |  | ||||||
| { |  | ||||||
| 	sw   res; |  | ||||||
| 	char buf[ GEN_PRINTF_MAXLEN ] = { 0 }; |  | ||||||
|  |  | ||||||
| 	va_list va; |  | ||||||
| 	va_start( va, fmt ); |  | ||||||
| 	res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1; |  | ||||||
| 	va_end( va ); |  | ||||||
|  |  | ||||||
| 	return append( buf, res ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| bool String::make_space_for( char const* str, sw add_len ) |  | ||||||
| { |  | ||||||
| 	sw available = avail_space(); |  | ||||||
|  |  | ||||||
| 	// NOTE: Return if there is enough space left |  | ||||||
| 	if ( available >= add_len ) |  | ||||||
| 	{ |  | ||||||
| 		return true; |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		sw new_len, old_size, new_size; |  | ||||||
|  |  | ||||||
| 		void* ptr; |  | ||||||
| 		void* new_ptr; |  | ||||||
|  |  | ||||||
| 		AllocatorInfo allocator = get_header().Allocator; |  | ||||||
| 		Header*       header	= nullptr; |  | ||||||
|  |  | ||||||
| 		new_len  = grow_formula( length() + add_len ); |  | ||||||
| 		ptr      = & get_header(); |  | ||||||
| 		old_size = size_of( Header ) + length() + 1; |  | ||||||
| 		new_size = size_of( Header ) + new_len + 1; |  | ||||||
|  |  | ||||||
| 		new_ptr = resize( allocator, ptr, old_size, new_size ); |  | ||||||
|  |  | ||||||
| 		if ( new_ptr == nullptr ) |  | ||||||
| 			return false; |  | ||||||
|  |  | ||||||
| 		header            = zpl_cast( Header* ) new_ptr; |  | ||||||
| 		header->Allocator = allocator; |  | ||||||
| 		header->Capacity  = new_len; |  | ||||||
|  |  | ||||||
| 		Data = rcast( char*, header + 1 ); |  | ||||||
|  |  | ||||||
| 		return str; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| #pragma endregion String | #pragma endregion String | ||||||
|   | |||||||
| @@ -8,20 +8,20 @@ | |||||||
| // Constant string with length. | // Constant string with length. | ||||||
| struct StrC | struct StrC | ||||||
| { | { | ||||||
| 	sw          Len; | 	ssize       Len; | ||||||
| 	char const* Ptr; | 	char const* Ptr; | ||||||
|  |  | ||||||
| 	operator char const* () const | #if ! GEN_COMPILER_C | ||||||
| 	{ | 	operator char const* ()               const { return Ptr; } | ||||||
| 		return Ptr; | 	char const& operator[]( ssize index ) const { return Ptr[index]; } | ||||||
| 	} | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define cast_to_strc( str ) * rcast( StrC*, str - sizeof(sw) ) | #define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) ) | ||||||
| #define txt( text ) StrC { sizeof( text ) - 1, text } | #define txt( text )         StrC { sizeof( text ) - 1, ( text ) } | ||||||
|  |  | ||||||
| StrC to_str( char const* str ) | inline | ||||||
| { | StrC to_str( char const* str ) { | ||||||
| 	return { str_len( str ), str }; | 	return { str_len( str ), str }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -29,357 +29,549 @@ StrC to_str( char const* str ) | |||||||
| // This is directly based off the ZPL string api. | // This is directly based off the ZPL string api. | ||||||
| // They used a header pattern | // They used a header pattern | ||||||
| // I kept it for simplicty of porting but its not necessary to keep it that way. | // I kept it for simplicty of porting but its not necessary to keep it that way. | ||||||
|  | #pragma region String | ||||||
|  | struct StringHeader; | ||||||
|  | struct String; | ||||||
|  |  | ||||||
|  | String        string_make(AllocatorInfo allocator, char const* str); | ||||||
|  | String        string_make(AllocatorInfo allocator, StrC str); | ||||||
|  | String        string_make_reserve(AllocatorInfo allocator, ssize capacity); | ||||||
|  | String        string_make_length(AllocatorInfo allocator, char const* str, ssize length); | ||||||
|  | String        string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...); | ||||||
|  | String        string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...); | ||||||
|  | String        string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue); | ||||||
|  | usize         string_grow_formula(usize value); | ||||||
|  | bool          are_equal(String const& lhs, String const& rhs); | ||||||
|  | bool          are_equal(String const& lhs, StrC rhs); | ||||||
|  | bool          make_space_for(String& str, char const* to_append, ssize add_len); | ||||||
|  | bool          append(String& str, char c); | ||||||
|  | bool          append(String& str, char const* str_to_append); | ||||||
|  | bool          append(String& str, char const* str_to_append, ssize length); | ||||||
|  | bool          append(String& str, StrC str_to_append); | ||||||
|  | bool          append(String& str, const String other); | ||||||
|  | bool          append_fmt(String& str, char const* fmt, ...); | ||||||
|  | ssize         avail_space(String const& str); | ||||||
|  | char&         back(String& str); | ||||||
|  | bool          contains(String const& str, StrC substring); | ||||||
|  | bool          contains(String const& str, String const& substring); | ||||||
|  | ssize         capacity(String const& str); | ||||||
|  | void          clear(String& str); | ||||||
|  | String        duplicate(String const& str, AllocatorInfo allocator); | ||||||
|  | void          free(String& str); | ||||||
|  | StringHeader& get_header(String& str); | ||||||
|  | ssize         length(String const& str); | ||||||
|  | b32           starts_with(String const& str, StrC substring); | ||||||
|  | b32           starts_with(String const& str, String substring); | ||||||
|  | void          skip_line(String& str); | ||||||
|  | void          strip_space(String& str); | ||||||
|  | void          trim(String& str, char const* cut_set); | ||||||
|  | void          trim_space(String& str); | ||||||
|  | String        visualize_whitespace(String const& str); | ||||||
|  |  | ||||||
|  | struct StringHeader { | ||||||
|  | 	AllocatorInfo Allocator; | ||||||
|  | 	ssize         Capacity; | ||||||
|  | 	ssize         Length; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #if ! GEN_COMPILER_C | ||||||
| struct String | struct String | ||||||
| { | { | ||||||
| 	struct Header | 	char* Data; | ||||||
| 	{ |  | ||||||
| 		AllocatorInfo Allocator; | 	forceinline operator bool()              { return Data != nullptr; } | ||||||
| 		sw            Capacity; | 	forceinline operator char*()             { return Data; } | ||||||
| 		sw            Length; | 	forceinline operator char const*() const { return Data; } | ||||||
| 	}; | 	forceinline operator StrC() const        { return { GEN_NS length(* this), Data }; } | ||||||
|  |  | ||||||
|  | 	String const& operator=(String const& other) const { | ||||||
|  | 		if (this == &other) | ||||||
|  | 			return *this; | ||||||
|  |  | ||||||
|  | 		String* this_ = ccast(String*, this); | ||||||
|  | 		this_->Data = other.Data; | ||||||
|  |  | ||||||
|  | 		return *this; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	forceinline char& operator[](ssize index)             { return Data[index]; } | ||||||
|  | 	forceinline char const& operator[](ssize index) const { return Data[index]; } | ||||||
|  |  | ||||||
|  | 	forceinline char* begin() const { return Data; } | ||||||
|  | 	forceinline char* end() const   { return Data + GEN_NS length(* this); } | ||||||
|  |  | ||||||
|  | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
|  | #pragma region Member Mapping | ||||||
|  | 	forceinline static String make(AllocatorInfo allocator, char const* str)                { return GEN_NS string_make(allocator, str); } | ||||||
|  | 	forceinline static String make(AllocatorInfo allocator, StrC str)                       { return GEN_NS string_make(allocator, str); } | ||||||
|  | 	forceinline static String make_reserve(AllocatorInfo allocator, ssize cap)              { return GEN_NS string_make_reserve(allocator, cap); } | ||||||
|  | 	forceinline static String make_length(AllocatorInfo a, char const* s, ssize l)          { return GEN_NS string_make_length(a, s, l); } | ||||||
|  | 	forceinline static String join(AllocatorInfo a, char const** p, ssize n, char const* g) { return GEN_NS string_join(a, p, n, g); } | ||||||
|  | 	forceinline static usize  grow_formula(usize value)                                     { return GEN_NS string_grow_formula(value); } | ||||||
|  |  | ||||||
| 	static | 	static | ||||||
| 	uw grow_formula( uw value ) | 	String fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
| 	{ | 		va_list va; | ||||||
| 		// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. | 		va_start(va, fmt); | ||||||
| 		return 4 * value + 8; | 		str_fmt_va(buf, buf_size, fmt, va); | ||||||
|  | 		va_end(va); | ||||||
|  | 		return GEN_NS string_make(allocator, buf); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static | 	static | ||||||
| 	String make( AllocatorInfo allocator, char const* str ) | 	String fmt_buf(AllocatorInfo allocator, char const* fmt, ...) { | ||||||
| 	{ | 		local_persist thread_local | ||||||
| 		sw length = str ? str_len( str ) : 0; | 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
| 		return make_length( allocator, str, length ); | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | ||||||
|  | 		va_end(va); | ||||||
|  | 		return GEN_NS string_make(allocator, buf); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static | 	forceinline bool          make_space_for(char const* str, ssize add_len) { return GEN_NS make_space_for(*this, str, add_len); } | ||||||
| 	String make( AllocatorInfo allocator, StrC str ) | 	forceinline bool          append(char c)                                 { return GEN_NS append(*this, c); } | ||||||
|  | 	forceinline bool          append(char const* str)                        { return GEN_NS append(*this, str); } | ||||||
|  | 	forceinline bool          append(char const* str, ssize length)          { return GEN_NS append(*this, str, length); } | ||||||
|  | 	forceinline bool          append(StrC str)                               { return GEN_NS append(*this, str); } | ||||||
|  | 	forceinline bool          append(const String other)                     { return GEN_NS append(*this, other); } | ||||||
|  | 	forceinline ssize         avail_space() const                            { return GEN_NS avail_space(*this); } | ||||||
|  | 	forceinline char&         back()                                         { return GEN_NS back(*this); } | ||||||
|  | 	forceinline bool          contains(StrC substring) const                 { return GEN_NS contains(*this, substring); } | ||||||
|  | 	forceinline bool          contains(String const& substring) const        { return GEN_NS contains(*this, substring); } | ||||||
|  | 	forceinline ssize         capacity() const                               { return GEN_NS capacity(*this); } | ||||||
|  | 	forceinline void          clear()                                        { GEN_NS clear(*this); } | ||||||
|  | 	forceinline String        duplicate(AllocatorInfo allocator) const       { return GEN_NS duplicate(*this, allocator); } | ||||||
|  | 	forceinline void          free()                                         { GEN_NS free(*this); } | ||||||
|  | 	forceinline bool          is_equal(String const& other) const            { return GEN_NS are_equal(* this, other); } | ||||||
|  | 	forceinline bool          is_equal(StrC other) const                     { return GEN_NS are_equal(* this, other); } | ||||||
|  | 	forceinline ssize         length() const                                 { return GEN_NS length(*this); } | ||||||
|  | 	forceinline b32           starts_with(StrC substring) const              { return GEN_NS starts_with(*this, substring); } | ||||||
|  | 	forceinline b32           starts_with(String substring) const            { return GEN_NS starts_with(*this, substring); } | ||||||
|  | 	forceinline void          skip_line()                                    { GEN_NS skip_line(*this); } | ||||||
|  | 	forceinline void          strip_space()                                  { GEN_NS strip_space(*this); } | ||||||
|  | 	forceinline void          trim(char const* cut_set)                      { GEN_NS trim(*this, cut_set); } | ||||||
|  | 	forceinline void          trim_space()                                   { GEN_NS trim_space(*this); } | ||||||
|  | 	forceinline String        visualize_whitespace() const                   { return GEN_NS visualize_whitespace(*this); } | ||||||
|  | 	forceinline StringHeader& get_header()                                   { return GEN_NS get_header(*this); } | ||||||
|  |  | ||||||
|  | 	bool append_fmt(char const* fmt, ...) { | ||||||
|  | 		ssize res; | ||||||
|  | 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 		va_list va; | ||||||
|  | 		va_start(va, fmt); | ||||||
|  | 		res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
|  | 		va_end(va); | ||||||
|  |  | ||||||
|  | 		return GEN_NS append(*this, buf, res); | ||||||
|  | 	} | ||||||
|  | #pragma endregion Member Mapping | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | inline char* begin(String& str) { return str; } | ||||||
|  | inline char* end(String& str)   { return scast(char*, str) + length(str); } | ||||||
|  | inline char* next(String& str)  { return scast(char*, str) + 1; } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | usize string_grow_formula(usize value) { | ||||||
|  | 	// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. | ||||||
|  | 	return 4 * value + 8; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_make(AllocatorInfo allocator, char const* str) { | ||||||
|  | 	ssize length = str ? str_len(str) : 0; | ||||||
|  | 	return string_make_length(allocator, str, length); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_make(AllocatorInfo allocator, StrC str) { | ||||||
|  | 	return string_make_length(allocator, str.Ptr, str.Len); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	str_fmt_va(buf, buf_size, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	return string_make(allocator, buf); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...) | ||||||
|  | { | ||||||
|  | 	local_persist thread_local | ||||||
|  | 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	return string_make(allocator, buf); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue) | ||||||
|  | { | ||||||
|  | 	String result = string_make(allocator, ""); | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx < num_parts; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		return make_length( allocator, str.Ptr, str.Len ); | 		append(result, parts[idx]); | ||||||
|  |  | ||||||
|  | 		if (idx < num_parts - 1) | ||||||
|  | 			append(result, glue); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static | 	return result; | ||||||
| 	String make_reserve( AllocatorInfo allocator, sw capacity ); | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	String make_length( AllocatorInfo allocator, char const* str, sw length ); | bool append(String& str, char c) { | ||||||
|  | 	return append(str, &c, 1); | ||||||
|  | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	String fmt( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... ); | bool append(String& str, char const* str_to_append) { | ||||||
|  | 	return append(str, str_to_append, str_len(str_to_append)); | ||||||
|  | } | ||||||
|  |  | ||||||
| 	static | inline | ||||||
| 	String fmt_buf( AllocatorInfo allocator, char const* fmt, ... ); | bool append(String& str, char const* str_to_append, ssize append_length) | ||||||
|  | { | ||||||
| 	static | 	if (sptr(str_to_append) > 0) | ||||||
| 	String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue ) |  | ||||||
| 	{ | 	{ | ||||||
| 		String result = make( allocator, "" ); | 		ssize curr_len = length(str); | ||||||
|  |  | ||||||
| 		for ( sw idx = 0; idx < num_parts; ++idx ) | 		if (!make_space_for(str, str_to_append, append_length)) | ||||||
| 		{ |  | ||||||
| 			result.append( parts[ idx ] ); |  | ||||||
|  |  | ||||||
| 			if ( idx < num_parts - 1 ) |  | ||||||
| 				result.append( glue ); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static |  | ||||||
| 	bool are_equal( String lhs, String rhs ) |  | ||||||
| 	{ |  | ||||||
| 		if ( lhs.length() != rhs.length() ) |  | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		for ( sw idx = 0; idx < lhs.length(); ++idx ) | 		StringHeader& header = get_header(str); | ||||||
| 			if ( lhs[ idx ] != rhs[ idx ] ) |  | ||||||
| 				return false; | 		mem_copy( scast(char*, str) + curr_len, str_to_append, append_length); | ||||||
|  |  | ||||||
|  | 		str[curr_len + append_length] = '\0'; | ||||||
|  |  | ||||||
|  | 		header.Length = curr_len + append_length; | ||||||
|  | 	} | ||||||
|  | 	return str_to_append != nullptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool append(String& str, StrC str_to_append) { | ||||||
|  | 	return append(str, str_to_append.Ptr, str_to_append.Len); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool append(String& str, const String other) { | ||||||
|  | 	return append(str, other, length(other)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool append_fmt(String& str, char const* fmt, ...) { | ||||||
|  | 	ssize res; | ||||||
|  | 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
|  |  | ||||||
|  | 	va_list va; | ||||||
|  | 	va_start(va, fmt); | ||||||
|  | 	res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
|  | 	va_end(va); | ||||||
|  |  | ||||||
|  | 	return append(str, buf, res); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool are_equal(String const& lhs, String const& rhs) | ||||||
|  | { | ||||||
|  | 	if (length(lhs) != length(rhs)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx < length(lhs); ++idx) | ||||||
|  | 		if (lhs[idx] != rhs[idx]) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool are_equal(String const& lhs, StrC rhs) | ||||||
|  | { | ||||||
|  | 	if (length(lhs) != (rhs.Len)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx < length(lhs); ++idx) | ||||||
|  | 		if (lhs[idx] != rhs[idx]) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | ssize avail_space(String const& str) { | ||||||
|  | 	StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  | 	return header.Capacity - header.Length; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | char& back(String& str) { | ||||||
|  | 	return str.Data[length(str) - 1]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool contains(String const& str, StrC substring) | ||||||
|  | { | ||||||
|  | 	StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |  | ||||||
|  | 	if (substring.Len > header.Length) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	ssize main_len = header.Length; | ||||||
|  | 	ssize sub_len = substring.Len; | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
|  | 	{ | ||||||
|  | 		if (str_compare(str.Data + idx, substring.Ptr, sub_len) == 0) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool contains(String const& str, String const& substring) | ||||||
|  | { | ||||||
|  | 	StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |  | ||||||
|  | 	if (length(substring) > header.Length) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	ssize main_len = header.Length; | ||||||
|  | 	ssize sub_len = length(substring); | ||||||
|  |  | ||||||
|  | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
|  | 	{ | ||||||
|  | 		if (str_compare(str.Data + idx, substring.Data, sub_len) == 0) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | ssize capacity(String const& str) { | ||||||
|  |    StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |    return header.Capacity; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void clear(String& str) { | ||||||
|  |    get_header(str).Length = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String duplicate(String const& str, AllocatorInfo allocator) { | ||||||
|  |    return string_make_length(allocator, str, length(str)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void free(String& str) { | ||||||
|  |    if (!str.Data) | ||||||
|  |    	return; | ||||||
|  |  | ||||||
|  |    StringHeader& header = get_header(str); | ||||||
|  |    GEN_NS free(header.Allocator, &header); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | StringHeader& get_header(String& str) { | ||||||
|  |    return *(StringHeader*)(str.Data - sizeof(StringHeader)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | ssize length(String const& str) | ||||||
|  | { | ||||||
|  |    StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |    return header.Length; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | bool make_space_for(String& str, char const* to_append, ssize add_len) | ||||||
|  | { | ||||||
|  | 	ssize available = avail_space(str); | ||||||
|  |  | ||||||
|  | 	if (available >= add_len) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		ssize new_len, old_size, new_size; | ||||||
|  | 		void* ptr; | ||||||
|  | 		void* new_ptr; | ||||||
|  |  | ||||||
|  | 		AllocatorInfo allocator = get_header(str).Allocator; | ||||||
|  | 		StringHeader* header = nullptr; | ||||||
|  |  | ||||||
|  | 		new_len = string_grow_formula(length(str) + add_len); | ||||||
|  | 		ptr = &get_header(str); | ||||||
|  | 		old_size = size_of(StringHeader) + length(str) + 1; | ||||||
|  | 		new_size = size_of(StringHeader) + new_len + 1; | ||||||
|  |  | ||||||
|  | 		new_ptr = resize(allocator, ptr, old_size, new_size); | ||||||
|  |  | ||||||
|  | 		if (new_ptr == nullptr) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		header = rcast(StringHeader*, new_ptr); | ||||||
|  | 		header->Allocator = allocator; | ||||||
|  | 		header->Capacity = new_len; | ||||||
|  |  | ||||||
|  | 		str.Data = rcast(char*, header + 1); | ||||||
|  |  | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| 	bool make_space_for( char const* str, sw add_len ); | inline | ||||||
|  | b32 starts_with(String const& str, StrC substring) { | ||||||
|  | 	if (substring.Len > length(str)) | ||||||
|  | 	return false; | ||||||
|  |  | ||||||
| 	bool append( char c ) | 	b32 result = str_compare(str.Data, substring.Ptr, substring.Len) == 0; | ||||||
| 	{ | 	return result; | ||||||
| 		return append( & c, 1 ); | } | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool append( char const* str ) | inline | ||||||
| 	{ | b32 starts_with(String const& str, String substring) { | ||||||
| 		return append( str, str_len( str ) ); | 	if (length(substring) > length(str)) | ||||||
| 	} | 		return false; | ||||||
|  |  | ||||||
| 	bool append( char const* str, sw length ) | 	b32 result = str_compare(str.Data, substring.Data, length(substring) - 1) == 0; | ||||||
| 	{ | 	return result; | ||||||
| 		if ( sptr(str) > 0 ) | } | ||||||
| 		{ |  | ||||||
| 			sw curr_len = this->length(); |  | ||||||
|  |  | ||||||
| 			if ( ! make_space_for( str, length ) ) | inline | ||||||
| 				return false; | void skip_line(String& str) | ||||||
|  |  | ||||||
| 			Header& header = get_header(); |  | ||||||
|  |  | ||||||
| 			mem_copy( Data + curr_len, str, length ); |  | ||||||
|  |  | ||||||
| 			Data[ curr_len + length ] = '\0'; |  | ||||||
|  |  | ||||||
| 			header.Length = curr_len + length; |  | ||||||
| 		} |  | ||||||
| 		return str; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool append( StrC str) |  | ||||||
| 	{ |  | ||||||
| 		return append( str.Ptr, str.Len ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool append( const String other ) |  | ||||||
| 	{ |  | ||||||
| 		return append( other.Data, other.length() ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool append_fmt( char const* fmt, ... ); |  | ||||||
|  |  | ||||||
| 	sw avail_space() const |  | ||||||
| 	{ |  | ||||||
| 		Header const& |  | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return header.Capacity - header.Length; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char& back() |  | ||||||
| 	{ |  | ||||||
| 		return Data[ length() - 1 ]; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sw capacity() const |  | ||||||
| 	{ |  | ||||||
| 		Header const& |  | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return header.Capacity; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void clear() |  | ||||||
| 	{ |  | ||||||
| 		get_header().Length = 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	String duplicate( AllocatorInfo allocator ) const |  | ||||||
| 	{ |  | ||||||
| 		return make_length( allocator, Data, length() ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void free() |  | ||||||
| 	{ |  | ||||||
| 		if ( ! Data ) |  | ||||||
| 			return; |  | ||||||
|  |  | ||||||
| 		Header& header = get_header(); |  | ||||||
|  |  | ||||||
| 		gen::free( header.Allocator, & header ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Header& get_header() |  | ||||||
| 	{ |  | ||||||
| 		return *(Header*)(Data - sizeof(Header)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	sw length() const |  | ||||||
| 	{ |  | ||||||
| 		Header const& |  | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return header.Length; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void skip_line() |  | ||||||
| 	{ |  | ||||||
| 	#define current (*scanner) |  | ||||||
| 		char* scanner = Data; |  | ||||||
| 		while ( current != '\r' && current != '\n' ) |  | ||||||
| 		{ |  | ||||||
| 			++ scanner; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		s32 new_length = scanner - Data; |  | ||||||
|  |  | ||||||
| 		if ( current == '\r' ) |  | ||||||
| 		{ |  | ||||||
| 			new_length += 1; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		mem_move( Data, scanner, new_length ); |  | ||||||
|  |  | ||||||
| 		Header* header = & get_header(); |  | ||||||
| 		header->Length = new_length; |  | ||||||
| 	#undef current |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void strip_space() |  | ||||||
| 	{ |  | ||||||
| 		char* write_pos = Data; |  | ||||||
| 		char* read_pos  = Data; |  | ||||||
|  |  | ||||||
| 		while ( * read_pos) |  | ||||||
| 		{ |  | ||||||
| 			if ( ! char_is_space( *read_pos )) |  | ||||||
| 			{ |  | ||||||
| 				*write_pos = *read_pos; |  | ||||||
| 				write_pos++; |  | ||||||
| 			} |  | ||||||
| 			read_pos++; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		write_pos[0] = '\0';  // Null-terminate the modified string |  | ||||||
|  |  | ||||||
| 		// Update the length if needed |  | ||||||
| 		get_header().Length = write_pos - Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void trim( char const* cut_set ) |  | ||||||
| 	{ |  | ||||||
| 		sw len = 0; |  | ||||||
|  |  | ||||||
| 		char* start_pos = Data; |  | ||||||
| 		char* end_pos   = Data + length() - 1; |  | ||||||
|  |  | ||||||
| 		while ( start_pos <= end_pos && char_first_occurence( cut_set, *start_pos ) ) |  | ||||||
| 			start_pos++; |  | ||||||
|  |  | ||||||
| 		while ( end_pos > start_pos && char_first_occurence( cut_set, *end_pos ) ) |  | ||||||
| 			end_pos--; |  | ||||||
|  |  | ||||||
| 		len = scast( sw, ( start_pos > end_pos ) ? 0 : ( ( end_pos - start_pos ) + 1 ) ); |  | ||||||
|  |  | ||||||
| 		if ( Data != start_pos ) |  | ||||||
| 			mem_move( Data, start_pos, len ); |  | ||||||
|  |  | ||||||
| 		Data[ len ] = '\0'; |  | ||||||
|  |  | ||||||
| 		get_header().Length = len; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void trim_space() |  | ||||||
| 	{ |  | ||||||
| 		return trim( " \t\r\n\v\f" ); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Debug function that provides a copy of the string with whitespace characters visualized. |  | ||||||
| 	String visualize_whitespace() const |  | ||||||
| 	{ |  | ||||||
| 		Header* header = (Header*)(Data - sizeof(Header)); |  | ||||||
|  |  | ||||||
| 		String result = make_reserve(header->Allocator, length() * 2); // Assume worst case for space requirements. |  | ||||||
|  |  | ||||||
| 		for ( char c : *this ) |  | ||||||
| 		{ |  | ||||||
| 			switch ( c ) |  | ||||||
| 			{ |  | ||||||
| 				case ' ': |  | ||||||
| 					result.append( txt("·") ); |  | ||||||
| 				break; |  | ||||||
| 				case '\t': |  | ||||||
| 					result.append( txt("→") ); |  | ||||||
| 				break; |  | ||||||
| 				case '\n': |  | ||||||
| 					result.append( txt("↵") ); |  | ||||||
| 				break; |  | ||||||
| 				case '\r': |  | ||||||
| 					result.append( txt("⏎") ); |  | ||||||
| 				break; |  | ||||||
| 				case '\v': |  | ||||||
| 					result.append( txt("⇕") ); |  | ||||||
| 				break; |  | ||||||
| 				case '\f': |  | ||||||
| 					result.append( txt("⌂") ); |  | ||||||
| 				break; |  | ||||||
| 				default: |  | ||||||
| 					result.append(c); |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return result; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// For-range support |  | ||||||
|  |  | ||||||
| 	char* begin() const |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char* end() const |  | ||||||
| 	{ |  | ||||||
| 		Header const& |  | ||||||
| 		header = * rcast( Header const*, Data - sizeof( Header )); |  | ||||||
|  |  | ||||||
| 		return Data + header.Length; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator bool() |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator char* () |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator char const* () const |  | ||||||
| 	{ |  | ||||||
| 		return Data; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	operator StrC() const |  | ||||||
| 	{ |  | ||||||
| 		return { length(), Data }; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Used with cached strings |  | ||||||
| 	// Essentially makes the string a string view. |  | ||||||
| 	String const& operator = ( String const& other ) const |  | ||||||
| 	{ |  | ||||||
| 		if ( this == & other ) |  | ||||||
| 			return *this; |  | ||||||
|  |  | ||||||
| 		String& this_ = ccast( String, *this ); |  | ||||||
|  |  | ||||||
| 		this_.Data = other.Data; |  | ||||||
|  |  | ||||||
| 		return this_; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char& operator [] ( sw index ) |  | ||||||
| 	{ |  | ||||||
| 		return Data[ index ]; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char const& operator [] ( sw index ) const |  | ||||||
| 	{ |  | ||||||
| 		return Data[ index ]; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	char* Data; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| struct String_POD |  | ||||||
| { | { | ||||||
|  | #define current (*scanner) | ||||||
|  | 	char* scanner = str.Data; | ||||||
|  | 	while (current != '\r' && current != '\n') { | ||||||
|  |  		++scanner; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s32 new_length = scanner - str.Data; | ||||||
|  |  | ||||||
|  | 	if (current == '\r') { | ||||||
|  | 		new_length += 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mem_move(str.Data, scanner, new_length); | ||||||
|  |  | ||||||
|  | 	StringHeader* header = &get_header(str); | ||||||
|  | 	header->Length = new_length; | ||||||
|  | #undef current | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void strip_space(String& str) | ||||||
|  | { | ||||||
|  |    char* write_pos = str.Data; | ||||||
|  |    char* read_pos = str.Data; | ||||||
|  |  | ||||||
|  |    while (*read_pos) | ||||||
|  |    { | ||||||
|  |    	if (!char_is_space(*read_pos)) | ||||||
|  |    	{ | ||||||
|  |    		*write_pos = *read_pos; | ||||||
|  |    		write_pos++; | ||||||
|  |    	} | ||||||
|  |    	read_pos++; | ||||||
|  |    } | ||||||
|  |  | ||||||
|  |    write_pos[0] = '\0';  // Null-terminate the modified string | ||||||
|  |  | ||||||
|  |    // Update the length if needed | ||||||
|  |    get_header(str).Length = write_pos - str.Data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void trim(String& str, char const* cut_set) | ||||||
|  | { | ||||||
|  |    ssize len = 0; | ||||||
|  |  | ||||||
|  |    char* start_pos = str.Data; | ||||||
|  |    char* end_pos = str.Data + length(str) - 1; | ||||||
|  |  | ||||||
|  |    while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos)) | ||||||
|  |    	start_pos++; | ||||||
|  |  | ||||||
|  |    while (end_pos > start_pos && char_first_occurence(cut_set, *end_pos)) | ||||||
|  |    	end_pos--; | ||||||
|  |  | ||||||
|  |    len = scast(ssize, (start_pos > end_pos) ? 0 : ((end_pos - start_pos) + 1)); | ||||||
|  |  | ||||||
|  |    if (str.Data != start_pos) | ||||||
|  |    	mem_move(str.Data, start_pos, len); | ||||||
|  |  | ||||||
|  |    str.Data[len] = '\0'; | ||||||
|  |  | ||||||
|  |    get_header(str).Length = len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | void trim_space(String& str) { | ||||||
|  |    trim(str, " \t\r\n\v\f"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline | ||||||
|  | String visualize_whitespace(String const& str) | ||||||
|  | { | ||||||
|  | 	StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  | 	String        result = string_make_reserve(header->Allocator, length(str) * 2); // Assume worst case for space requirements. | ||||||
|  |  | ||||||
|  | 	for (auto c : str) switch (c) | ||||||
|  | 	{ | ||||||
|  | 		case ' ': | ||||||
|  | 			append(result, txt("·")); | ||||||
|  | 		break; | ||||||
|  | 		case '\t': | ||||||
|  | 			append(result, txt("→")); | ||||||
|  | 		break; | ||||||
|  | 		case '\n': | ||||||
|  | 			append(result, txt("↵")); | ||||||
|  | 		break; | ||||||
|  | 		case '\r': | ||||||
|  | 			append(result, txt("⏎")); | ||||||
|  | 		break; | ||||||
|  | 		case '\v': | ||||||
|  | 			append(result, txt("⇕")); | ||||||
|  | 		break; | ||||||
|  | 		case '\f': | ||||||
|  | 			append(result, txt("⌂")); | ||||||
|  | 		break; | ||||||
|  | 		default: | ||||||
|  | 			append(result, c); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | #pragma endregion String | ||||||
|  |  | ||||||
|  | struct String_POD { | ||||||
| 	char* Data; | 	char* Data; | ||||||
| }; | }; | ||||||
| static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | ||||||
|  |  | ||||||
| // Implements basic string interning. Data structure is based off the ZPL Hashtable. | // Implements basic string interning. Data structure is based off the ZPL Hashtable. | ||||||
| using StringTable = HashTable<String const>; | typedef HashTable<String const>   StringTable; | ||||||
|  |  | ||||||
| // Represents strings cached with the string table. | // Represents strings cached with the string table. | ||||||
| // Should never be modified, if changed string is desired, cache_string( str ) another. | // Should never be modified, if changed string is desired, cache_string( str ) another. | ||||||
| using StringCached = String const; | typedef String const   StringCached; | ||||||
|  |  | ||||||
| #pragma endregion Strings | #pragma endregion Strings | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ | |||||||
| 	{ | 	{ | ||||||
| 		u32 hi, lo; | 		u32 hi, lo; | ||||||
| 		__asm__ __volatile__( "rdtsc" : "=a"( lo ), "=d"( hi ) ); | 		__asm__ __volatile__( "rdtsc" : "=a"( lo ), "=d"( hi ) ); | ||||||
| 		return ( zpl_cast( u64 ) lo ) | ( ( zpl_cast( u64 ) hi ) << 32 ); | 		return scast( u64, lo ) | ( scast( u64, hi ) << 32 ); | ||||||
| 	} | 	} | ||||||
| 	#elif defined( __powerpc__ ) | 	#elif defined( __powerpc__ ) | ||||||
| 	u64 read_cpu_time_stamp_counter( void ) | 	u64 read_cpu_time_stamp_counter( void ) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| // This file is intended to be included within gen.hpp (There is no pragma diagnostic ignores) | // This file is intended to be included within gen.hpp (There is no pragma diagnostic ignores) | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "dependencies/header_start.hpp" | #include "dependencies/platform.hpp" | ||||||
|  |  | ||||||
| GEN_NS_BEGIN | GEN_NS_BEGIN | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,23 +11,23 @@ using namespace gen; | |||||||
| CodeBody gen_ecode( char const* path ) | CodeBody gen_ecode( char const* path ) | ||||||
| { | { | ||||||
| 	char  scratch_mem[kilobytes(1)]; | 	char  scratch_mem[kilobytes(1)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( allocator_info(scratch), zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
|  |  | ||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for ( ADT_Node node : enum_strs ) | 	for ( ADT_Node node : enum_strs ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* code = node.string; | 		char const* code = node.string; | ||||||
| 		enum_entries.append_fmt( "%s,\n", code ); | 		append_fmt( enum_entries, "%s,\n", code ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | 		append_fmt( to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", (StrC)enum_entries, "enum Type : u32 { <entries> NumTypes };")); | 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", (StrC)enum_entries, "enum Type : u32 { <entries> NumTypes };")); | ||||||
| @@ -35,6 +35,7 @@ CodeBody gen_ecode( char const* path ) | |||||||
| #pragma push_macro("local_persist") | #pragma push_macro("local_persist") | ||||||
| #undef local_persist | #undef local_persist | ||||||
| 	CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( Type type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -56,9 +57,9 @@ CodeBody gen_ecode( char const* path ) | |||||||
| CodeBody gen_eoperator( char const* path ) | CodeBody gen_eoperator( char const* path ) | ||||||
| { | { | ||||||
| 	char scratch_mem[kilobytes(4)]; | 	char scratch_mem[kilobytes(4)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( allocator_info(scratch), zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
| @@ -66,16 +67,16 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for (uw idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = str_strs [idx].string; | 		char const* entry_to_str = str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		append_fmt( enum_entries, "%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		append_fmt( to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | ||||||
| @@ -89,6 +90,7 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| #pragma push_macro("local_persist") | #pragma push_macro("local_persist") | ||||||
| #undef local_persist | #undef local_persist | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		StrC to_str( Type op ) | 		StrC to_str( Type op ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -111,9 +113,9 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| CodeBody gen_especifier( char const* path ) | CodeBody gen_especifier( char const* path ) | ||||||
| { | { | ||||||
| 	char scratch_mem[kilobytes(4)]; | 	char scratch_mem[kilobytes(4)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	file_read_contents( scratch, zero_terminate, path ); | 	file_read_contents( allocator_info(scratch), zero_terminate, path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_nodes; | 	CSV_Object csv_nodes; | ||||||
| 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | 	csv_parse( &csv_nodes, scratch_mem, GlobalAllocator, false ); | ||||||
| @@ -121,16 +123,16 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | 	Array<ADT_Node> enum_strs = csv_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | 	Array<ADT_Node> str_strs  = csv_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries   = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String enum_entries   = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
| 	String to_str_entries = String::make_reserve( GlobalAllocator, kilobytes(1) ); | 	String to_str_entries = string_make_reserve( GlobalAllocator, kilobytes(1) ); | ||||||
|  |  | ||||||
| 	for (uw idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = str_strs [idx].string; | 		char const* entry_to_str = str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		append_fmt( enum_entries, "%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		append_fmt( to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", (StrC)enum_entries, stringize( | ||||||
| @@ -142,6 +144,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize( | 	CodeFn is_trailing = parse_function(token_fmt("specifier", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		bool is_trailing( Type specifier ) | 		bool is_trailing( Type specifier ) | ||||||
| 		{ | 		{ | ||||||
| 			return specifier > Virtual; | 			return specifier > Virtual; | ||||||
| @@ -159,6 +162,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| #undef forceinline | #undef forceinline | ||||||
| #undef neverinline | #undef neverinline | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( Type type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -171,6 +175,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		Type to_type( StrC str ) | 		Type to_type( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -213,14 +218,16 @@ CodeBody gen_especifier( char const* path ) | |||||||
| CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | ||||||
| { | { | ||||||
| 	char  scratch_mem[kilobytes(16)]; | 	char  scratch_mem[kilobytes(16)]; | ||||||
| 	Arena scratch = Arena::init_from_memory( scratch_mem, sizeof(scratch_mem) ); | 	Arena scratch = arena_init_from_memory( scratch_mem, sizeof(scratch_mem) ); | ||||||
|  |  | ||||||
| 	FileContents enum_content = file_read_contents( scratch, zero_terminate, etok_path ); | 	AllocatorInfo scratch_info = allocator_info(scratch); | ||||||
|  |  | ||||||
|  | 	FileContents enum_content = file_read_contents( scratch_info, zero_terminate, etok_path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_enum_nodes; | 	CSV_Object csv_enum_nodes; | ||||||
| 	csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false ); | 	csv_parse( &csv_enum_nodes, rcast(char*, enum_content.data), GlobalAllocator, false ); | ||||||
|  |  | ||||||
| 	FileContents attrib_content = file_read_contents( scratch, zero_terminate, attr_path ); | 	FileContents attrib_content = file_read_contents( scratch_info, zero_terminate, attr_path ); | ||||||
|  |  | ||||||
| 	CSV_Object csv_attr_nodes; | 	CSV_Object csv_attr_nodes; | ||||||
| 	csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false ); | 	csv_parse( &csv_attr_nodes, rcast(char*, attrib_content.data), GlobalAllocator, false ); | ||||||
| @@ -230,34 +237,34 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 	Array<ADT_Node> attribute_strs     = csv_attr_nodes.nodes[0].nodes; | 	Array<ADT_Node> attribute_strs     = csv_attr_nodes.nodes[0].nodes; | ||||||
| 	Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes; | 	Array<ADT_Node> attribute_str_strs = csv_attr_nodes.nodes[1].nodes; | ||||||
|  |  | ||||||
| 	String enum_entries             = String::make_reserve( GlobalAllocator, kilobytes(2) ); | 	String enum_entries             = string_make_reserve( GlobalAllocator, kilobytes(2) ); | ||||||
| 	String to_str_entries           = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String to_str_entries           = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
| 	String attribute_entries        = String::make_reserve( GlobalAllocator, kilobytes(2) ); | 	String attribute_entries        = string_make_reserve( GlobalAllocator, kilobytes(2) ); | ||||||
| 	String to_str_attributes        = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String to_str_attributes        = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
| 	String attribute_define_entries = String::make_reserve( GlobalAllocator, kilobytes(4) ); | 	String attribute_define_entries = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
|  |  | ||||||
| 	for (uw idx = 0; idx < enum_strs.num(); idx++) | 	for (usize idx = 0; idx < num(enum_strs); idx++) | ||||||
| 	{ | 	{ | ||||||
| 		char const* enum_str     = enum_strs[idx].string; | 		char const* enum_str     = enum_strs[idx].string; | ||||||
| 		char const* entry_to_str = enum_str_strs [idx].string; | 		char const* entry_to_str = enum_str_strs [idx].string; | ||||||
|  |  | ||||||
| 		enum_entries.append_fmt( "%s,\n", enum_str ); | 		append_fmt( enum_entries, "%s,\n", enum_str ); | ||||||
| 		to_str_entries.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		append_fmt( to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( uw idx = 0; idx < attribute_strs.num(); idx++ ) | 	for ( usize idx = 0; idx < num(attribute_strs); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* attribute_str = attribute_strs[idx].string; | 		char const* attribute_str = attribute_strs[idx].string; | ||||||
| 		char const* entry_to_str  = attribute_str_strs [idx].string; | 		char const* entry_to_str  = attribute_str_strs [idx].string; | ||||||
|  |  | ||||||
| 		attribute_entries.append_fmt( "Attribute_%s,\n", attribute_str ); | 		append_fmt( attribute_entries, "Attribute_%s,\n", attribute_str ); | ||||||
| 		to_str_attributes.append_fmt( "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		append_fmt( to_str_attributes, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 		attribute_define_entries.append_fmt( "Entry( Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | 		append_fmt( attribute_define_entries, "Entry( Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | ||||||
|  |  | ||||||
| 		if ( idx < attribute_strs.num() - 1 ) | 		if ( idx < num(attribute_strs) - 1 ) | ||||||
| 			attribute_define_entries.append( " \\\n"); | 			append( attribute_define_entries, " \\\n"); | ||||||
| 		else | 		else | ||||||
| 			attribute_define_entries.append( "\n"); | 			append( attribute_define_entries, "\n"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | ||||||
| @@ -282,6 +289,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| #undef do_once_start | #undef do_once_start | ||||||
| #undef do_once_end | #undef do_once_end | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, "attribute_toks", (StrC)to_str_attributes, stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", (StrC)to_str_entries, "attribute_toks", (StrC)to_str_attributes, stringize( | ||||||
|  | 		inline | ||||||
| 		StrC to_str( Type type ) | 		StrC to_str( Type type ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -295,6 +303,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", (StrC)to_str_entries, stringize( | ||||||
|  | 		inline | ||||||
| 		Type to_type( StrC str ) | 		Type to_type( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| 			local_persist | 			local_persist | ||||||
| @@ -339,6 +348,7 @@ CodeBody gen_ast_inlines() | |||||||
| #undef log_failure | #undef log_failure | ||||||
| 	char const* code_impl_tmpl = stringize( | 	char const* code_impl_tmpl = stringize( | ||||||
| 		\n | 		\n | ||||||
|  | 		inline | ||||||
| 		char const* <typename>::debug_str() | 		char const* <typename>::debug_str() | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast == nullptr ) | 			if ( ast == nullptr ) | ||||||
| @@ -346,6 +356,7 @@ CodeBody gen_ast_inlines() | |||||||
|  |  | ||||||
| 			return rcast(AST*, ast)->debug_str(); | 			return rcast(AST*, ast)->debug_str(); | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		Code <typename>::duplicate() | 		Code <typename>::duplicate() | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast == nullptr ) | 			if ( ast == nullptr ) | ||||||
| @@ -356,20 +367,32 @@ CodeBody gen_ast_inlines() | |||||||
|  |  | ||||||
| 			return { rcast(AST*, ast)->duplicate() }; | 			return { rcast(AST*, ast)->duplicate() }; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
|  | 		bool <typename>::is_body() | ||||||
|  | 		{ | ||||||
|  | 			if ( ast == nullptr ) | ||||||
|  | 			{ | ||||||
|  | 				return rcast(AST*, ast)->is_body(); | ||||||
|  | 			} | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		inline | ||||||
| 		bool <typename>::is_equal( Code other ) | 		bool <typename>::is_equal( Code other ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast == nullptr || other.ast == nullptr ) | 			if ( ast == nullptr || other.ast == nullptr ) | ||||||
| 			{ | 			{ | ||||||
| 				log_failure("Code::is_equal: Cannot compare code, AST is null!"); | 				// Just check if they're both null. | ||||||
| 				return false; | 				// log_failure( "Code::is_equal: Cannot compare code, AST is null!" ); | ||||||
|  | 				return ast == nullptr && other.ast == nullptr; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return rcast(AST*, ast)->is_equal( other.ast ); | 			return rcast(AST*, ast)->is_equal( other.ast ); | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		bool <typename>::is_valid() | 		bool <typename>::is_valid() | ||||||
| 		{ | 		{ | ||||||
| 			return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid; | 			return (AST*) ast != nullptr && rcast( AST*, ast)->Type != CodeT::Invalid; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		void <typename>::set_global() | 		void <typename>::set_global() | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast == nullptr ) | 			if ( ast == nullptr ) | ||||||
| @@ -380,6 +403,7 @@ CodeBody gen_ast_inlines() | |||||||
|  |  | ||||||
| 			rcast(AST*, ast)->Parent = Code::Global.ast; | 			rcast(AST*, ast)->Parent = Code::Global.ast; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		<typename>& <typename>::operator =( Code other ) | 		<typename>& <typename>::operator =( Code other ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( other.ast && other->Parent ) | 			if ( other.ast && other->Parent ) | ||||||
| @@ -391,14 +415,17 @@ CodeBody gen_ast_inlines() | |||||||
| 			ast = rcast( decltype(ast), other.ast ); | 			ast = rcast( decltype(ast), other.ast ); | ||||||
| 			return *this; | 			return *this; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		bool <typename>::operator ==( Code other ) | 		bool <typename>::operator ==( Code other ) | ||||||
| 		{ | 		{ | ||||||
| 			return (AST*) ast == other.ast; | 			return (AST*) ast == other.ast; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		bool <typename>::operator !=( Code other ) | 		bool <typename>::operator !=( Code other ) | ||||||
| 		{ | 		{ | ||||||
| 			return (AST*) ast != other.ast; | 			return (AST*) ast != other.ast; | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		<typename>::operator bool() | 		<typename>::operator bool() | ||||||
| 		{ | 		{ | ||||||
| 			return ast != nullptr; | 			return ast != nullptr; | ||||||
| @@ -406,14 +433,17 @@ CodeBody gen_ast_inlines() | |||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	char const* codetype_impl_tmpl = stringize( | 	char const* codetype_impl_tmpl = stringize( | ||||||
|  | 		inline | ||||||
| 		AST* Code<typename>::raw() | 		AST* Code<typename>::raw() | ||||||
| 		{ | 		{ | ||||||
| 			return rcast( AST*, ast ); | 			return rcast( AST*, ast ); | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		Code<typename>::operator Code() | 		Code<typename>::operator Code() | ||||||
| 		{ | 		{ | ||||||
| 			return *rcast( Code*, this ); | 			return *rcast( Code*, this ); | ||||||
| 		} | 		} | ||||||
|  | 		inline | ||||||
| 		AST_<typename>* Code<typename>::operator->() | 		AST_<typename>* Code<typename>::operator->() | ||||||
| 		{ | 		{ | ||||||
| 			if ( ast == nullptr ) | 			if ( ast == nullptr ) | ||||||
| @@ -481,12 +511,11 @@ CodeBody gen_ast_inlines() | |||||||
| 	impl_code_var.     append( parse_global_body( token_fmt( "typename", StrC name(Var),            codetype_impl_tmpl ))); | 	impl_code_var.     append( parse_global_body( token_fmt( "typename", StrC name(Var),            codetype_impl_tmpl ))); | ||||||
|  |  | ||||||
| 	char const* cast_tmpl = stringize( | 	char const* cast_tmpl = stringize( | ||||||
| 		AST::operator Code<typename>() | 		inline	AST::operator Code<typename>() | ||||||
| 		{ | 		{ | ||||||
| 			return { rcast( AST_<typename>*, this ) }; | 			return { rcast( AST_<typename>*, this ) }; | ||||||
| 		} | 		} | ||||||
|  | 		inline Code::operator Code<typename>() const | ||||||
| 		Code::operator Code<typename>() const |  | ||||||
| 		{ | 		{ | ||||||
| 			return { (AST_<typename>*) ast }; | 			return { (AST_<typename>*) ast }; | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								project/helpers/member_proc_support.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								project/helpers/member_proc_support.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "gen.hpp" | ||||||
|  |  | ||||||
|  | GEN_NS_BEGIN | ||||||
|  | #include "dependencies/parsing.hpp" | ||||||
|  | GEN_NS_END | ||||||
|  |  | ||||||
|  | using namespace gen; | ||||||
|  |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| #if __clang__ | #ifdef __clang__ | ||||||
| #	pragma clang diagnostic pop | #	pragma clang diagnostic pop | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if __GNUC__ | #ifdef __GNUC__ | ||||||
| #	pragma GCC diagnostic pop | #	pragma GCC diagnostic pop | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| #if __clang__ | #ifdef __clang__ | ||||||
| #	pragma clang diagnostic push | #	pragma clang diagnostic push | ||||||
| #	pragma clang diagnostic ignored "-Wunused-const-variable" | #	pragma clang diagnostic ignored "-Wunused-const-variable" | ||||||
|  | #	pragma clang diagnostic ignored "-Wunused-but-set-variable" | ||||||
| #	pragma clang diagnostic ignored "-Wswitch" | #	pragma clang diagnostic ignored "-Wswitch" | ||||||
| #	pragma clang diagnostic ignored "-Wunused-variable" | #	pragma clang diagnostic ignored "-Wunused-variable" | ||||||
| #   pragma clang diagnostic ignored "-Wunknown-pragmas" | #   pragma clang diagnostic ignored "-Wunknown-pragmas" | ||||||
| @@ -8,7 +9,7 @@ | |||||||
| #	pragma clang diagnostic ignored "-Wunused-function" | #	pragma clang diagnostic ignored "-Wunused-function" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if __GNUC__ | #ifdef __GNUC__ | ||||||
| #	pragma GCC diagnostic push | #	pragma GCC diagnostic push | ||||||
| #   pragma GCC diagnostic ignored "-Wunknown-pragmas" | #   pragma GCC diagnostic ignored "-Wunknown-pragmas" | ||||||
| #	pragma GCC diagnostic ignored "-Wcomment" | #	pragma GCC diagnostic ignored "-Wcomment" | ||||||
|   | |||||||
| @@ -24,8 +24,6 @@ | |||||||
| #undef forceinline | #undef forceinline | ||||||
| #undef neverinline | #undef neverinline | ||||||
|  |  | ||||||
| #undef zpl_cast |  | ||||||
|  |  | ||||||
| #undef global | #undef global | ||||||
| #undef internal | #undef internal | ||||||
| #undef local_persist | #undef local_persist | ||||||
|   | |||||||
| @@ -2,14 +2,36 @@ | |||||||
| # It will most likely need a partial rewrite to segment the build process into separate script invocations based on the OS. | # It will most likely need a partial rewrite to segment the build process into separate script invocations based on the OS. | ||||||
| # That or just rewrite it in an sh script and call it a day. | # That or just rewrite it in an sh script and call it a day. | ||||||
|  |  | ||||||
| Import-Module ./helpers/target_arch.psm1 |  | ||||||
| $target_arch        = Join-Path $PSScriptRoot 'helpers/target_arch.psm1' | $target_arch        = Join-Path $PSScriptRoot 'helpers/target_arch.psm1' | ||||||
| $devshell           = Join-Path $PSScriptRoot 'helpers/devshell.ps1' | $devshell           = Join-Path $PSScriptRoot 'helpers/devshell.ps1' | ||||||
| $format_cpp	        = Join-Path $PSScriptRoot 'helpers/format_cpp.psm1' | $format_cpp	        = Join-Path $PSScriptRoot 'helpers/format_cpp.psm1' | ||||||
|  | $refactor_unreal    = Join-Path $PSScriptRoot 'refactor_unreal.ps1' | ||||||
| $incremental_checks = Join-Path $PSScriptRoot 'helpers/incremental_checks.ps1' | $incremental_checks = Join-Path $PSScriptRoot 'helpers/incremental_checks.ps1' | ||||||
| $vendor_toolchain   = Join-Path $PSScriptRoot 'helpers/vendor_toolchain.ps1' | $vendor_toolchain   = Join-Path $PSScriptRoot 'helpers/vendor_toolchain.ps1' | ||||||
|  |  | ||||||
| $path_root = git rev-parse --show-toplevel | Import-Module $target_arch | ||||||
|  |  | ||||||
|  | function Get-ScriptRepoRoot { | ||||||
|  |     $currentPath = $PSScriptRoot | ||||||
|  |     while ($currentPath -ne $null -and $currentPath -ne "") | ||||||
|  | 	{ | ||||||
|  |         if (Test-Path (Join-Path $currentPath ".git")) { | ||||||
|  |             return $currentPath | ||||||
|  |         } | ||||||
|  |         # Also check for .git file which indicates a submodule | ||||||
|  |         $gitFile = Join-Path $currentPath ".git" | ||||||
|  |         if (Test-Path $gitFile -PathType Leaf) | ||||||
|  | 		{ | ||||||
|  |             $gitContent = Get-Content $gitFile | ||||||
|  |             if ($gitContent -match "gitdir: (.+)") { | ||||||
|  |                 return $currentPath | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         $currentPath = Split-Path $currentPath -Parent | ||||||
|  |     } | ||||||
|  |     throw "Unable to find repository root" | ||||||
|  | } | ||||||
|  | $path_root = Get-ScriptRepoRoot | ||||||
|  |  | ||||||
| Import-Module $target_arch | Import-Module $target_arch | ||||||
| Import-Module $format_cpp | Import-Module $format_cpp | ||||||
| @@ -22,6 +44,8 @@ Push-Location $path_root | |||||||
| 	   $verbose      = $false | 	   $verbose      = $false | ||||||
| [bool] $bootstrap    = $false | [bool] $bootstrap    = $false | ||||||
| [bool] $singleheader = $false | [bool] $singleheader = $false | ||||||
|  | [bool] $c_library    = $false | ||||||
|  | [bool] $unreal       = $false | ||||||
| [bool] $test         = $false | [bool] $test         = $false | ||||||
|  |  | ||||||
| [array] $vendors = @( "clang", "msvc" ) | [array] $vendors = @( "clang", "msvc" ) | ||||||
| @@ -36,6 +60,8 @@ if ( $args ) { $args | ForEach-Object { | |||||||
| 		"debug"               { $release      = $false } | 		"debug"               { $release      = $false } | ||||||
| 		"bootstrap"           { $bootstrap    = $true } | 		"bootstrap"           { $bootstrap    = $true } | ||||||
| 		"singleheader"        { $singleheader = $true } | 		"singleheader"        { $singleheader = $true } | ||||||
|  | 		"c_library"           { $c_library    = $true } | ||||||
|  | 		"unreal"              { $unreal       = $true } | ||||||
| 		"test"                { $test         = $true } | 		"test"                { $test         = $true } | ||||||
| 	} | 	} | ||||||
| }} | }} | ||||||
| @@ -64,7 +90,7 @@ else { | |||||||
| 	$optimize = $true | 	$optimize = $true | ||||||
| } | } | ||||||
|  |  | ||||||
| if ( $bootstrap -eq $false -and $singleheader -eq $false -and $test -eq $false ) { | if ( $bootstrap -eq $false -and $singleheader -eq $false -and $c_library -eq $false -and $unreal -eq $false -and $test -eq $false ) { | ||||||
| 	throw "No build target specified. One must be specified, this script will not assume one" | 	throw "No build target specified. One must be specified, this script will not assume one" | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -79,7 +105,9 @@ write-host "Build Type: $(if ($release) {"Release"} else {"Debug"} )" | |||||||
| $path_build        = Join-Path $path_root build | $path_build        = Join-Path $path_root build | ||||||
| $path_project      = Join-Path $path_root project | $path_project      = Join-Path $path_root project | ||||||
| $path_scripts      = Join-Path $path_root scripts | $path_scripts      = Join-Path $path_root scripts | ||||||
| $path_singleheader = Join-Path $path_root singleheader | $path_c_library    = join-Path $path_root gen_c_library | ||||||
|  | $path_singleheader = Join-Path $path_root gen_singleheader | ||||||
|  | $path_unreal       = Join-Path $path_root gen_unreal_engine | ||||||
| $path_test         = Join-Path $path_root test | $path_test         = Join-Path $path_root test | ||||||
|  |  | ||||||
| if ( $bootstrap ) | if ( $bootstrap ) | ||||||
| @@ -162,6 +190,84 @@ if ( $singleheader ) | |||||||
| 	Pop-Location | 	Pop-Location | ||||||
| } | } | ||||||
|  |  | ||||||
|  | if ( $c_library ) | ||||||
|  | { | ||||||
|  | 	$path_build = join-path $path_c_library build | ||||||
|  | 	$path_gen   = join-path $path_c_library gen | ||||||
|  |  | ||||||
|  | 	if ( -not(Test-Path($path_build) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_build | ||||||
|  | 	} | ||||||
|  | 	if ( -not(Test-Path($path_gen) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_gen | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$includes    = @( $path_project ) | ||||||
|  | 	$unit       = join-path $path_c_library "c_library.cpp" | ||||||
|  | 	$executable = join-path $path_build     "c_library.exe" | ||||||
|  |  | ||||||
|  | 	$compiler_args = @() | ||||||
|  | 	$compiler_args += ( $flag_define + 'GEN_TIME' ) | ||||||
|  |  | ||||||
|  | 	$linker_args   = @( | ||||||
|  | 		$flag_link_win_subsystem_console | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
|  | 	Push-Location $path_c_library | ||||||
|  | 		if ( Test-Path( $executable ) ) { | ||||||
|  | 			write-host "`nRunning c_library generator" | ||||||
|  | 			$time_taken = Measure-Command { & $executable | ||||||
|  | 					| ForEach-Object { | ||||||
|  | 						write-host `t $_ -ForegroundColor Green | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms" | ||||||
|  | 		} | ||||||
|  | 	Pop-Location | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if ( $unreal ) | ||||||
|  | { | ||||||
|  | 	$path_build = join-path $path_unreal build | ||||||
|  | 	$path_gen   = join-path $path_unreal gen | ||||||
|  |  | ||||||
|  | 	if ( -not(Test-Path($path_build) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_build | ||||||
|  | 	} | ||||||
|  | 	if ( -not(Test-Path($path_gen) )) { | ||||||
|  | 		New-Item -ItemType Directory -Path $path_gen | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	$includes    = @( $path_project ) | ||||||
|  | 	$unit       = join-path $path_unreal "unreal.cpp" | ||||||
|  | 	$executable = join-path $path_build  "unreal.exe" | ||||||
|  |  | ||||||
|  | 	$compiler_args = @() | ||||||
|  | 	$compiler_args += ( $flag_define + 'GEN_TIME' ) | ||||||
|  |  | ||||||
|  | 	$linker_args   = @( | ||||||
|  | 		$flag_link_win_subsystem_console | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|  |  | ||||||
|  | 	Push-Location $path_unreal | ||||||
|  | 		if ( Test-Path( $executable ) ) { | ||||||
|  | 			write-host "`nRunning unreal variant generator" | ||||||
|  | 			$time_taken = Measure-Command { & $executable | ||||||
|  | 					| ForEach-Object { | ||||||
|  | 						write-host `t $_ -ForegroundColor Green | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			write-host "`n Unreal variant generator completed in $($time_taken.TotalMilliseconds) ms" | ||||||
|  | 		} | ||||||
|  | 	Pop-Location | ||||||
|  |  | ||||||
|  | 	. $refactor_unreal | ||||||
|  | } | ||||||
|  |  | ||||||
| if ( $test ) | if ( $test ) | ||||||
| { | { | ||||||
| 	$path_gen          = join-path $path_test gen | 	$path_gen          = join-path $path_test gen | ||||||
| @@ -226,10 +332,9 @@ if ( $test ) | |||||||
|  |  | ||||||
| #region Formatting | #region Formatting | ||||||
| push-location $path_scripts | push-location $path_scripts | ||||||
| if ( $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) | if ( $true -and $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) | ||||||
| { | { | ||||||
| 	$path_gen      = join-path $path_project gen | 	$path_gen      = join-path $path_project gen | ||||||
| 	$path_comp_gen = join-path $path_project components/gen |  | ||||||
| 	$include  = @( | 	$include  = @( | ||||||
| 		'gen.hpp', 'gen.cpp', | 		'gen.hpp', 'gen.cpp', | ||||||
| 		'gen.dep.hpp', 'gen.dep.cpp', | 		'gen.dep.hpp', 'gen.dep.cpp', | ||||||
| @@ -237,12 +342,12 @@ if ( $bootstrap -and (Test-Path (Join-Path $path_project "gen/gen.hpp")) ) | |||||||
| 		'gen.scanner.hpp', 'gen.scanner.cpp' | 		'gen.scanner.hpp', 'gen.scanner.cpp' | ||||||
| 	) | 	) | ||||||
| 	$exclude  = $null | 	$exclude  = $null | ||||||
| 	format-cpp $path_gen $include $exclude | 	# format-cpp $path_gen $include $exclude | ||||||
| 	format-cpp $path_comp_gen @( 'ast_inlines.hpp', 'ecode.hpp', 'especifier.hpp', 'eoperator.hpp', 'etoktype.cpp' ) $null | 	format-cpp $path_comp_gen @( 'ast_inlines.hpp', 'ecode.hpp', 'especifier.hpp', 'eoperator.hpp', 'etoktype.cpp' ) $null | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| if ( $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp")) ) | if ( $false -and $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp")) ) | ||||||
| { | { | ||||||
| 	$path_gen = join-path $path_singleheader gen | 	$path_gen = join-path $path_singleheader gen | ||||||
| 	$include  = @( | 	$include  = @( | ||||||
| @@ -252,6 +357,19 @@ if ( $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp")) | |||||||
| 	format-cpp $path_gen $include $exclude | 	format-cpp $path_gen $include $exclude | ||||||
| } | } | ||||||
|  |  | ||||||
|  | if ( $false -and $unreal -and (Test-Path( Join-Path $path_unreal "gen/gen.hpp")) ) | ||||||
|  | { | ||||||
|  | 	$path_gen = join-path $path_unreal gen | ||||||
|  | 	$include  = @( | ||||||
|  | 		'gen.hpp', 'gen.cpp', | ||||||
|  | 		'gen.dep.hpp', 'gen.dep.cpp', | ||||||
|  | 		'gen.builder.hpp', 'gen.builder.cpp' | ||||||
|  | 		'gen.scanner.hpp', 'gen.scanner.cpp' | ||||||
|  | 	) | ||||||
|  | 	$exclude  = $null | ||||||
|  | 	format-cpp $path_gen $include $exclude | ||||||
|  | } | ||||||
|  |  | ||||||
| if ( $test -and $false ) | if ( $test -and $false ) | ||||||
| { | { | ||||||
| 	$path_gen = join-path $path_test gen | 	$path_gen = join-path $path_test gen | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								scripts/c_library.refactor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								scripts/c_library.refactor
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  |  __VERSION 1 | ||||||
|  |  | ||||||
|  | // This is a example template to be used with the refactor program | ||||||
|  | // Use it to refactor the naming convention of this library to your own. | ||||||
|  | // Can be used as an aid to help use use your project's implementation if it fullfills the dependencies of this project. | ||||||
|  | // Example: Most likely have a memory and string library already, just rename the functions and make sure the args are the same. | ||||||
|  | // Program: https://github.com/Ed94/refactor | ||||||
|  |  | ||||||
|  | // NOTE: Due to the current limitations of the program, not every symbol in the library can be renamed. | ||||||
|  | // This is due to the program not actually parsing C/C++. | ||||||
|  |  | ||||||
|  | // not       : Ignore | ||||||
|  | // include   : #includes | ||||||
|  | // word      : Alphanumeric or underscore | ||||||
|  | // namespace : Prefix search and replace (c-namspaces). | ||||||
|  | // regex     : Unavailable in __VERSION 1. | ||||||
|  |  | ||||||
|  | // Precedence (highest to lowest): | ||||||
|  | // word, namespace, regex | ||||||
|  |  | ||||||
|  | // Gen Macro namespace | ||||||
|  | // namespace GEN_, new_namespace_ | ||||||
|  |  | ||||||
|  | // TODO(Ed): This will be large as nearly all symbols will need to optionally support getting prefixed with gen_ or something else the user wants. | ||||||
| @@ -43,9 +43,6 @@ | |||||||
| // word GEN_COMPILER_MINGW, new_name | // word GEN_COMPILER_MINGW, new_name | ||||||
| // word GEN_COMPILER_MSVC,  new_name | // word GEN_COMPILER_MSVC,  new_name | ||||||
|  |  | ||||||
|     // General |  | ||||||
| // word zpl_cast, new_name |  | ||||||
|  |  | ||||||
| // word global,        new_name | // word global,        new_name | ||||||
| // word internal,      new_name | // word internal,      new_name | ||||||
| // word local_persist, new_name | // word local_persist, new_name | ||||||
| @@ -150,8 +147,8 @@ | |||||||
| // word u16,  new_name | // word u16,  new_name | ||||||
| // word u32,  new_name | // word u32,  new_name | ||||||
| // word u64,  new_name | // word u64,  new_name | ||||||
| // word uw,   new_name | // word usize,   new_name | ||||||
| // word sw,   new_name | // word ssize,   new_name | ||||||
| // word sptr, new_name | // word sptr, new_name | ||||||
| // word uptr, new_name | // word uptr, new_name | ||||||
| // word f32,  new_name | // word f32,  new_name | ||||||
|   | |||||||
| @@ -3,46 +3,89 @@ cls | |||||||
| $build = Join-Path $PSScriptRoot 'build.ci.ps1' | $build = Join-Path $PSScriptRoot 'build.ci.ps1' | ||||||
|  |  | ||||||
| if ( $IsWindows ) { | if ( $IsWindows ) { | ||||||
| 	& $build release msvc bootstrap singleheader | 	& $build release msvc bootstrap singleheader unreal msvc debug | ||||||
| } | } | ||||||
| else { | else { | ||||||
| 	& $build release clang bootstrap singleheader | 	& $build release clang bootstrap singleheader unreal msvc debug | ||||||
| } | } | ||||||
|  |  | ||||||
| $path_root             = git rev-parse --show-toplevel | $path_root             = git rev-parse --show-toplevel | ||||||
| $path_docs			   = Join-Path $path_root docs | $path_docs			   = Join-Path $path_root         docs | ||||||
| $path_project          = Join-Path $path_root project | $path_project          = Join-Path $path_root         project | ||||||
| $path_project_gen      = Join-Path $path_project gen | $path_project_gen      = Join-Path $path_project      gen | ||||||
| $path_singleheader	   = Join-Path $path_root singleheader | $path_singleheader	   = Join-Path $path_root         singleheader | ||||||
| $path_singleheader_gen = Join-Path $path_singleheader gen | $path_singleheader_gen = Join-Path $path_singleheader gen | ||||||
| $path_release          = Join-Path $path_root release | $path_unreal           = Join-Path $path_root         unreal_engine | ||||||
| $path_release_content  = Join-Path $path_release content | $path_unreal_gen       = Join-Path $path_unreal       gen | ||||||
|  | $path_release          = Join-Path $path_root         release | ||||||
|  | $path_release_content  = Join-Path $path_release      content | ||||||
|  |  | ||||||
| if ( -not(Test-Path $path_release) ) { | if ( -not(Test-Path $path_release) ) { | ||||||
| 	New-Item -ItemType Directory -Path $path_release | 	New-Item -ItemType Directory -Path $path_release | ||||||
| } | } | ||||||
|  |  | ||||||
| if ( -not(Test-Path $path_release_content) ) { | function prep-ReleaseContent() | ||||||
|  | { | ||||||
| 	New-Item -ItemType Directory -Path $path_release_content | 	New-Item -ItemType Directory -Path $path_release_content | ||||||
|  |  | ||||||
|  | 	$license            = Join-Path $path_root LICENSE | ||||||
|  | 	$readme_root        = Join-Path $path_root Readme.md | ||||||
|  | 	$readme_docs        = Join-Path $path_docs Readme.md | ||||||
|  | 	$readme_ast_design  = Join-Path $path_docs AST_Design.md | ||||||
|  | 	$readme_ast_types   = Join-Path $path_docs AST_Types.md | ||||||
|  | 	$readme_parsing     = Join-Path $path_docs Parsing.md | ||||||
|  | 	$readme_parser_algo = Join-Path $path_docs Parser_Algo.md | ||||||
|  |  | ||||||
|  | 	Copy-Item $license		      -Destination (Join-Path $path_release_content "LICENSE") | ||||||
|  | 	Copy-Item $readme_root        -Destination (Join-Path $path_release_content "Readme.md") | ||||||
|  | 	Copy-Item $readme_docs        -Destination (Join-Path $path_release_content "Readme_Docs.md") | ||||||
|  | 	Copy-Item $readme_ast_design  -Destination (Join-Path $path_release_content "AST_Design.md") | ||||||
|  | 	Copy-Item $readme_ast_types   -Destination (Join-Path $path_release_content "AST_Types.md") | ||||||
|  | 	Copy-Item $readme_parsing     -Destination (Join-Path $path_release_content "Parsing.md") | ||||||
|  | 	Copy-Item $readme_parser_algo -Destination (Join-Path $path_release_content "Parser_Algo.md") | ||||||
| } | } | ||||||
|  |  | ||||||
| $license        = Join-Path $path_root LICENSE |  | ||||||
| $readme_root    = Join-Path $path_root Readme.md |  | ||||||
| $readme_docs    = Join-Path $path_docs Readme.md |  | ||||||
| $readme_parsing = Join-Path $path_docs Parsing.md |  | ||||||
|  |  | ||||||
| Copy-Item $license		  -Destination (Join-Path $path_release_content "LICENSE") |  | ||||||
| Copy-Item $readme_root    -Destination (Join-Path $path_release_content "Readme.md") |  | ||||||
| Copy-Item $readme_docs    -Destination (Join-Path $path_release_content "Readme_Docs.md") |  | ||||||
| Copy-Item $readme_parsing -Destination (Join-Path $path_release_content "Parsing.md") |  | ||||||
|  |  | ||||||
| # Singleheader | # Singleheader | ||||||
|  | prep-ReleaseContent | ||||||
| Copy-Item        -Path $path_singleheader_gen\gen.hpp -Destination $path_release_content\gen.hpp | Copy-Item        -Path $path_singleheader_gen\gen.hpp -Destination $path_release_content\gen.hpp | ||||||
| Compress-Archive -Path $path_release_content\*        -DestinationPath $path_release\gencpp_singleheader.zip -Force | Compress-Archive -Path $path_release_content\*        -DestinationPath $path_release\gencpp_singleheader.zip -Force | ||||||
| Remove-Item      -Path $path_release_content\gen.hpp | Remove-Item -Path $path_release_content -Recurse | ||||||
|  |  | ||||||
| # Segmented | # Segmented | ||||||
|  | prep-ReleaseContent | ||||||
| Copy-Item        -Path $path_project_gen\*     -Destination $path_release_content | Copy-Item        -Path $path_project_gen\*     -Destination $path_release_content | ||||||
| Compress-Archive -Path $path_release_content\* -DestinationPath $path_release\gencpp_segmented.zip -Force | Compress-Archive -Path $path_release_content\* -DestinationPath $path_release\gencpp_segmented.zip -Force | ||||||
|  | Remove-Item -Path $path_release_content -Recurse | ||||||
|  |  | ||||||
|  | # Unreal | ||||||
|  | prep-ReleaseContent | ||||||
|  | Copy-Item        -Path $path_unreal_gen\*      -Destination $path_release_content | ||||||
|  | Compress-Archive -Path $path_release_content\* -DestinationPath $path_release\gencpp_unreal.zip -Force | ||||||
|  | Remove-Item -Path $path_release_content -Recurse | ||||||
|  |  | ||||||
|  | # As Is | ||||||
|  |  | ||||||
|  | prep-ReleaseContent | ||||||
|  | Copy-Item        -Verbose -Path $path_project\gen.hpp               -Destination $path_release_content | ||||||
|  | Copy-Item        -Verbose -Path $path_project\gen.cpp               -Destination $path_release_content | ||||||
|  | Copy-Item        -Verbose -Path $path_project\gen.dep.hpp           -Destination $path_release_content | ||||||
|  | Copy-Item        -Verbose -Path $path_project\gen.dep.cpp           -Destination $path_release_content | ||||||
|  | Copy-Item        -Verbose -Path $path_project\auxillary\builder.hpp -Destination $path_release_content\auxillary | ||||||
|  | Copy-Item        -Verbose -Path $path_project\auxillary\builder.cpp -Destination $path_release_content\auxillary | ||||||
|  | Copy-Item        -Verbose -Path $path_project\auxillary\scanner.hpp -Destination $path_release_content\auxillary | ||||||
|  | Copy-Item        -Verbose -Path $path_project\auxillary\scanner.cpp -Destination $path_release_content\auxillary | ||||||
|  |  | ||||||
|  | New-Item -ItemType Directory -Force -Path "$path_release_content\components" | ||||||
|  | New-Item -ItemType Directory -Force -Path "$path_release_content\components\gen" | ||||||
|  | New-Item -ItemType Directory -Force -Path "$path_release_content\dependencies" | ||||||
|  | New-Item -ItemType Directory -Force -Path "$path_release_content\enums" | ||||||
|  | New-Item -ItemType Directory -Force -Path "$path_release_content\helpers" | ||||||
|  |  | ||||||
|  | Get-ChildItem -Verbose -Path "$path_project\components\*"     -Include *.cpp,*.hpp | Copy-Item -Destination "$path_release_content\components" | ||||||
|  | Get-ChildItem -Verbose -Path "$path_project\components\gen\*" -Include *.cpp,*.hpp | Copy-Item -Destination "$path_release_content\components\gen" | ||||||
|  | Get-ChildItem -Verbose -Path "$path_project\dependencies\*"   -Include *.cpp,*.hpp | Copy-Item -Destination "$path_release_content\dependencies" | ||||||
|  | Get-ChildItem -Verbose -Path "$path_project\enums\*"          -Include *.csv       | Copy-Item -Destination "$path_release_content\enums" | ||||||
|  | Get-ChildItem -Verbose -Path "$path_project\helpers\*"        -Include *.cpp,*.hpp | Copy-Item -Destination "$path_release_content\helpers" | ||||||
|  |  | ||||||
|  | Compress-Archive -Path $path_release_content\** -DestinationPath $path_release\gencpp_as_is.zip -Force | ||||||
| Remove-Item -Path $path_release_content -Recurse | Remove-Item -Path $path_release_content -Recurse | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user