mirror of
				https://github.com/Ed94/gencpp.git
				synced 2025-10-31 06:50:53 -07:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			6081834687
			...
			cae1555b11
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cae1555b11 | |||
| f7709bb64e | |||
| 3a55af9ce4 | 
							
								
								
									
										18
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -40,7 +40,23 @@ | |||||||
| 		"*.m": "cpp", | 		"*.m": "cpp", | ||||||
| 		"atomic": "cpp", | 		"atomic": "cpp", | ||||||
| 		"gen.h": "c", | 		"gen.h": "c", | ||||||
| 		"string_ops.hpp": "c" | 		"string_ops.hpp": "c", | ||||||
|  | 		"assert.h": "c", | ||||||
|  | 		"intrin.h": "c", | ||||||
|  | 		"bit": "cpp", | ||||||
|  | 		"cmath": "cpp", | ||||||
|  | 		"cstddef": "cpp", | ||||||
|  | 		"cstdint": "cpp", | ||||||
|  | 		"cstdio": "cpp", | ||||||
|  | 		"cstdlib": "cpp", | ||||||
|  | 		"cstring": "cpp", | ||||||
|  | 		"ctime": "cpp", | ||||||
|  | 		"cwchar": "cpp", | ||||||
|  | 		"iosfwd": "cpp", | ||||||
|  | 		"new": "cpp", | ||||||
|  | 		"typeinfo": "cpp", | ||||||
|  | 		"unordered_map": "cpp", | ||||||
|  | 		"xstddef": "cpp" | ||||||
| 	}, | 	}, | ||||||
| 	"C_Cpp.intelliSenseEngineFallback": "disabled", | 	"C_Cpp.intelliSenseEngineFallback": "disabled", | ||||||
| 	"mesonbuild.configureOnOpen": true, | 	"mesonbuild.configureOnOpen": true, | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ constexpr StrC implementation_guard_end = txt(R"( | |||||||
|  |  | ||||||
| void format_file( char const* path ) | void format_file( char const* path ) | ||||||
| { | { | ||||||
| 	String resolved_path = String::make(GlobalAllocator, to_str(path)); | 	String resolved_path = String::make(GlobalAllocator, to_strc_from_c_str(path)); | ||||||
|  |  | ||||||
| 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | 	String style_arg = String::make(GlobalAllocator, txt("-style=file:")); | ||||||
| 	style_arg.append("../scripts/.clang-format "); | 	style_arg.append("../scripts/.clang-format "); | ||||||
| @@ -100,6 +100,9 @@ int gen_main() | |||||||
| #define project_dir "../project/" | #define project_dir "../project/" | ||||||
| 	gen::init(); | 	gen::init(); | ||||||
|  |  | ||||||
|  | 	PreprocessorDefines.append(txt("GEN_API_C_BEGIN")); | ||||||
|  | 	PreprocessorDefines.append(txt("GEN_API_C_END")); | ||||||
|  |  | ||||||
| 	Code push_ignores           = scan_file( project_dir "helpers/push_ignores.inline.hpp" ); | 	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 pop_ignores            = scan_file( project_dir "helpers/pop_ignores.inline.hpp" ); | ||||||
| 	Code c_library_header_start = scan_file( "components/header_start.hpp" ); | 	Code c_library_header_start = scan_file( "components/header_start.hpp" ); | ||||||
| @@ -127,15 +130,32 @@ int gen_main() | |||||||
| 		header.print( basic_types ); | 		header.print( basic_types ); | ||||||
| 		header.print( debug ); | 		header.print( debug ); | ||||||
|  |  | ||||||
|  | 		// Array(StrC) to_rename = array_init_reserve(StrC, GlobalAllocator, 128); | ||||||
|  | 		// to_rename.append(txt("align_forward")); | ||||||
|  | 		// to_rename.append(txt("pointer_add")); | ||||||
|  | 		// to_rename.append(txt("allocator_info")); | ||||||
|  | 		// to_rename.append(txt("size_remaining")); | ||||||
|  | 		// to_rename.append(txt("free")); | ||||||
|  | 		// to_rename.append(txt("clear")); | ||||||
|  | 		// to_rename.append(txt("init_sub")); | ||||||
|  | 		// to_rename.append(txt("check")); | ||||||
|  |  | ||||||
|  | 		// NeedsSelectors needs_selectors; | ||||||
|  | 		// needs_selectors.table = hashtable_init_reserve(Array(CodeFn), GlobalAllocator, 1024); | ||||||
|  | 		// for ( StrC id : to_rename ) { | ||||||
|  | 		// 	needs_selectors.set(id, array_init_reserve(CodeFn, GlobalAllocator, 128)); | ||||||
|  | 		// } | ||||||
|  |  | ||||||
| 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | 		CodeBody parsed_memory = parse_file( project_dir "dependencies/memory.hpp" ); | ||||||
| 		CodeBody memory        = def_body(CT_Global_Body); | 		CodeBody memory        = def_body(CT_Global_Body); | ||||||
|  |  | ||||||
| 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) | 		for ( Code entry = parsed_memory.begin(); entry != parsed_memory.end(); ++ entry ) | ||||||
| 		{ | 		{ | ||||||
| 			switch (entry->Type) | 			switch (entry->Type) | ||||||
| 			{ | 			{ | ||||||
| 				case CT_Using: | 				case CT_Using: | ||||||
| 				{ | 				{ | ||||||
| 					log_fmt("REPLACE THIS MANUALLY: %S\n", entry->Name); | 					log_fmt("REPLACE THIS MANUALLY: %SC\n", entry->Name); | ||||||
| 					CodeUsing   using_ver   = cast(CodeUsing, entry); | 					CodeUsing   using_ver   = cast(CodeUsing, entry); | ||||||
| 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | 					CodeTypedef typedef_ver = def_typedef(using_ver->Name, using_ver->UnderlyingType); | ||||||
|  |  | ||||||
| @@ -145,11 +165,10 @@ int gen_main() | |||||||
| 				case CT_Function_Fwd: | 				case CT_Function_Fwd: | ||||||
| 				{ | 				{ | ||||||
| 					CodeFn fn = cast(CodeFn, entry); | 					CodeFn fn = cast(CodeFn, entry); | ||||||
| 					if ( fn->Name.is_equal(txt("free")) ) | 					// for ( StrC id : to_rename ) if (fn->Name.is_equal(id)) { | ||||||
| 					{ | 					// 	rename_function_to_unique_symbol(fn); | ||||||
| 						fn->Name = get_cached_string(txt("gen_free_ptr")); | 					// } | ||||||
| 					} | 					memory.append(fn); | ||||||
| 					memory.append(entry); |  | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 				case CT_Function: | 				case CT_Function: | ||||||
| @@ -160,11 +179,11 @@ int gen_main() | |||||||
| 						log_fmt("Found constexpr: %S\n", entry.to_string()); | 						log_fmt("Found constexpr: %S\n", entry.to_string()); | ||||||
| 						fn->Specs.append(Spec_Inline); | 						fn->Specs.append(Spec_Inline); | ||||||
| 					} | 					} | ||||||
| 					if ( fn->Name.is_equal(txt("free")) ) | 					// for ( StrC id : to_rename ) if (fn->Name.is_equal(id)) { | ||||||
| 					{ | 					// 	Array(CodeFn) list = * needs_selectors.get(id); | ||||||
| 						fn->Name = get_cached_string(txt("gen_free_ptr")); | 					// 	list.append(rename_function_to_unique_symbol(fn)); | ||||||
| 					} | 					// } | ||||||
| 					memory.append(entry); | 					memory.append(fn); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 				case CT_Template: | 				case CT_Template: | ||||||
| @@ -213,6 +232,9 @@ int gen_main() | |||||||
| 					b32 found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, parsed_memory ); | 					b32 found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_MEMBER_FEATURES"), entry, parsed_memory ); | ||||||
| 					if (found) break; | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_REFERENCES"), entry, parsed_memory ); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
| 					memory.append(entry); | 					memory.append(entry); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| @@ -226,6 +248,12 @@ int gen_main() | |||||||
| 				break; | 				break; | ||||||
| 				case CT_Preprocess_Pragma: | 				case CT_Preprocess_Pragma: | ||||||
| 				{ | 				{ | ||||||
|  | 					CodePragma pragma = cast(CodePragma, entry); | ||||||
|  | 					// if (pragma->Content.starts_with(txt("region Memory"))) { | ||||||
|  | 					// 	memory.append(generic_test); | ||||||
|  | 					// 	break; | ||||||
|  | 					// } | ||||||
|  |  | ||||||
| 					b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); | 					b32 found = swap_pragma_region_implementation( txt("FixedArena"), gen_fixed_arenas, entry, memory); | ||||||
| 					if (found) break; | 					if (found) break; | ||||||
|  |  | ||||||
| @@ -238,10 +266,15 @@ int gen_main() | |||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// CodeBody selectors = generate_generic_selectors(needs_selectors); | ||||||
|  | 		// memory.append_at(selectors, 0) | ||||||
|  | 		// memory.append(fmt_newline); | ||||||
|  |  | ||||||
| 		header.print( dump_to_scratch_and_retireve(memory) ); | 		header.print( dump_to_scratch_and_retireve(memory) ); | ||||||
|  |  | ||||||
| 		Code string_ops = scan_file( project_dir "dependencies/string_ops.hpp" ); | 		Code string_ops = scan_file( project_dir "dependencies/string_ops.hpp" ); | ||||||
| 		header.print( string_ops ); | 		// header.print( string_ops ); | ||||||
|  |  | ||||||
| 		CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" ); | 		CodeBody printing_parsed = parse_file( project_dir "dependencies/printing.hpp" ); | ||||||
| 		CodeBody printing        = def_body(CT_Global_Body); | 		CodeBody printing        = def_body(CT_Global_Body); | ||||||
| @@ -259,7 +292,7 @@ int gen_main() | |||||||
| 				break; | 				break; | ||||||
| 				case CT_Variable: | 				case CT_Variable: | ||||||
| 				{ | 				{ | ||||||
| 					if (contains(entry->Name, txt("Msg_Invalid_Value"))) | 					if ( strc_contains(entry->Name, txt("Msg_Invalid_Value"))) | ||||||
| 					{ | 					{ | ||||||
| 						CodeDefine define = def_define(entry->Name, entry->Value->Content); | 						CodeDefine define = def_define(entry->Name, entry->Value->Content); | ||||||
| 						printing.append(define); | 						printing.append(define); | ||||||
| @@ -273,7 +306,7 @@ int gen_main() | |||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		header.print(dump_to_scratch_and_retireve(printing)); | 		// header.print(dump_to_scratch_and_retireve(printing)); | ||||||
|  |  | ||||||
| 		CodeBody containers = def_body(CT_Global_Body); | 		CodeBody containers = def_body(CT_Global_Body); | ||||||
| 		{ | 		{ | ||||||
| @@ -285,10 +318,10 @@ int gen_main() | |||||||
| 			containers.append( def_pragma(code(endregion Containers))); | 			containers.append( def_pragma(code(endregion Containers))); | ||||||
| 		} | 		} | ||||||
| 		header.print(fmt_newline); | 		header.print(fmt_newline); | ||||||
| 		header.print(dump_to_scratch_and_retireve(containers)); | 		// header.print(dump_to_scratch_and_retireve(containers)); | ||||||
|  |  | ||||||
| 		Code hashing = scan_file( project_dir "dependencies/hashing.hpp" ); | 		Code hashing = scan_file( project_dir "dependencies/hashing.hpp" ); | ||||||
| 		header.print( hashing ); | 		// header.print( hashing ); | ||||||
|  |  | ||||||
| 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | 		CodeBody parsed_strings = parse_file( project_dir "dependencies/strings.hpp" ); | ||||||
| 		CodeBody strings        = def_body(CT_Global_Body); | 		CodeBody strings        = def_body(CT_Global_Body); | ||||||
| @@ -298,7 +331,22 @@ int gen_main() | |||||||
| 			{ | 			{ | ||||||
| 				case CT_Preprocess_If: | 				case CT_Preprocess_If: | ||||||
| 				{ | 				{ | ||||||
| 					ignore_preprocess_cond_block(txt("! GEN_COMPILER_C"), entry, parsed_strings); | 					CodePreprocessCond cond = cast(CodePreprocessCond, entry); | ||||||
|  | 					if (cond->Content.starts_with(txt("GEN_COMPILER_C || ! GEN_SUPPORT_CPP_MEMBER_FEATURES"))) | ||||||
|  | 					{ | ||||||
|  | 						++ entry; | ||||||
|  | 						strings.append(entry); // typedef | ||||||
|  | 						strings.append(fmt_newline); | ||||||
|  |  | ||||||
|  | 						for (; entry != end(parsed_strings) && entry->Type != CT_Preprocess_EndIf; ++ entry) {} | ||||||
|  | 						++ entry; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					bool found = ignore_preprocess_cond_block(txt("! GEN_COMPILER_C"), entry, parsed_strings); | ||||||
|  | 					if (found) break; | ||||||
|  |  | ||||||
|  | 					found = ignore_preprocess_cond_block(txt("GEN_SUPPORT_CPP_REFERENCES"), entry, parsed_strings); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
|  |  | ||||||
| @@ -350,7 +398,7 @@ int gen_main() | |||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		header.print(dump_to_scratch_and_retireve(strings)); | 		// header.print(dump_to_scratch_and_retireve(strings)); | ||||||
|  |  | ||||||
| 		Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" ); | 		Code filesystem = scan_file( project_dir "dependencies/filesystem.hpp" ); | ||||||
| 		Code timing = scan_file( project_dir "dependencies/timing.hpp" ); | 		Code timing = scan_file( project_dir "dependencies/timing.hpp" ); | ||||||
|   | |||||||
| @@ -283,11 +283,11 @@ CodeBody gen_array( StrC type, StrC array_name ) | |||||||
| #pragma pop_macro( "GEN_ASSERT" ) | #pragma pop_macro( "GEN_ASSERT" ) | ||||||
|  |  | ||||||
| 	return def_global_body( args( | 	return def_global_body( args( | ||||||
| 		def_pragma( to_str( str_fmt_buf( "region %S", array_type ))), | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "region %S", array_type ))), | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		result, | 		result, | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		def_pragma( to_str( str_fmt_buf( "endregion %S", array_type ))), | 		def_pragma( string_to_strc(string_fmt_buf( GlobalAllocator, "endregion %S", array_type ))), | ||||||
| 		fmt_newline | 		fmt_newline | ||||||
| 	)); | 	)); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -341,14 +341,14 @@ CodeBody gen_hashtable( StrC type, StrC hashtable_name ) | |||||||
| 		, type.Len, type.Ptr ); | 		, type.Len, type.Ptr ); | ||||||
|  |  | ||||||
| 	return def_global_body(args( | 	return def_global_body(args( | ||||||
| 		def_pragma( to_str( str_fmt_buf( "region %S", tbl_type ))), | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "region %S", tbl_type ))), | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		hashtable_types, | 		hashtable_types, | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		entry_array, | 		entry_array, | ||||||
| 		hashtable_def, | 		hashtable_def, | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		def_pragma( to_str( str_fmt_buf( "endregion %S", tbl_type ))), | 		def_pragma( string_to_strc( string_fmt_buf( GlobalAllocator, "endregion %S", tbl_type ))), | ||||||
| 		fmt_newline | 		fmt_newline | ||||||
| 	)); | 	)); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,22 +5,67 @@ | |||||||
|  |  | ||||||
| using SwapContentProc = CodeBody(void); | using SwapContentProc = CodeBody(void); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | struct NeedsSelectors { | ||||||
|  | 	HashTable(Array(CodeFn)) table; | ||||||
|  |  | ||||||
|  | 	void set(StrC sig, Array(CodeFn) list) { | ||||||
|  | 		u32  key = crc32(sig.Ptr, sig.Len); | ||||||
|  | 		table.set(key, list); | ||||||
|  | 	} | ||||||
|  | 	Array(CodeFn)* get(StrC sig) { | ||||||
|  | 		u32  key = crc32(sig.Ptr, sig.Len); | ||||||
|  | 		return table.get(key); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | CodeBody generate_generic_selectors(Array(Array(CodeFn)) listing) | ||||||
|  | { | ||||||
|  | 	constexpr char const* tmpl_selector =  | ||||||
|  | R"( #define <base_name>(<params>) \ | ||||||
|  | _Generic(( | ||||||
|  | )) | ||||||
|  | ); | ||||||
|  | )"; | ||||||
|  |  | ||||||
|  | 	CodeBody result = def_body(CT_Global_Body); | ||||||
|  | 	for (Array(CodeFn) functions : listing) | ||||||
|  | 	{ | ||||||
|  | 		 | ||||||
|  | 	} | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
| b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& body ) | b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& body ) | ||||||
| { | { | ||||||
| 	b32 found = false; | 	b32 found = false; | ||||||
| 	CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter); | 	CodePreprocessCond cond = cast(CodePreprocessCond, entry_iter); | ||||||
| 	if ( cond->Content.contains(cond_sig) ) | 	if ( cond->Content.contains(cond_sig) ) | ||||||
| 	{ | 	{ | ||||||
| 		log_fmt("Preprocess cond found: %S\n", cond->Content); | 		log_fmt("Preprocess cond found: %SC\n", cond->Content); | ||||||
| 		found = true; | 		found = true; | ||||||
|  |  | ||||||
| 		s32 depth = 1; | 		s32 depth = 1; | ||||||
| 		++ entry_iter; for(b32 continue_for = true; continue_for && entry_iter != body.end(); ) switch | 		++ entry_iter; | ||||||
|  | 		for(b32 continue_for = true; continue_for && entry_iter != body.end(); ) switch | ||||||
| 		(entry_iter->Type) { | 		(entry_iter->Type) { | ||||||
| 			case CT_Preprocess_If: | 			case CT_Preprocess_If: | ||||||
| 			case CT_Preprocess_IfDef: | 			case CT_Preprocess_IfDef: | ||||||
| 			case CT_Preprocess_IfNotDef: | 			case CT_Preprocess_IfNotDef: | ||||||
| 				depth ++; | 				++ depth; | ||||||
|  | 		 		++ entry_iter; | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 			case CT_Preprocess_Else: | ||||||
|  | 				++ entry_iter; | ||||||
|  | 				for(; continue_for && entry_iter != body.end(); ++ entry_iter) | ||||||
|  | 				{ | ||||||
|  | 					if (entry_iter->Type == CT_Preprocess_EndIf) | ||||||
|  | 					{ | ||||||
|  | 						continue_for = false; | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					body.append(entry_iter); | ||||||
|  | 				} | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 			case CT_Preprocess_EndIf: | 			case CT_Preprocess_EndIf: | ||||||
| @@ -30,6 +75,7 @@ b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& bod | |||||||
| 					continue_for = false; | 					continue_for = false; | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
|  | 				++ entry_iter; | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
| 			default: | 			default: | ||||||
| @@ -41,6 +87,72 @@ b32 ignore_preprocess_cond_block( StrC cond_sig, Code& entry_iter, CodeBody& bod | |||||||
| 	return found; | 	return found; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | CodeFn rename_function_to_unique_symbol(CodeFn fn, StrC optional_prefix = txt("")) | ||||||
|  | { | ||||||
|  |     // Get basic components for the name | ||||||
|  |     StrC old_name = fn->Name; | ||||||
|  |     String new_name; | ||||||
|  |  | ||||||
|  |     // Add prefix if provided | ||||||
|  |     if (optional_prefix.Len) | ||||||
|  |         new_name = string_fmt_buf(GlobalAllocator, "%SC_%SC_", optional_prefix, old_name); | ||||||
|  |     else | ||||||
|  |         new_name = string_fmt_buf(GlobalAllocator, "%SC_", old_name); | ||||||
|  |  | ||||||
|  |     // Add return type to the signature | ||||||
|  |     if (fn->ReturnType) | ||||||
|  |         new_name.append_fmt("_%SC", fn->ReturnType->Name); | ||||||
|  |  | ||||||
|  |     // Add parameter types to create a unique signature | ||||||
|  |     bool first_param = true; | ||||||
|  |     for (CodeParam param = fn->Params; param.ast; param = param->Next) | ||||||
|  |     { | ||||||
|  |         if (param->ValueType) | ||||||
|  |         { | ||||||
|  |             // Add separator for readability | ||||||
|  |             if (first_param) | ||||||
|  |             { | ||||||
|  |                 new_name.append("_P_"); | ||||||
|  |                 first_param = false; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 new_name.append("_"); | ||||||
|  |  | ||||||
|  |             // Add parameter type, handle any specifiers | ||||||
|  |             if (param->ValueType->Specs && param->ValueType->Specs->NumEntries > 0) | ||||||
|  |             { | ||||||
|  |                 // Add specifiers (const, volatile, etc) | ||||||
|  |                 for (Specifier spec : param->ValueType->Specs) | ||||||
|  |                 { | ||||||
|  | 					if (spec == Spec_Ptr) { | ||||||
|  | 						new_name.append("ptr_"); | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  |                     new_name.append_fmt("%SC_", to_str(spec)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             new_name.append_fmt("%SC", param->ValueType->Name); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Handle function specifiers if present | ||||||
|  |     if (fn->Specs && fn->Specs->NumEntries > 0) | ||||||
|  |     { | ||||||
|  |         new_name.append("_S_"); | ||||||
|  |         for (Specifier* spec = begin(fn->Specs);  | ||||||
|  |              spec != end(fn->Specs);  | ||||||
|  |              ++spec) | ||||||
|  |         { | ||||||
|  |             new_name.append_fmt("%SC_", to_str(*spec)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn->Name = new_name; | ||||||
|  |     return fn; | ||||||
|  | } | ||||||
|  |  | ||||||
| bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body ) | bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_content, Code& entry_iter, CodeBody& body ) | ||||||
| { | { | ||||||
| 	bool found = false; | 	bool found = false; | ||||||
| @@ -54,7 +166,8 @@ bool swap_pragma_region_implementation( StrC region_name, SwapContentProc* swap_ | |||||||
| 		// body.append(possible_region); | 		// body.append(possible_region); | ||||||
| 		body.append(swap_content()); | 		body.append(swap_content()); | ||||||
|  |  | ||||||
| 		++ entry_iter; for(b32 continue_for = true; continue_for; ++entry_iter) switch | 		++ entry_iter; | ||||||
|  | 		for(b32 continue_for = true; continue_for; ++entry_iter) switch | ||||||
| 		(entry_iter->Type) { | 		(entry_iter->Type) { | ||||||
| 			case CT_Preprocess_Pragma: | 			case CT_Preprocess_Pragma: | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ Builder Builder::open( char const* path ) | |||||||
|  |  | ||||||
| void Builder::pad_lines( s32 num ) | void Builder::pad_lines( s32 num ) | ||||||
| { | { | ||||||
| 	append( & Buffer,  "\n" ); | 	string_append_strc( & Buffer, txt("\n") ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print( Code code ) | void Builder::print( Code code ) | ||||||
| @@ -29,7 +29,7 @@ void Builder::print( Code code ) | |||||||
| 	String   str = to_string(code); | 	String   str = to_string(code); | ||||||
| 	// const ssize 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 ); | ||||||
| 	append( & Buffer, str ); | 	string_append_string( & Buffer, str ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::print_fmt( char const* fmt, ... ) | void Builder::print_fmt( char const* fmt, ... ) | ||||||
| @@ -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 ); | ||||||
| 	append( (String*) & Buffer, (char const*)buf, res ); | 	string_append_c_str_len( (String*) & Buffer, (char const*)buf, res ); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Builder::write() | void Builder::write() | ||||||
| { | { | ||||||
| 	b32 result = file_write( & File, Buffer, length(Buffer) ); | 	b32 result = file_write( & File, Buffer, string_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 ); | ||||||
| 	free(& Buffer); | 	string_free(& Buffer); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ Code scan_file( char const* 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 ); | ||||||
| 		get_header(str)->Length = fsize; | 		string_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. | ||||||
| @@ -52,7 +52,7 @@ Code scan_file( char const* path ) | |||||||
|  |  | ||||||
| 				if ( ! found_directive ) | 				if ( ! found_directive ) | ||||||
| 				{ | 				{ | ||||||
| 					if ( left && str_compare( scanner, directive_start.Ptr, directive_start.Len ) == matched ) | 					if ( left && str_compare_len( scanner, directive_start.Ptr, directive_start.Len ) == matched ) | ||||||
| 					{ | 					{ | ||||||
| 						scanner += directive_start.Len; | 						scanner += directive_start.Len; | ||||||
| 						left    -= directive_start.Len; | 						left    -= directive_start.Len; | ||||||
| @@ -60,7 +60,7 @@ Code scan_file( char const* path ) | |||||||
| 						while ( left && char_is_space( current ) ) | 						while ( left && char_is_space( current ) ) | ||||||
| 							move_fwd(); | 							move_fwd(); | ||||||
|  |  | ||||||
| 						if ( left && str_compare( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) | 						if ( left && str_compare_len( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched ) | ||||||
| 						{ | 						{ | ||||||
| 							scanner += def_intellisense.Len; | 							scanner += def_intellisense.Len; | ||||||
| 							left    -= def_intellisense.Len; | 							left    -= def_intellisense.Len; | ||||||
| @@ -80,7 +80,7 @@ Code scan_file( char const* path ) | |||||||
| 					continue; | 					continue; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if ( left && str_compare( scanner, directive_end.Ptr, directive_end.Len ) == matched ) | 				if ( left && str_compare_len( scanner, directive_end.Ptr, directive_end.Len ) == matched ) | ||||||
| 				{ | 				{ | ||||||
| 					scanner += directive_end.Len; | 					scanner += directive_end.Len; | ||||||
| 					left    -= directive_end.Len; | 					left    -= directive_end.Len; | ||||||
| @@ -97,12 +97,12 @@ Code scan_file( char const* path ) | |||||||
| 					if ( (scanner + 2) >= ( (char const*) str + fsize ) ) | 					if ( (scanner + 2) >= ( (char const*) str + fsize ) ) | ||||||
| 					{ | 					{ | ||||||
| 						mem_move( str, scanner, left ); | 						mem_move( str, scanner, left ); | ||||||
| 						get_header(str)->Length = left; | 						string_get_header(str)->Length = left; | ||||||
| 						break; | 						break; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					mem_move( str, scanner, left ); | 					mem_move( str, scanner, left ); | ||||||
| 					get_header(str)->Length = left; | 					string_get_header(str)->Length = left; | ||||||
|  |  | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| @@ -116,7 +116,7 @@ Code scan_file( char const* path ) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	file_close( & file ); | 	file_close( & file ); | ||||||
| 	return untyped_str( to_strc(str) ); | 	return untyped_str( string_to_strc(str) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|   | |||||||
| @@ -26,20 +26,20 @@ constexpr char const* generation_notice = | |||||||
|  |  | ||||||
| void format_file( char const* path ) | void format_file( char const* path ) | ||||||
| { | { | ||||||
| 	String resolved_path = string_make(GlobalAllocator, to_str(path)); | 	String resolved_path = string_make_strc(GlobalAllocator, to_strc_from_c_str(path)); | ||||||
|  |  | ||||||
| 	String style_arg = string_make(GlobalAllocator, txt("-style=file:")); | 	String style_arg = string_make_strc(GlobalAllocator, txt("-style=file:")); | ||||||
| 	append( & style_arg, "../scripts/.clang-format "); | 	string_append_strc( & style_arg, txt("../scripts/.clang-format ")); | ||||||
|  |  | ||||||
| 	// Need to execute clang format on the generated file to get it to match the original. | 	// Need to execute clang format on the generated file to get it to match the original. | ||||||
| 	#define clang_format      "clang-format " | 	#define clang_format      txt("clang-format ") | ||||||
| 	#define cf_format_inplace "-i " | 	#define cf_format_inplace txt("-i ") | ||||||
| 	#define cf_verbose        "-verbose " | 	#define cf_verbose        txt("-verbose ") | ||||||
| 	String command = string_make( GlobalAllocator, clang_format ); | 	String command = string_make_strc( GlobalAllocator, clang_format ); | ||||||
| 	append( & command, cf_format_inplace ); | 	string_append_strc( & command, cf_format_inplace ); | ||||||
| 	append( & command, cf_verbose ); | 	string_append_strc( & command, cf_verbose ); | ||||||
| 	append( & command, style_arg ); | 	string_append_string( & command, style_arg ); | ||||||
| 	append( & command, resolved_path ); | 	string_append_string( & command, resolved_path ); | ||||||
| 		log_fmt("\tRunning clang-format on file:\n"); | 		log_fmt("\tRunning clang-format on file:\n"); | ||||||
| 		system( command ); | 		system( command ); | ||||||
| 		log_fmt("\tclang-format finished reformatting.\n"); | 		log_fmt("\tclang-format finished reformatting.\n"); | ||||||
| @@ -145,7 +145,7 @@ int gen_main() | |||||||
| 		def_include(txt("components/types.hpp")), | 		def_include(txt("components/types.hpp")), | ||||||
| 		preprocess_endif, | 		preprocess_endif, | ||||||
| 		fmt_newline, | 		fmt_newline, | ||||||
| 		untyped_str( to_str(generation_notice) ) | 		untyped_str( to_strc_from_c_str(generation_notice) ) | ||||||
| 	)); | 	)); | ||||||
|  |  | ||||||
| 	// gen.hpp | 	// gen.hpp | ||||||
|   | |||||||
| @@ -14,13 +14,13 @@ char const* debug_str(Code self) | |||||||
| 	String* result       = & result_stack; | 	String* result       = & result_stack; | ||||||
|  |  | ||||||
| 	if ( self->Parent ) | 	if ( self->Parent ) | ||||||
| 		append_fmt( result, "\n\tParent       : %S %S", type_str(self->Parent), self->Name ? self->Name : "" ); | 		string_append_fmt( result, "\n\tParent       : %S %S", type_str(self->Parent), self->Name ? self->Name : "" ); | ||||||
| 	else | 	else | ||||||
| 		append_fmt( result, "\n\tParent       : %S", "Null" ); | 		string_append_fmt( result, "\n\tParent       : %S", "Null" ); | ||||||
|  |  | ||||||
| 	append_fmt( result, "\n\tName         : %S", self->Name ? self->Name : "Null" ); | 	string_append_fmt( result, "\n\tName         : %S", self->Name ? self->Name : "Null" ); | ||||||
| 	append_fmt( result, "\n\tType         : %S", type_str(self) ); | 	string_append_fmt( result, "\n\tType         : %S", type_str(self) ); | ||||||
| 	append_fmt( result, "\n\tModule Flags : %S", to_str( self->ModuleFlags ) ); | 	string_append_fmt( result, "\n\tModule Flags : %S", to_str( self->ModuleFlags ) ); | ||||||
|  |  | ||||||
| 	switch ( self->Type ) | 	switch ( self->Type ) | ||||||
| 	{ | 	{ | ||||||
| @@ -30,9 +30,9 @@ char const* debug_str(Code self) | |||||||
| 		case CT_Access_Protected: | 		case CT_Access_Protected: | ||||||
| 		case CT_Access_Public: | 		case CT_Access_Public: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Untyped: | 		case CT_Untyped: | ||||||
| @@ -48,74 +48,74 @@ char const* debug_str(Code self) | |||||||
| 		case CT_Preprocess_IfDef: | 		case CT_Preprocess_IfDef: | ||||||
| 		case CT_Preprocess_IfNotDef: | 		case CT_Preprocess_IfNotDef: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tContent: %S", self->Content ); | 			string_append_fmt( result, "\n\tContent: %S", self->Content ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Class: | 		case CT_Class: | ||||||
| 		case CT_Struct: | 		case CT_Struct: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt  ? self->InlineCmt->Content     : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt  ? self->InlineCmt->Content     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes  : %S", self->Attributes ? to_string(self->Attributes)  : "Null" ); | 			string_append_fmt( result, "\n\tAttributes  : %S", self->Attributes ? to_string(self->Attributes)  : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParentAccess: %s", self->ParentType ? to_str( self->ParentAccess ) : "No Parent" ); | 			string_append_fmt( result, "\n\tParentAccess: %s", self->ParentType ? to_str( self->ParentAccess ) : "No Parent" ); | ||||||
| 			append_fmt( result, "\n\tParentType  : %s", self->ParentType ? type_str(self->ParentType)   : "Null" ); | 			string_append_fmt( result, "\n\tParentType  : %s", self->ParentType ? type_str(self->ParentType)   : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody        : %S", self->Body       ? debug_str(self->Body)        : "Null" ); | 			string_append_fmt( result, "\n\tBody        : %S", self->Body       ? debug_str(self->Body)        : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Class_Fwd: | 		case CT_Class_Fwd: | ||||||
| 		case CT_Struct_Fwd: | 		case CT_Struct_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt  ? self->InlineCmt->Content     : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt  ? self->InlineCmt->Content     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes  : %S", self->Attributes ? to_string(self->Attributes)  : "Null" ); | 			string_append_fmt( result, "\n\tAttributes  : %S", self->Attributes ? to_string(self->Attributes)  : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParentAccess: %s", self->ParentType ? to_str( self->ParentAccess ) : "No Parent" ); | 			string_append_fmt( result, "\n\tParentAccess: %s", self->ParentType ? to_str( self->ParentAccess ) : "No Parent" ); | ||||||
| 			append_fmt( result, "\n\tParentType  : %s", self->ParentType ? type_str(self->ParentType)   : "Null" ); | 			string_append_fmt( result, "\n\tParentType  : %s", self->ParentType ? type_str(self->ParentType)   : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Constructor: | 		case CT_Constructor: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | 			string_append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | ||||||
| 			append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? to_string(self->InitializerList) : "Null" ); | 			string_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? to_string(self->InitializerList) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams         : %S", self->Params          ? to_string(self->Params)          : "Null" ); | 			string_append_fmt( result, "\n\tParams         : %S", self->Params          ? to_string(self->Params)          : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody           : %S", self->Body            ? debug_str(self->Body)            : "Null" ); | 			string_append_fmt( result, "\n\tBody           : %S", self->Body            ? debug_str(self->Body)            : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Constructor_Fwd: | 		case CT_Constructor_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | 			string_append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | ||||||
| 			append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? to_string(self->InitializerList) : "Null" ); | 			string_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? to_string(self->InitializerList) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams         : %S", self->Params          ? to_string(self->Params)          : "Null" ); | 			string_append_fmt( result, "\n\tParams         : %S", self->Params          ? to_string(self->Params)          : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Destructor: | 		case CT_Destructor: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt      : %S", self->InlineCmt       ? self->InlineCmt->Content         : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | 			string_append_fmt( result, "\n\tSpecs          : %S", self->Specs           ? to_string(self->Specs)           : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody           : %S", self->Body            ? debug_str(self->Body)            : "Null" ); | 			string_append_fmt( result, "\n\tBody           : %S", self->Body            ? debug_str(self->Body)            : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Destructor_Fwd: | 		case CT_Destructor_Fwd: | ||||||
| @@ -124,208 +124,208 @@ char const* debug_str(Code self) | |||||||
| 		case CT_Enum: | 		case CT_Enum: | ||||||
| 		case CT_Enum_Class: | 		case CT_Enum_Class: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt       : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt       : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes      : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | 			string_append_fmt( result, "\n\tAttributes      : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | 			string_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody            : %S", self->Body           ? debug_str(self->Body)           : "Null" ); | 			string_append_fmt( result, "\n\tBody            : %S", self->Body           ? debug_str(self->Body)           : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Enum_Fwd: | 		case CT_Enum_Fwd: | ||||||
| 		case CT_Enum_Class_Fwd: | 		case CT_Enum_Class_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt       : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt       : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes      : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | 			string_append_fmt( result, "\n\tAttributes      : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | 			string_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Extern_Linkage: | 		case CT_Extern_Linkage: | ||||||
| 		case CT_Namespace: | 		case CT_Namespace: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tBody: %S", self->Body ? debug_str(self->Body) : "Null" ); | 			string_append_fmt( result, "\n\tBody: %S", self->Body ? debug_str(self->Body) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Friend: | 		case CT_Friend: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt  : %S", self->InlineCmt   ? self->InlineCmt->Content     : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt  : %S", self->InlineCmt   ? self->InlineCmt->Content     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? to_string(self->Declaration) : "Null" ); | 			string_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? to_string(self->Declaration) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Function: | 		case CT_Function: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | 			string_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | 			string_append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | 			string_append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Function_Fwd: | 		case CT_Function_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | 			string_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | 			string_append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Module: | 		case CT_Module: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Operator: | 		case CT_Operator: | ||||||
| 		case CT_Operator_Member: | 		case CT_Operator_Member: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | 			string_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | 			string_append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | 			string_append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | ||||||
| 			append_fmt( result, "\n\tOp        : %S", to_str( self->Op ) ); | 			string_append_fmt( result, "\n\tOp        : %S", to_str( self->Op ) ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Operator_Fwd: | 		case CT_Operator_Fwd: | ||||||
| 		case CT_Operator_Member_Fwd: | 		case CT_Operator_Member_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content    : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | 			string_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | 			string_append_fmt( result, "\n\tParams    : %S", self->Params     ? to_string(self->Params)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tOp        : %S", to_str( self->Op ) ); | 			string_append_fmt( result, "\n\tOp        : %S", to_str( self->Op ) ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Operator_Cast: | 		case CT_Operator_Cast: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content   : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content   : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)     : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tValueType : %S", self->ValueType  ? to_string(self->ValueType) : "Null" ); | 			string_append_fmt( result, "\n\tValueType : %S", self->ValueType  ? to_string(self->ValueType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)      : "Null" ); | 			string_append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)      : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Operator_Cast_Fwd: | 		case CT_Operator_Cast_Fwd: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content   : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt  ? self->InlineCmt->Content   : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)     : "Null" ); | 			string_append_fmt( result, "\n\tSpecs     : %S", self->Specs      ? to_string(self->Specs)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tValueType : %S", self->ValueType  ? to_string(self->ValueType) : "Null" ); | 			string_append_fmt( result, "\n\tValueType : %S", self->ValueType  ? to_string(self->ValueType) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Parameters: | 		case CT_Parameters: | ||||||
| 			append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); | 			string_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); | ||||||
| 			append_fmt( result, "\n\tLast      : %S", self->Last->Name ); | 			string_append_fmt( result, "\n\tLast      : %S", self->Last->Name ); | ||||||
| 			append_fmt( result, "\n\tNext      : %S", self->Next->Name ); | 			string_append_fmt( result, "\n\tNext      : %S", self->Next->Name ); | ||||||
| 			append_fmt( result, "\n\tValueType : %S", self->ValueType ? to_string(self->ValueType) : "Null" ); | 			string_append_fmt( result, "\n\tValueType : %S", self->ValueType ? to_string(self->ValueType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tValue     : %S", self->Value     ? to_string(self->Value)     : "Null" ); | 			string_append_fmt( result, "\n\tValue     : %S", self->Value     ? to_string(self->Value)     : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Specifiers: | 		case CT_Specifiers: | ||||||
| 		{ | 		{ | ||||||
| 			append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); | 			string_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); | ||||||
| 			GEN_NS append( result, "\n\tArrSpecs: " ); | 			string_append_strc( result, txt("\n\tArrSpecs: ") ); | ||||||
|  |  | ||||||
| 			s32 idx  = 0; | 			s32 idx  = 0; | ||||||
| 			s32 left = self->NumEntries; | 			s32 left = self->NumEntries; | ||||||
| 			while ( left-- ) | 			while ( left-- ) | ||||||
| 			{ | 			{ | ||||||
| 				StrC spec = to_str( self->ArrSpecs[idx] ); | 				StrC spec = to_str( self->ArrSpecs[idx] ); | ||||||
| 				append_fmt( result, "%.*s, ", spec.Len, spec.Ptr ); | 				string_append_fmt( result, "%.*s, ", spec.Len, spec.Ptr ); | ||||||
| 				idx++; | 				idx++; | ||||||
| 			} | 			} | ||||||
| 			append_fmt( result, "\n\tNextSpecs: %S", self->NextSpecs ? debug_str(self->NextSpecs) : "Null" ); | 			string_append_fmt( result, "\n\tNextSpecs: %S", self->NextSpecs ? debug_str(self->NextSpecs) : "Null" ); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Template: | 		case CT_Template: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tParams     : %S", self->Params      ? to_string(self->Params)      : "Null" ); | 			string_append_fmt( result, "\n\tParams     : %S", self->Params      ? to_string(self->Params)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? to_string(self->Declaration) : "Null" ); | 			string_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? to_string(self->Declaration) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Typedef: | 		case CT_Typedef: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt     : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt     : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | 			string_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Typename: | 		case CT_Typename: | ||||||
| 			append_fmt( result, "\n\tAttributes     : %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes     : %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs          : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | 			string_append_fmt( result, "\n\tSpecs          : %S", self->Specs      ? to_string(self->Specs)      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tReturnType     : %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | 			string_append_fmt( result, "\n\tReturnType     : %S", self->ReturnType ? to_string(self->ReturnType) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tParams         : %S", self->Params     ? to_string(self->Params)     : "Null" ); | 			string_append_fmt( result, "\n\tParams         : %S", self->Params     ? to_string(self->Params)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tArrExpr        : %S", self->ArrExpr    ? to_string(self->ArrExpr)    : "Null" ); | 			string_append_fmt( result, "\n\tArrExpr        : %S", self->ArrExpr    ? to_string(self->ArrExpr)    : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Union: | 		case CT_Union: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | 			string_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? to_string(self->Attributes) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | 			string_append_fmt( result, "\n\tBody      : %S", self->Body       ? debug_str(self->Body)       : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Using: | 		case CT_Using: | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt     : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt     : %S", self->InlineCmt      ? self->InlineCmt->Content        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes    : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | 			string_append_fmt( result, "\n\tAttributes    : %S", self->Attributes     ? to_string(self->Attributes)     : "Null" ); | ||||||
| 			append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | 			string_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? to_string(self->UnderlyingType) : "Null" ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Variable: | 		case CT_Variable: | ||||||
| @@ -333,25 +333,25 @@ char const* debug_str(Code self) | |||||||
| 			if ( self->Parent && self->Parent->Type == CT_Variable ) | 			if ( self->Parent && self->Parent->Type == CT_Variable ) | ||||||
| 			{ | 			{ | ||||||
| 				// Its a NextVar | 				// Its a NextVar | ||||||
| 				append_fmt( result, "\n\tSpecs       : %S", self->Specs        ? to_string(self->Specs)        : "Null" ); | 				string_append_fmt( result, "\n\tSpecs       : %S", self->Specs        ? to_string(self->Specs)        : "Null" ); | ||||||
| 				append_fmt( result, "\n\tValue       : %S", self->Value        ? to_string(self->Value)        : "Null" ); | 				string_append_fmt( result, "\n\tValue       : %S", self->Value        ? to_string(self->Value)        : "Null" ); | ||||||
| 				append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? to_string(self->BitfieldSize) : "Null" ); | 				string_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? to_string(self->BitfieldSize) : "Null" ); | ||||||
| 				append_fmt( result, "\n\tNextVar     : %S", self->NextVar      ? debug_str(self->NextVar)      : "Null" ); | 				string_append_fmt( result, "\n\tNextVar     : %S", self->NextVar      ? debug_str(self->NextVar)      : "Null" ); | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if ( self->Prev ) | 			if ( self->Prev ) | ||||||
| 				append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tPrev: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
| 			if ( self->Next ) | 			if ( self->Next ) | ||||||
| 				append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | 				string_append_fmt( result, "\n\tNext: %S %S", type_str(self->Prev), self->Prev->Name ? self->Prev->Name : "Null" ); | ||||||
|  |  | ||||||
| 			append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt    ? self->InlineCmt->Content      : "Null" ); | 			string_append_fmt( result, "\n\tInlineCmt   : %S", self->InlineCmt    ? self->InlineCmt->Content      : "Null" ); | ||||||
| 			append_fmt( result, "\n\tAttributes  : %S", self->Attributes   ? to_string(self->Attributes)   : "Null" ); | 			string_append_fmt( result, "\n\tAttributes  : %S", self->Attributes   ? to_string(self->Attributes)   : "Null" ); | ||||||
| 			append_fmt( result, "\n\tSpecs       : %S", self->Specs        ? to_string(self->Specs)        : "Null" ); | 			string_append_fmt( result, "\n\tSpecs       : %S", self->Specs        ? to_string(self->Specs)        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tValueType   : %S", self->ValueType    ? to_string(self->ValueType)    : "Null" ); | 			string_append_fmt( result, "\n\tValueType   : %S", self->ValueType    ? to_string(self->ValueType)    : "Null" ); | ||||||
| 			append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? to_string(self->BitfieldSize) : "Null" ); | 			string_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? to_string(self->BitfieldSize) : "Null" ); | ||||||
| 			append_fmt( result, "\n\tValue       : %S", self->Value        ? to_string(self->Value)        : "Null" ); | 			string_append_fmt( result, "\n\tValue       : %S", self->Value        ? to_string(self->Value)        : "Null" ); | ||||||
| 			append_fmt( result, "\n\tNextVar     : %S", self->NextVar      ? debug_str(self->NextVar)      : "Null" ); | 			string_append_fmt( result, "\n\tNextVar     : %S", self->NextVar      ? debug_str(self->NextVar)      : "Null" ); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -370,7 +370,7 @@ Code duplicate(Code self) | |||||||
|  |  | ||||||
| String to_string(Code self) | String to_string(Code self) | ||||||
| { | { | ||||||
| 	String result = string_make( GlobalAllocator, "" ); | 	String result = string_make_strc( GlobalAllocator, txt("") ); | ||||||
| 	GEN_NS to_string( self, & result ); | 	GEN_NS to_string( self, & result ); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| @@ -387,25 +387,25 @@ void to_string( Code self, 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 | ||||||
| 			append_fmt( result, "Invalid Code!" ); | 			string_append_fmt( result, "Invalid Code!" ); | ||||||
| 		#endif | 		#endif | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_NewLine: | 		case CT_NewLine: | ||||||
| 			append( result,"\n"); | 			string_append_strc( result, txt("\n")); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Untyped: | 		case CT_Untyped: | ||||||
| 		case CT_Execution: | 		case CT_Execution: | ||||||
| 		case CT_Comment: | 		case CT_Comment: | ||||||
| 		case CT_PlatformAttributes: | 		case CT_PlatformAttributes: | ||||||
| 			append( result, self->Content ); | 			string_append_strc( result, self->Content ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Access_Private: | 		case CT_Access_Private: | ||||||
| 		case CT_Access_Protected: | 		case CT_Access_Protected: | ||||||
| 		case CT_Access_Public: | 		case CT_Access_Public: | ||||||
| 			append( result, self->Name ); | 			string_append_strc( result, self->Name ); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
| 		case CT_Class: | 		case CT_Class: | ||||||
| @@ -654,8 +654,8 @@ bool is_equal( Code self, Code 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"                                         \ | ||||||
| 			, visualize_whitespace(self->content, GlobalAllocator)        \ | 			, strc_visualize_whitespace(self->content, GlobalAllocator)    \ | ||||||
| 			, visualize_whitespace(other->content, GlobalAllocator)       \ | 			, strc_visualize_whitespace(other->content, GlobalAllocator)   \ | ||||||
| 		);                                                                 \ | 		);                                                                 \ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -159,16 +159,16 @@ extern CodeTypename t_typename; | |||||||
| // Used by the lexer to persistently treat all these identifiers as preprocessor defines. | // Used by the lexer to persistently treat all these identifiers as preprocessor defines. | ||||||
| // Populate with strings via gen::get_cached_string. | // Populate with strings via gen::get_cached_string. | ||||||
| // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. | // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. | ||||||
| extern Array< StringCached > PreprocessorDefines; | extern Array(StringCached) PreprocessorDefines; | ||||||
|  |  | ||||||
| #ifdef GEN_EXPOSE_BACKEND | #ifdef GEN_EXPOSE_BACKEND | ||||||
|  |  | ||||||
| 	// Global allocator used for data with process lifetime. | 	// Global allocator used for data with process lifetime. | ||||||
| 	extern AllocatorInfo  GlobalAllocator; | 	extern AllocatorInfo  GlobalAllocator; | ||||||
| 	extern Array< Arena > Global_AllocatorBuckets; | 	extern Array(Arena) Global_AllocatorBuckets; | ||||||
|  |  | ||||||
| 	extern Array< Pool >  CodePools; | 	extern Array(Pool)  CodePools; | ||||||
| 	extern Array< Arena > StringArenas; | 	extern Array(Arena) StringArenas; | ||||||
|  |  | ||||||
| 	extern StringTable StringCache; | 	extern StringTable StringCache; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -134,7 +134,7 @@ Code begin( CodeBody body) { | |||||||
| } | } | ||||||
| inline | inline | ||||||
| Code end(CodeBody body ){ | Code end(CodeBody body ){ | ||||||
| 	return { nullptr }; | 	return { rcast(AST*, body.ast)->Back->Next }; | ||||||
| } | } | ||||||
| #pragma endregion CodeBody | #pragma endregion CodeBody | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ internal void deinit(); | |||||||
| internal | internal | ||||||
| void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize 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 = back(& Global_AllocatorBuckets); | 	Arena* last = array_back(& Global_AllocatorBuckets); | ||||||
|  |  | ||||||
| 	switch ( type ) | 	switch ( type ) | ||||||
| 	{ | 	{ | ||||||
| @@ -24,13 +24,13 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 				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 ( ! append( & Global_AllocatorBuckets, bucket ) ) | 				if ( ! array_append( & Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = back(& Global_AllocatorBuckets); | 				last = array_back(& Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return alloc_align( allocator_info(last), size, alignment ); | 			return alloc_align( arena_allocator_info(last), size, alignment ); | ||||||
| 		} | 		} | ||||||
| 		case EAllocation_FREE: | 		case EAllocation_FREE: | ||||||
| 		{ | 		{ | ||||||
| @@ -51,10 +51,10 @@ void* Global_Allocator_Proc( void* allocator_data, AllocType type, ssize size, s | |||||||
| 				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 ( ! append( & Global_AllocatorBuckets, bucket ) ) | 				if ( ! array_append( & Global_AllocatorBuckets, bucket ) ) | ||||||
| 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | 					GEN_FATAL( "Failed to append bucket to Global_AllocatorBuckets"); | ||||||
|  |  | ||||||
| 				last = back(& Global_AllocatorBuckets); | 				last = array_back(& Global_AllocatorBuckets); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			void* result = alloc_align( last->Backing, size, alignment ); | 			void* result = alloc_align( last->Backing, size, alignment ); | ||||||
| @@ -249,7 +249,7 @@ void init() | |||||||
| 		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"); | ||||||
|  |  | ||||||
| 		append( & Global_AllocatorBuckets, bucket ); | 		array_append( & Global_AllocatorBuckets, bucket ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the arrays | 	// Setup the arrays | ||||||
| @@ -272,7 +272,7 @@ void init() | |||||||
| 		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" ); | ||||||
|  |  | ||||||
| 		append( & CodePools, code_pool ); | 		array_append( & CodePools, code_pool ); | ||||||
|  |  | ||||||
| 		LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | 		LexArena = arena_init_from_allocator( Allocator_Lexer, LexAllocator_Size ); | ||||||
|  |  | ||||||
| @@ -281,7 +281,7 @@ void init() | |||||||
| 		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" ); | ||||||
|  |  | ||||||
| 		append( & StringArenas, string_arena ); | 		array_append( & StringArenas, string_arena ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Setup the hash tables | 	// Setup the hash tables | ||||||
| @@ -302,62 +302,62 @@ void init() | |||||||
| void deinit() | void deinit() | ||||||
| { | { | ||||||
| 	usize index = 0; | 	usize index = 0; | ||||||
| 	usize left  = num(CodePools); | 	usize left  = array_num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		free(code_pool); | 		pool_free(code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = num(StringArenas); | 	left  = array_num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| 		free(string_arena); | 		arena_free(string_arena); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	destroy(& StringCache); | 	destroy(& StringCache); | ||||||
|  |  | ||||||
| 	free( & CodePools); | 	array_free( & CodePools); | ||||||
| 	free( & StringArenas); | 	array_free( & StringArenas); | ||||||
|  |  | ||||||
| 	free(& LexArena); | 	arena_free(& LexArena); | ||||||
|  |  | ||||||
| 	free(& PreprocessorDefines); | 	array_free(& PreprocessorDefines); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = num(Global_AllocatorBuckets); | 	left  = array_num(Global_AllocatorBuckets); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | 		Arena* bucket = & Global_AllocatorBuckets[ index ]; | ||||||
| 		free(bucket); | 		arena_free(bucket); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	free(Global_AllocatorBuckets); | 	array_free(& Global_AllocatorBuckets); | ||||||
| 	parser::deinit(); | 	parser::deinit(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void reset() | void reset() | ||||||
| { | { | ||||||
| 	s32 index = 0; | 	s32 index = 0; | ||||||
| 	s32 left  = num(CodePools); | 	s32 left  = array_num(CodePools); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Pool* code_pool = & CodePools[index]; | 		Pool* code_pool = & CodePools[index]; | ||||||
| 		clear(* code_pool); | 		pool_clear(code_pool); | ||||||
| 		index++; | 		index++; | ||||||
| 	} | 	} | ||||||
| 	while ( left--, left ); | 	while ( left--, left ); | ||||||
|  |  | ||||||
| 	index = 0; | 	index = 0; | ||||||
| 	left  = num(StringArenas); | 	left  = array_num(StringArenas); | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		Arena* string_arena = & StringArenas[index]; | 		Arena* string_arena = & StringArenas[index]; | ||||||
| @@ -373,7 +373,7 @@ void reset() | |||||||
|  |  | ||||||
| AllocatorInfo get_string_allocator( s32 str_length ) | AllocatorInfo get_string_allocator( s32 str_length ) | ||||||
| { | { | ||||||
| 	Arena* last = back(& StringArenas); | 	Arena* last = array_back(& StringArenas); | ||||||
|  |  | ||||||
| 	usize size_req = str_length + sizeof(StringHeader) + sizeof(char*); | 	usize size_req = str_length + sizeof(StringHeader) + sizeof(char*); | ||||||
|  |  | ||||||
| @@ -381,13 +381,13 @@ AllocatorInfo get_string_allocator( s32 str_length ) | |||||||
| 	{ | 	{ | ||||||
| 		Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | 		Arena new_arena = arena_init_from_allocator( Allocator_StringArena, SizePer_StringArena ); | ||||||
|  |  | ||||||
| 		if ( ! append( & StringArenas, new_arena ) ) | 		if ( ! array_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 = back(& StringArenas); | 		last = array_back(& StringArenas); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return allocator_info(last); | 	return arena_allocator_info(last); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Will either make or retrive a code string. | // Will either make or retrive a code string. | ||||||
| @@ -402,16 +402,16 @@ StringCached get_cached_string( StrC str ) | |||||||
| 			return * result; | 			return * result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String result = string_make( get_string_allocator( str.Len ), str ); | 	String result = string_make_strc( get_string_allocator( str.Len ), str ); | ||||||
| 	set(& StringCache, key, { length(result), result } ); | 	set(& StringCache, key, { str.Len, result } ); | ||||||
|  |  | ||||||
| 	return { length(result), result }; | 	return { str.Len, result }; | ||||||
| } | } | ||||||
|  |  | ||||||
| // 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 = back( & CodePools); | 	Pool* allocator = array_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) ); | ||||||
| @@ -419,13 +419,13 @@ Code make_code() | |||||||
| 		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 ( ! append( & CodePools, code_pool ) ) | 		if ( ! array_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 = back( & CodePools); | 		allocator = array_back( & CodePools); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Code result { rcast( AST*, alloc( allocator_info(allocator), sizeof(AST) )) }; | 	Code result { rcast( AST*, alloc( pool_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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 		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_init(StrC, allocator_info(& tok_map_arena) ); | 		tok_map       = hashtable_init(StrC, arena_allocator_info(& tok_map_arena) ); | ||||||
|  |  | ||||||
| 		s32 left = num_tokens - 1; | 		s32 left = num_tokens - 1; | ||||||
|  |  | ||||||
| @@ -94,7 +94,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va ) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	clear(tok_map); | 	clear(tok_map); | ||||||
| 	free(& tok_map_arena); | 	arena_free(& tok_map_arena); | ||||||
|  |  | ||||||
| 	ssize result = buf_size - remaining; | 	ssize result = buf_size - remaining; | ||||||
|  |  | ||||||
| @@ -142,7 +142,7 @@ Code untyped_fmt( char const* fmt, ...) | |||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Name    = get_cached_string( { str_len(fmt, MaxNameLength), fmt } ); | 	result->Name    = get_cached_string( { str_len_capped(fmt, MaxNameLength), fmt } ); | ||||||
| 	result->Type    = CT_Untyped; | 	result->Type    = CT_Untyped; | ||||||
| 	result->Content = get_cached_string( { length, buf } ); | 	result->Content = get_cached_string( { length, buf } ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -472,23 +472,23 @@ CodeComment def_comment( StrC content ) | |||||||
| 		length++; | 		length++; | ||||||
|  |  | ||||||
| 		str_copy( line, scanner, length ); | 		str_copy( line, scanner, length ); | ||||||
| 		append_fmt(& cmt_formatted, "//%.*s", length, line ); | 		string_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 ( * back(& cmt_formatted) != '\n' ) | 	if ( * string_back(cmt_formatted) != '\n' ) | ||||||
| 		append( & cmt_formatted, "\n" ); | 		string_append_strc( & cmt_formatted, txt("\n") ); | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Type    = CT_Comment; | 	result->Type    = CT_Comment; | ||||||
| 	result->Name    = get_cached_string( { length(cmt_formatted), cmt_formatted } ); | 	result->Name    = get_cached_string( { string_length(cmt_formatted), cmt_formatted } ); | ||||||
| 	result->Content = result->Name; | 	result->Content = result->Name; | ||||||
|  |  | ||||||
| 	free(& cmt_formatted); | 	string_free(& cmt_formatted); | ||||||
|  |  | ||||||
| 	return (CodeComment) result; | 	return (CodeComment) result; | ||||||
| } | } | ||||||
| @@ -907,14 +907,14 @@ CodeInclude def_include( StrC path, Opts_def_include p ) | |||||||
| 		return InvalidCode; | 		return InvalidCode; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	StrC content = p.foreign ? | 	String content = p.foreign ? | ||||||
| 			to_str( str_fmt_buf( "<%.*s>", path.Len, path.Ptr )) | 			string_fmt_buf( GlobalAllocator, "<%.*s>",   path.Len, path.Ptr ) | ||||||
| 		:	to_str( str_fmt_buf( "\"%.*s\"", path.Len, path.Ptr )); | 		:	string_fmt_buf( GlobalAllocator, "\"%.*s\"", path.Len, path.Ptr ); | ||||||
|  |  | ||||||
| 	Code | 	Code | ||||||
| 	result          = make_code(); | 	result          = make_code(); | ||||||
| 	result->Type    = CT_Preprocess_Include; | 	result->Type    = CT_Preprocess_Include; | ||||||
| 	result->Name    = get_cached_string( content ); | 	result->Name    = get_cached_string( string_to_strc(content) ); | ||||||
| 	result->Content = result->Name; | 	result->Content = result->Name; | ||||||
|  |  | ||||||
| 	return (CodeInclude) result; | 	return (CodeInclude) result; | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ String to_string(Token tok) | |||||||
|  |  | ||||||
| 	StrC type_str = to_str( tok.Type ); | 	StrC type_str = to_str( tok.Type ); | ||||||
|  |  | ||||||
| 	append_fmt( & result, "Line: %d Column: %d, Type: %.*s Content: %.*s" | 	string_append_fmt( & result, "Line: %d Column: %d, Type: %.*s Content: %.*s" | ||||||
| 		, tok.Line, tok.Column | 		, tok.Line, tok.Column | ||||||
| 		, type_str.Len, type_str.Ptr | 		, type_str.Len, type_str.Ptr | ||||||
| 		, tok.Length, tok.Text | 		, tok.Length, tok.Text | ||||||
| @@ -221,7 +221,7 @@ forceinline | |||||||
| s32 lex_preprocessor_directive( LexContext* ctx ) | s32 lex_preprocessor_directive( LexContext* ctx ) | ||||||
| { | { | ||||||
| 	char const* hash = ctx->scanner; | 	char const* hash = ctx->scanner; | ||||||
| 	append( & Tokens, { hash, 1, Tok_Preprocess_Hash, ctx->line, ctx->column, TF_Preprocess } ); | 	array_append( & Tokens, { hash, 1, Tok_Preprocess_Hash, ctx->line, ctx->column, TF_Preprocess } ); | ||||||
|  |  | ||||||
| 	move_forward(); | 	move_forward(); | ||||||
| 	SkipWhitespace(); | 	SkipWhitespace(); | ||||||
| @@ -297,14 +297,14 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | |||||||
|  |  | ||||||
| 		ctx->token.Length = ctx->token.Length + ctx->token.Text - hash; | 		ctx->token.Length = ctx->token.Length + ctx->token.Text - hash; | ||||||
| 		ctx->token.Text   = hash; | 		ctx->token.Text   = hash; | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		return Lex_Continue; // Skip found token, its all handled here. | 		return Lex_Continue; // Skip found token, its all handled here. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( ctx->token.Type == Tok_Preprocess_Else || ctx->token.Type == Tok_Preprocess_EndIf ) | 	if ( ctx->token.Type == Tok_Preprocess_Else || ctx->token.Type == Tok_Preprocess_EndIf ) | ||||||
| 	{ | 	{ | ||||||
| 		ctx->token.Flags |= TF_Preprocess_Cond; | 		ctx->token.Flags |= TF_Preprocess_Cond; | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		end_line(); | 		end_line(); | ||||||
| 		return Lex_Continue; | 		return Lex_Continue; | ||||||
| 	} | 	} | ||||||
| @@ -313,7 +313,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | |||||||
| 		ctx->token.Flags |= TF_Preprocess_Cond; | 		ctx->token.Flags |= TF_Preprocess_Cond; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	append( & Tokens, ctx->token ); | 	array_append( & Tokens, ctx->token ); | ||||||
|  |  | ||||||
| 	SkipWhitespace(); | 	SkipWhitespace(); | ||||||
|  |  | ||||||
| @@ -337,7 +337,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | |||||||
| 			name.Length++; | 			name.Length++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		append( & Tokens, name ); | 		array_append( & Tokens, name ); | ||||||
|  |  | ||||||
| 		u64 key = crc32( name.Text, name.Length ); | 		u64 key = crc32( name.Text, name.Length ); | ||||||
| 		set(& ctx->defines, key, to_str(name) ); | 		set(& ctx->defines, key, to_str(name) ); | ||||||
| @@ -383,7 +383,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | |||||||
| 			move_forward(); | 			move_forward(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		append( & Tokens, preprocess_content ); | 		array_append( & Tokens, preprocess_content ); | ||||||
| 		return Lex_Continue; // Skip found token, its all handled here. | 		return Lex_Continue; // Skip found token, its all handled here. | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -445,7 +445,7 @@ s32 lex_preprocessor_directive( LexContext* ctx ) | |||||||
| 		preprocess_content.Length++; | 		preprocess_content.Length++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	append( & Tokens, preprocess_content ); | 	array_append( & Tokens, preprocess_content ); | ||||||
| 	return Lex_Continue; // Skip found token, its all handled here. | 	return Lex_Continue; // Skip found token, its all handled here. | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -454,7 +454,7 @@ void lex_found_token( LexContext* ctx ) | |||||||
| { | { | ||||||
| 	if ( ctx->token.Type != Tok_Invalid ) | 	if ( ctx->token.Type != Tok_Invalid ) | ||||||
| 	{ | 	{ | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -481,7 +481,7 @@ void lex_found_token( LexContext* ctx ) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ctx->token.Type = type; | 		ctx->token.Type = type; | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -491,7 +491,7 @@ void lex_found_token( LexContext* ctx ) | |||||||
| 	{ | 	{ | ||||||
| 		ctx->token.Type   = type; | 		ctx->token.Type   = type; | ||||||
| 		ctx->token.Flags |= TF_Specifier; | 		ctx->token.Flags |= TF_Specifier; | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -499,7 +499,7 @@ void lex_found_token( LexContext* ctx ) | |||||||
| 	if ( type != Tok_Invalid ) | 	if ( type != Tok_Invalid ) | ||||||
| 	{ | 	{ | ||||||
| 		ctx->token.Type = type; | 		ctx->token.Type = type; | ||||||
| 		append( & Tokens, ctx->token ); | 		array_append( & Tokens, ctx->token ); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -551,7 +551,7 @@ void lex_found_token( LexContext* ctx ) | |||||||
| 		ctx->token.Type = Tok_Identifier; | 		ctx->token.Type = Tok_Identifier; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	append( & Tokens, ctx->token ); | 	array_append( & Tokens, ctx->token ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -578,16 +578,16 @@ TokArray lex( StrC content ) | |||||||
| 		return { {}, 0 }; | 		return { {}, 0 }; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	foreach( StringCached*, entry, PreprocessorDefines ) | 	for ( StringCached* entry = array_begin(PreprocessorDefines); entry != array_end(PreprocessorDefines); entry = array_next(PreprocessorDefines, entry)) | ||||||
| 	{ | 	{ | ||||||
| 		s32         length  = 0; | 		s32         length  = 0; | ||||||
| 		char const* scanner = * entry; | 		char const* entry_scanner = * entry; | ||||||
| 		while ( entry->Len > length && (char_is_alphanumeric( *scanner ) || *scanner == '_') ) | 		while ( entry->Len > length && (char_is_alphanumeric( *entry_scanner ) || *entry_scanner == '_') ) | ||||||
| 		{ | 		{ | ||||||
| 			c.scanner++; | 			entry_scanner++; | ||||||
| 			length ++; | 			length ++; | ||||||
| 		} | 		} | ||||||
| 		if ( c.scanner[0] == '(' ) | 		if ( entry_scanner[0] == '(' ) | ||||||
| 		{ | 		{ | ||||||
| 			length++; | 			length++; | ||||||
| 		} | 		} | ||||||
| @@ -596,7 +596,7 @@ TokArray lex( StrC content ) | |||||||
| 		set(& c.defines, key, (StrC) * entry ); | 		set(& c.defines, key, (StrC) * entry ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	clear(Tokens); | 	array_clear(Tokens); | ||||||
|  |  | ||||||
| 	while (c.left ) | 	while (c.left ) | ||||||
| 	{ | 	{ | ||||||
| @@ -626,7 +626,7 @@ TokArray lex( StrC content ) | |||||||
| 				c.token.Type = Tok_NewLine; | 				c.token.Type = Tok_NewLine; | ||||||
| 				c.token.Length++; | 				c.token.Length++; | ||||||
|  |  | ||||||
| 				append( & Tokens, c.token ); | 				array_append( & Tokens, c.token ); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -1095,7 +1095,7 @@ TokArray lex( StrC content ) | |||||||
| 							move_forward(); | 							move_forward(); | ||||||
| 							c.token.Length++; | 							c.token.Length++; | ||||||
| 						} | 						} | ||||||
| 						append( & Tokens, c.token ); | 						array_append( & Tokens, c.token ); | ||||||
| 						continue; | 						continue; | ||||||
| 					} | 					} | ||||||
| 					else if ( current == '*' ) | 					else if ( current == '*' ) | ||||||
| @@ -1131,7 +1131,7 @@ TokArray lex( StrC content ) | |||||||
| 							move_forward(); | 							move_forward(); | ||||||
| 							c.token.Length++; | 							c.token.Length++; | ||||||
| 						} | 						} | ||||||
| 						append( & Tokens, c.token ); | 						array_append( & Tokens, c.token ); | ||||||
| 						// end_line(); | 						// end_line(); | ||||||
| 						continue; | 						continue; | ||||||
| 					} | 					} | ||||||
| @@ -1224,9 +1224,9 @@ TokArray lex( StrC content ) | |||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			s32 start = max( 0, num(Tokens) - 100 ); | 			s32 start = max( 0, array_num(Tokens) - 100 ); | ||||||
| 			log_fmt("\n%d\n", start); | 			log_fmt("\n%d\n", start); | ||||||
| 			for ( s32 idx = start; idx < num(Tokens); idx++ ) | 			for ( s32 idx = start; idx < array_num(Tokens); idx++ ) | ||||||
| 			{ | 			{ | ||||||
| 				log_fmt( "Token %d Type: %s : %.*s\n" | 				log_fmt( "Token %d Type: %s : %.*s\n" | ||||||
| 					, idx | 					, idx | ||||||
| @@ -1249,7 +1249,7 @@ TokArray lex( StrC content ) | |||||||
| 		lex_found_token( ctx ); | 		lex_found_token( ctx ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( num(Tokens) == 0 ) | 	if ( array_num(Tokens) == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "Failed to lex any tokens" ); | 		log_failure( "Failed to lex any tokens" ); | ||||||
| 		return { {}, 0 }; | 		return { {}, 0 }; | ||||||
|   | |||||||
| @@ -50,28 +50,28 @@ String to_string(ParseContext ctx) | |||||||
| 	String result = string_make_reserve( GlobalAllocator, kilobytes(4) ); | 	String result = string_make_reserve( GlobalAllocator, kilobytes(4) ); | ||||||
|  |  | ||||||
| 	Token scope_start = ctx.Scope->Start; | 	Token scope_start = ctx.Scope->Start; | ||||||
| 	Token last_valid  = ctx.Tokens.Idx >= num(ctx.Tokens.Arr) ? ctx.Tokens.Arr[num(ctx.Tokens.Arr) -1] : (* current(& ctx.Tokens, true)); | 	Token last_valid  = ctx.Tokens.Idx >= array_num(ctx.Tokens.Arr) ? ctx.Tokens.Arr[array_num(ctx.Tokens.Arr) -1] : (* current(& ctx.Tokens, true)); | ||||||
|  |  | ||||||
| 	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 <= back( & ctx.Tokens.Arr)->Text && *current != '\n' && length < 74 ) | 	while ( current <= array_back( & ctx.Tokens.Arr)->Text && *current != '\n' && length < 74 ) | ||||||
| 	{ | 	{ | ||||||
| 		current++; | 		current++; | ||||||
| 		length++; | 		length++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String line = string_make( GlobalAllocator, { length, scope_start.Text } ); | 	String line = string_make_strc( GlobalAllocator, { length, scope_start.Text } ); | ||||||
| 	append_fmt( & result, "\tScope    : %s\n", line ); | 	string_append_fmt( & result, "\tScope    : %s\n", line ); | ||||||
| 	free(& line); | 	string_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_strc( GlobalAllocator, { length_from_err, last_valid.Text } ); | ||||||
|  |  | ||||||
| 	if ( length_from_err < 100 ) | 	if ( length_from_err < 100 ) | ||||||
| 		append_fmt(& result, "\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); | 		string_append_fmt(& result, "\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' ); | ||||||
| 	else | 	else | ||||||
| 		append_fmt(& result, "\t(%d, %d)\n", last_valid.Line, last_valid.Column ); | 		string_append_fmt(& result, "\t(%d, %d)\n", last_valid.Line, last_valid.Column ); | ||||||
|  |  | ||||||
| 	StackNode* curr_scope = ctx.Scope; | 	StackNode* curr_scope = ctx.Scope; | ||||||
| 	s32 level = 0; | 	s32 level = 0; | ||||||
| @@ -79,11 +79,11 @@ String to_string(ParseContext ctx) | |||||||
| 	{ | 	{ | ||||||
| 		if ( is_valid(curr_scope->Name) ) | 		if ( is_valid(curr_scope->Name) ) | ||||||
| 		{ | 		{ | ||||||
| 			append_fmt(& result, "\t%d: %s, AST Name: %.*s\n", level, curr_scope->ProcName.Ptr, curr_scope->Name.Length, curr_scope->Name.Text ); | 			string_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 | ||||||
| 		{ | 		{ | ||||||
| 			append_fmt(& result, "\t%d: %s\n", level, curr_scope->ProcName.Ptr ); | 			string_append_fmt(& result, "\t%d: %s\n", level, curr_scope->ProcName.Ptr ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		curr_scope = curr_scope->Prev; | 		curr_scope = curr_scope->Prev; | ||||||
| @@ -97,7 +97,7 @@ global ParseContext Context; | |||||||
|  |  | ||||||
| bool __eat(TokArray* self, TokType type ) | bool __eat(TokArray* self, TokType type ) | ||||||
| { | { | ||||||
| 	if ( num(self->Arr) - self->Idx <= 0 ) | 	if ( array_num(self->Arr) - self->Idx <= 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		log_failure( "No tokens left.\n%s", to_string(Context) ); | 		log_failure( "No tokens left.\n%s", to_string(Context) ); | ||||||
| 		return false; | 		return false; | ||||||
| @@ -136,12 +136,12 @@ bool __eat(TokArray* self, TokType type ) | |||||||
| internal | internal | ||||||
| void init() | void init() | ||||||
| { | { | ||||||
| 	Tokens = array_init_reserve<Token>( allocator_info( & LexArena) | 	Tokens = array_init_reserve(Token, arena_allocator_info( & LexArena) | ||||||
| 		, ( LexAllocator_Size - sizeof( ArrayHeader ) ) / sizeof(Token) | 		, ( LexAllocator_Size - sizeof( ArrayHeader ) ) / sizeof(Token) | ||||||
| 	); | 	); | ||||||
|  |  | ||||||
| 	fixed_arena_init(& defines_map_arena); | 	fixed_arena_init(& defines_map_arena); | ||||||
| 	defines = hashtable_init_reserve<StrC>( allocator_info( & defines_map_arena), 256 ); | 	defines = hashtable_init_reserve(StrC, allocator_info( & defines_map_arena), 256 ); | ||||||
| } | } | ||||||
|  |  | ||||||
| internal | internal | ||||||
| @@ -175,7 +175,7 @@ bool _check_parse_args( StrC def, char const* func_name ) | |||||||
| #	define prevtok        (* previous( Context.Tokens, dont_skip_formatting)) | #	define prevtok        (* previous( Context.Tokens, dont_skip_formatting)) | ||||||
| #	define nexttok		  (* next( Context.Tokens, skip_formatting )) | #	define nexttok		  (* next( Context.Tokens, skip_formatting )) | ||||||
| #	define eat( Type_ )   __eat( & Context.Tokens, Type_ ) | #	define eat( Type_ )   __eat( & Context.Tokens, Type_ ) | ||||||
| #	define left           ( num(Context.Tokens.Arr) - Context.Tokens.Idx ) | #	define left           ( array_num(Context.Tokens.Arr) - Context.Tokens.Idx ) | ||||||
|  |  | ||||||
| #ifdef check | #ifdef check | ||||||
| #define CHECK_WAS_DEFINED | #define CHECK_WAS_DEFINED | ||||||
| @@ -298,7 +298,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if ( tokleft ) | 			if ( tokleft ) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			append( & content, cut_ptr, cut_length ); | 			string_append_c_str_len( & 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 +320,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if ( tokleft ) | 			if ( tokleft ) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			append( & content, cut_ptr, cut_length ); | 			string_append_c_str_len( & content, cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -334,7 +334,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			scanner += 2; | 			scanner += 2; | ||||||
| 			tokleft -= 2; | 			tokleft -= 2; | ||||||
|  |  | ||||||
| 			append( & content,  cut_ptr, cut_length ); | 			string_append_c_str_len( & content,  cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -353,7 +353,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 			if (tokleft) | 			if (tokleft) | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 			append( & content,  cut_ptr, cut_length ); | 			string_append_c_str_len( & content,  cut_ptr, cut_length ); | ||||||
| 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | 			last_cut = sptr( scanner ) - sptr( raw_text.Ptr ); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -362,10 +362,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) | ||||||
| 				append( & content, cut_ptr, cut_length); | 				string_append_c_str_len( & content, cut_ptr, cut_length); | ||||||
|  |  | ||||||
| 			if ( * back( & content ) != ' ' ) | 			if ( * string_back( content ) != ' ' ) | ||||||
| 				append( & content, ' '); | 				string_append_char( & content, ' ' ); | ||||||
|  |  | ||||||
| 			move_fwd(); | 			move_fwd(); | ||||||
| 			last_cut = sptr(scanner) - sptr(raw_text.Ptr); | 			last_cut = sptr(scanner) - sptr(raw_text.Ptr); | ||||||
| @@ -381,17 +381,17 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 				scanner += 2; | 				scanner += 2; | ||||||
| 				tokleft -= 2; | 				tokleft -= 2; | ||||||
|  |  | ||||||
| 				append( & content,  cut_ptr, cut_length ); | 				string_append_c_str_len( & 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 ) | ||||||
| 				append( & content,  cut_ptr, cut_length ); | 				string_append_c_str_len( & content,  cut_ptr, cut_length ); | ||||||
|  |  | ||||||
| 			// Replace with a space | 			// Replace with a space | ||||||
| 			if ( * back( & content ) != ' ' ) | 			if ( * string_back( content ) != ' ' ) | ||||||
| 				append( & content,  ' ' ); | 				string_append_char( & content,  ' ' ); | ||||||
|  |  | ||||||
| 			scanner += 2; | 			scanner += 2; | ||||||
| 			tokleft -= 2; | 			tokleft -= 2; | ||||||
| @@ -408,17 +408,17 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
|  |  | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
|  |  | ||||||
| 				append( & content,  cut_ptr, cut_length ); | 				string_append_c_str_len( & 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 ) | ||||||
| 				append( & content,  cut_ptr, cut_length ); | 				string_append_c_str_len( & content,  cut_ptr, cut_length ); | ||||||
|  |  | ||||||
| 			// Replace with a space | 			// Replace with a space | ||||||
| 			if ( * back( & content ) != ' ' ) | 			if ( * string_back( content ) != ' ' ) | ||||||
| 				append( & content,  ' ' ); | 				string_append_char( & content,  ' ' ); | ||||||
|  |  | ||||||
| 			move_fwd(); | 			move_fwd(); | ||||||
|  |  | ||||||
| @@ -429,7 +429,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
| 		// Escaped newlines | 		// Escaped newlines | ||||||
| 		if ( scanner[0] == '\\' ) | 		if ( scanner[0] == '\\' ) | ||||||
| 		{ | 		{ | ||||||
| 			append( & content,  cut_ptr, cut_length ); | 			string_append_c_str_len( & 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' ) | ||||||
| @@ -456,7 +456,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 ] ) ) | ||||||
| 		{ | 		{ | ||||||
| 			append( & content,  cut_ptr, cut_length ); | 			string_append_c_str_len( & content,  cut_ptr, cut_length ); | ||||||
| 			do | 			do | ||||||
| 			{ | 			{ | ||||||
| 				move_fwd(); | 				move_fwd(); | ||||||
| @@ -466,9 +466,9 @@ 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 | ||||||
| 			char* last = back(& content); | 			char* last = string_back(content); | ||||||
| 			if ( last == nullptr || * last != ' ' ) | 			if ( last == nullptr || * last != ' ' ) | ||||||
| 				append( & content,  ' ' ); | 				string_append_char( & content, ' ' ); | ||||||
|  |  | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| @@ -478,7 +478,7 @@ String strip_formatting( StrC raw_text, bool preserve_newlines = true ) | |||||||
|  |  | ||||||
| 	if ( last_cut < raw_text.Len ) | 	if ( last_cut < raw_text.Len ) | ||||||
| 	{ | 	{ | ||||||
| 		append( & content,  cut_ptr, raw_text.Len - last_cut ); | 		string_append_c_str_len( & content,  cut_ptr, raw_text.Len - last_cut ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #undef cut_ptr | #undef cut_ptr | ||||||
| @@ -669,7 +669,7 @@ CodeAttributes parse_attributes() | |||||||
|  |  | ||||||
| 		Code result     = make_code(); | 		Code result     = make_code(); | ||||||
| 		result->Type    = CT_PlatformAttributes; | 		result->Type    = CT_PlatformAttributes; | ||||||
| 		result->Name    = get_cached_string( { length(name_stripped), name_stripped } ); | 		result->Name    = get_cached_string( { string_length(name_stripped), name_stripped } ); | ||||||
| 		result->Content = result->Name; | 		result->Content = result->Name; | ||||||
| 		// result->Token   = | 		// result->Token   = | ||||||
|  |  | ||||||
| @@ -723,7 +723,7 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
| 		char interface_arr_mem[ kilobytes(4) ] {0}; | 		char interface_arr_mem[ kilobytes(4) ] {0}; | ||||||
| 	Array<CodeTypename> interfaces; { | 	Array<CodeTypename> interfaces; { | ||||||
| 		Arena arena = arena_init_from_memory( interface_arr_mem, kilobytes(4) ); | 		Arena arena = arena_init_from_memory( interface_arr_mem, kilobytes(4) ); | ||||||
| 		interfaces  = array_init_reserve<CodeTypename>( allocator_info(& arena), 4 ); | 		interfaces  = array_init_reserve(CodeTypename, arena_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. | ||||||
| @@ -754,7 +754,7 @@ Code parse_class_struct( TokType which, bool inplace_def = false ) | |||||||
| 			} | 			} | ||||||
| 			Token interface_tok = parse_identifier(); | 			Token interface_tok = parse_identifier(); | ||||||
|  |  | ||||||
| 			append( & interfaces, def_type( to_str(interface_tok) ) ); | 			array_append( & interfaces, def_type( to_str(interface_tok) ) ); | ||||||
| 			// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... | 			// <ModuleFlags> <class/struct> <Attributes> <Name> : <Access Specifier> <Name>, ... | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -786,7 +786,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; | ||||||
|  |  | ||||||
| 	free(& interfaces); | 	array_free(& interfaces); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1048,9 +1048,9 @@ CodeBody parse_class_struct_body( TokType which, Token name ) | |||||||
| 					if ( attributes ) | 					if ( attributes ) | ||||||
| 					{ | 					{ | ||||||
| 						String fused = string_make_reserve( GlobalAllocator, attributes->Content.Len + more_attributes->Content.Len ); | 						String fused = string_make_reserve( GlobalAllocator, attributes->Content.Len + more_attributes->Content.Len ); | ||||||
| 						append_fmt( & fused, "%S %S", attributes->Content, more_attributes->Content ); | 						string_append_fmt( & fused, "%S %S", attributes->Content, more_attributes->Content ); | ||||||
|  |  | ||||||
| 						attributes->Name    = get_cached_string({ length(fused), fused }); | 						attributes->Name    = get_cached_string( { string_length(fused), fused }); | ||||||
| 						attributes->Content = attributes->Name; | 						attributes->Content = attributes->Name; | ||||||
| 						// <Attributes> <Specifiers> <Attributes> | 						// <Attributes> <Specifiers> <Attributes> | ||||||
| 					} | 					} | ||||||
| @@ -1086,7 +1086,7 @@ CodeBody parse_class_struct_body( TokType which, Token name ) | |||||||
| 			{ | 			{ | ||||||
| 				if ( nexttok.Type == Tok_Capture_Start && name.Length && currtok.Type == Tok_Identifier ) | 				if ( nexttok.Type == Tok_Capture_Start && name.Length && currtok.Type == Tok_Identifier ) | ||||||
| 				{ | 				{ | ||||||
| 					if ( str_compare( name.Text, currtok.Text, name.Length ) == 0 ) | 					if ( str_compare_len( name.Text, currtok.Text, name.Length ) == 0 ) | ||||||
| 					{ | 					{ | ||||||
| 						member = parse_constructor( specifiers ); | 						member = parse_constructor( specifiers ); | ||||||
| 						// <Attributes> <Specifiers> <Name>() | 						// <Attributes> <Specifiers> <Name>() | ||||||
| @@ -1159,7 +1159,7 @@ Code parse_complicated_definition( TokType which ) | |||||||
|  |  | ||||||
| 	s32 idx         = tokens.Idx; | 	s32 idx         = tokens.Idx; | ||||||
| 	s32 level       = 0; | 	s32 level       = 0; | ||||||
| 	for ( ; idx < num(tokens.Arr); idx++ ) | 	for ( ; idx < array_num(tokens.Arr); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( tokens.Arr[ idx ].Type == Tok_BraceCurly_Open ) | 		if ( tokens.Arr[ idx ].Type == Tok_BraceCurly_Open ) | ||||||
| 			level++; | 			level++; | ||||||
| @@ -1344,7 +1344,7 @@ CodeDefine parse_define() | |||||||
| 		return define; | 		return define; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	define->Content = get_cached_string( to_strc( strip_formatting( to_str(currtok), strip_formatting_dont_preserve_newlines )) ); | 	define->Content = get_cached_string( string_to_strc( strip_formatting( to_str(currtok), strip_formatting_dont_preserve_newlines )) ); | ||||||
| 	eat( Tok_Preprocess_Content ); | 	eat( Tok_Preprocess_Content ); | ||||||
| 	// #define <Name> <Content> | 	// #define <Name> <Content> | ||||||
|  |  | ||||||
| @@ -1489,12 +1489,12 @@ CodeFn parse_function_after_name( | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	String | 	String | ||||||
| 	name_stripped = string_make( GlobalAllocator, to_str(name) ); | 	name_stripped = string_make_strc( GlobalAllocator, to_str(name) ); | ||||||
| 	strip_space(name_stripped); | 	strip_space(name_stripped); | ||||||
|  |  | ||||||
| 	CodeFn | 	CodeFn | ||||||
| 	result              = (CodeFn) make_code(); | 	result              = (CodeFn) make_code(); | ||||||
| 	result->Name        = get_cached_string( to_strc(name_stripped) ); | 	result->Name        = get_cached_string( string_to_strc(name_stripped) ); | ||||||
| 	result->ModuleFlags = mflags; | 	result->ModuleFlags = mflags; | ||||||
|  |  | ||||||
| 	if ( body ) | 	if ( body ) | ||||||
| @@ -1840,7 +1840,7 @@ CodeBody parse_global_nspace( CodeType 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 < num(Context.Tokens.Arr); idx++ ) | 				for ( ; idx < array_num(Context.Tokens.Arr); idx++ ) | ||||||
| 				{ | 				{ | ||||||
| 					Token tok = Context.Tokens.Arr[ idx ]; | 					Token tok = Context.Tokens.Arr[ idx ]; | ||||||
|  |  | ||||||
| @@ -1912,14 +1912,14 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) | |||||||
|  |  | ||||||
| 	s32   idx = tokens.Idx; | 	s32   idx = tokens.Idx; | ||||||
| 	Token nav = tokens.Arr[ idx ]; | 	Token nav = tokens.Arr[ idx ]; | ||||||
| 	for ( ; idx < num(tokens.Arr); idx++, nav = tokens.Arr[ idx ] ) | 	for ( ; idx < array_num(tokens.Arr); idx++, nav = tokens.Arr[ 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 < num(tokens.Arr); idx++, nav = tokens.Arr[idx] ) | 			for ( ; idx < array_num(tokens.Arr); idx++, nav = tokens.Arr[idx] ) | ||||||
| 			{ | 			{ | ||||||
| 				if (nav.Text[ 0 ] == '<') | 				if (nav.Text[ 0 ] == '<') | ||||||
| 					++ template_level; | 					++ template_level; | ||||||
| @@ -2001,7 +2001,7 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers ) | |||||||
| 		tok_left = tokens.Arr[idx]; | 		tok_left = tokens.Arr[idx]; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool is_same = str_compare( tok_right.Text, tok_left.Text, tok_right.Length ) == 0; | 	bool is_same = str_compare_len( tok_right.Text, tok_left.Text, tok_right.Length ) == 0; | ||||||
| 	if (tok_left.Type == Tok_Identifier && is_same) | 	if (tok_left.Type == Tok_Identifier && is_same) | ||||||
| 	{ | 	{ | ||||||
| 		// We have found the pattern we desired | 		// We have found the pattern we desired | ||||||
| @@ -2357,7 +2357,7 @@ CodeOperator parse_operator_after_ret_type( | |||||||
| 		{ | 		{ | ||||||
| 			StrC str_new    = to_str(Op_New); | 			StrC str_new    = to_str(Op_New); | ||||||
| 			StrC str_delete = to_str(Op_Delete); | 			StrC str_delete = to_str(Op_Delete); | ||||||
| 			if ( str_compare( currtok.Text, str_new.Ptr, max(str_new.Len - 1, currtok.Length)) == 0) | 			if ( str_compare_len( currtok.Text, str_new.Ptr, max(str_new.Len - 1, currtok.Length)) == 0) | ||||||
| 			{ | 			{ | ||||||
| 				op = Op_New; | 				op = Op_New; | ||||||
| 				eat( Tok_Identifier ); | 				eat( Tok_Identifier ); | ||||||
| @@ -2369,7 +2369,7 @@ CodeOperator parse_operator_after_ret_type( | |||||||
| 						idx++; | 						idx++; | ||||||
| 				} | 				} | ||||||
| 				Token next = Context.Tokens.Arr[idx]; | 				Token next = Context.Tokens.Arr[idx]; | ||||||
| 				if ( currtok.Type == Tok_Operator && str_compare(currtok.Text, "[]", 2) == 0) | 				if ( currtok.Type == Tok_Operator && str_compare_len(currtok.Text, "[]", 2) == 0) | ||||||
| 				{ | 				{ | ||||||
| 					eat(Tok_Operator); | 					eat(Tok_Operator); | ||||||
| 					op = Op_NewArray; | 					op = Op_NewArray; | ||||||
| @@ -2381,7 +2381,7 @@ CodeOperator parse_operator_after_ret_type( | |||||||
| 					op = Op_NewArray; | 					op = Op_NewArray; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else if ( str_compare( currtok.Text, str_delete.Ptr, max(str_delete.Len - 1, currtok.Length )) == 0) | 			else if ( str_compare_len( currtok.Text, str_delete.Ptr, max(str_delete.Len - 1, currtok.Length )) == 0) | ||||||
| 			{ | 			{ | ||||||
| 				op = Op_Delete; | 				op = Op_Delete; | ||||||
| 				eat(Tok_Identifier); | 				eat(Tok_Identifier); | ||||||
| @@ -2393,7 +2393,7 @@ CodeOperator parse_operator_after_ret_type( | |||||||
| 						idx++; | 						idx++; | ||||||
| 				} | 				} | ||||||
| 				Token next = Context.Tokens.Arr[idx]; | 				Token next = Context.Tokens.Arr[idx]; | ||||||
| 				if ( currtok.Type == Tok_Operator && str_compare(currtok.Text, "[]", 2) == 0) | 				if ( currtok.Type == Tok_Operator && str_compare_len(currtok.Text, "[]", 2) == 0) | ||||||
| 				{ | 				{ | ||||||
| 					eat(Tok_Operator); | 					eat(Tok_Operator); | ||||||
| 					op = Op_DeleteArray; | 					op = Op_DeleteArray; | ||||||
| @@ -2513,7 +2513,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 < num(Context.Tokens.Arr); idx++ ) | 	for ( ; idx < array_num(Context.Tokens.Arr); idx++ ) | ||||||
| 	{ | 	{ | ||||||
| 		Token tok = Context.Tokens.Arr[ idx ]; | 		Token tok = Context.Tokens.Arr[ idx ]; | ||||||
|  |  | ||||||
| @@ -2730,7 +2730,7 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 				eat( currtok.Type ); | 				eat( currtok.Type ); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			value = untyped_str( to_strc(strip_formatting( to_str(value_tok), strip_formatting_dont_preserve_newlines )) ); | 			value = untyped_str( string_to_strc(strip_formatting( to_str(value_tok), strip_formatting_dont_preserve_newlines )) ); | ||||||
| 			// ( <Macro> <ValueType> <Name> = <Expression> | 			// ( <Macro> <ValueType> <Name> = <Expression> | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -2845,7 +2845,7 @@ CodeParam parse_params( bool use_template_capture ) | |||||||
| 					eat( currtok.Type ); | 					eat( currtok.Type ); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				value = untyped_str( to_strc(strip_formatting( to_str(value_tok), strip_formatting_dont_preserve_newlines )) ); | 				value = untyped_str( string_to_strc(strip_formatting( to_str(value_tok), strip_formatting_dont_preserve_newlines )) ); | ||||||
| 				// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression> | 				// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression> | ||||||
| 			} | 			} | ||||||
| 			// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. | 			// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> = <Expression>, .. | ||||||
| @@ -2957,7 +2957,7 @@ Code parse_simple_preprocess( TokType which ) | |||||||
| 		// <Macro> { <Body> } | 		// <Macro> { <Body> } | ||||||
|  |  | ||||||
| 		StrC prev_proc = Context.Scope->Prev->ProcName; | 		StrC prev_proc = Context.Scope->Prev->ProcName; | ||||||
| 		if ( str_compare( prev_proc.Ptr, "parse_typedef", prev_proc.Len ) != 0 ) | 		if ( str_compare_len( prev_proc.Ptr, "parse_typedef", prev_proc.Len ) != 0 ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( check( Tok_Statement_End )) | 			if ( check( Tok_Statement_End )) | ||||||
| 			{ | 			{ | ||||||
| @@ -2975,7 +2975,7 @@ Code parse_simple_preprocess( TokType which ) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if ( str_compare( Context.Scope->Prev->ProcName.Ptr, "parse_typedef", Context.Scope->Prev->ProcName.Len ) != 0 ) | 		if ( str_compare_len( Context.Scope->Prev->ProcName.Ptr, "parse_typedef", Context.Scope->Prev->ProcName.Len ) != 0 ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( check( Tok_Statement_End )) | 			if ( check( Tok_Statement_End )) | ||||||
| 			{ | 			{ | ||||||
| @@ -2994,7 +2994,7 @@ Code parse_simple_preprocess( TokType which ) | |||||||
|  |  | ||||||
| 	char const* content = str_fmt_buf( "%.*s ", tok.Length, tok.Text ); | 	char const* content = str_fmt_buf( "%.*s ", tok.Length, tok.Text ); | ||||||
|  |  | ||||||
| 	Code result = untyped_str( GEN_NS to_str(content) ); | 	Code result = untyped_str( to_strc_from_c_str(content) ); | ||||||
| 	Context.Scope->Name = tok; | 	Context.Scope->Name = tok; | ||||||
|  |  | ||||||
| 	pop(& Context); | 	pop(& Context); | ||||||
| @@ -3494,7 +3494,7 @@ CodeDestructor parse_destructor( CodeSpecifiers specifiers ) | |||||||
|  |  | ||||||
| 			append(specifiers, Spec_Pure ); | 			append(specifiers, Spec_Pure ); | ||||||
| 		} | 		} | ||||||
| 		else if ( left && str_compare( upcoming.Text, "default", sizeof("default") - 1 ) == 0) | 		else if ( left && str_compare_len( upcoming.Text, "default", sizeof("default") - 1 ) == 0) | ||||||
| 		{ | 		{ | ||||||
| 			body = parse_assignment_expression(); | 			body = parse_assignment_expression(); | ||||||
| 			// <Virtual Specifier> ~< | 			// <Virtual Specifier> ~< | ||||||
| @@ -3609,7 +3609,7 @@ CodeEnum parse_enum( bool inplace_def ) | |||||||
| 		// We'll support the enum_underlying macro | 		// We'll support the enum_underlying macro | ||||||
| 		StrC sig = txt("enum_underlying"); | 		StrC sig = txt("enum_underlying"); | ||||||
|  |  | ||||||
| 		if (currtok.Length >= sig.Len && str_compare(currtok.Text, sig.Ptr, sig.Len) == 0 ) | 		if (currtok.Length >= sig.Len && str_compare_len(currtok.Text, sig.Ptr, sig.Len) == 0 ) | ||||||
| 		{ | 		{ | ||||||
| 			use_macro_underlying = true; | 			use_macro_underlying = true; | ||||||
| 			underlying_macro     = parse_simple_preprocess( Tok_Preprocess_Macro); | 			underlying_macro     = parse_simple_preprocess( Tok_Preprocess_Macro); | ||||||
| @@ -3861,6 +3861,45 @@ CodeFriend parse_friend() | |||||||
|  |  | ||||||
| 	CodeFn         function   = { nullptr }; | 	CodeFn         function   = { nullptr }; | ||||||
| 	CodeOperator   op         = { nullptr }; | 	CodeOperator   op         = { nullptr }; | ||||||
|  | 	CodeSpecifiers specifiers = { nullptr }; | ||||||
|  |  | ||||||
|  | 	// Specifiers Parsing | ||||||
|  | 	{ | ||||||
|  | 		Specifier specs_found[ 16 ] { Spec_NumSpecifiers }; | ||||||
|  | 		s32       NumSpecifiers = 0; | ||||||
|  |  | ||||||
|  | 		while ( left && is_specifier(currtok) ) | ||||||
|  | 		{ | ||||||
|  | 			Specifier spec = to_specifier( to_str(currtok) ); | ||||||
|  |  | ||||||
|  | 			switch ( spec ) | ||||||
|  | 			{ | ||||||
|  | 				case Spec_Const : | ||||||
|  | 				case Spec_Inline : | ||||||
|  | 				case Spec_ForceInline : | ||||||
|  | 					break; | ||||||
|  |  | ||||||
|  | 				default : | ||||||
|  | 					log_failure( "Invalid specifier %s for friend definition\n%s", to_str( spec ), to_string(Context) ); | ||||||
|  | 					pop(& Context); | ||||||
|  | 					return InvalidCode; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Ignore const it will be handled by the type | ||||||
|  | 			if ( spec == Spec_Const ) | ||||||
|  | 				break; | ||||||
|  |  | ||||||
|  | 			specs_found[ NumSpecifiers ] = spec; | ||||||
|  | 			NumSpecifiers++; | ||||||
|  | 			eat( currtok.Type ); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if ( NumSpecifiers ) | ||||||
|  | 		{ | ||||||
|  | 			specifiers = def_specifiers( NumSpecifiers, specs_found ); | ||||||
|  | 		} | ||||||
|  | 		// <friend> <specifiers> | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Type declaration or return type | 	// Type declaration or return type | ||||||
| 	CodeTypename type = parse_type(); | 	CodeTypename type = parse_type(); | ||||||
| @@ -3879,7 +3918,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, NullCode, NullCode, type, name ); | 		function = parse_function_after_name( ModuleFlag_None, NullCode, specifiers, type, name ); | ||||||
|  |  | ||||||
| 		// Parameter list | 		// Parameter list | ||||||
| 		// CodeParam params = parse_params(); | 		// CodeParam params = parse_params(); | ||||||
| @@ -3897,7 +3936,7 @@ CodeFriend parse_friend() | |||||||
| 	// Operator declaration or definition | 	// Operator declaration or definition | ||||||
| 	if ( currtok.Type == Tok_Decl_Operator ) | 	if ( currtok.Type == Tok_Decl_Operator ) | ||||||
| 	{ | 	{ | ||||||
| 		op = parse_operator_after_ret_type( ModuleFlag_None, NullCode, NullCode, type ); | 		op = parse_operator_after_ret_type( ModuleFlag_None, NullCode, specifiers, type ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeComment inline_cmt = NullCode; | 	CodeComment inline_cmt = NullCode; | ||||||
| @@ -4375,7 +4414,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 < num(Context.Tokens.Arr); idx++ ) | 			for ( ; idx < array_num(Context.Tokens.Arr); idx++ ) | ||||||
| 			{ | 			{ | ||||||
| 				Token tok = Context.Tokens.Arr[ idx ]; | 				Token tok = Context.Tokens.Arr[ idx ]; | ||||||
|  |  | ||||||
| @@ -4829,7 +4868,7 @@ else if ( currtok.Type == Tok_DeclType ) | |||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	result->Name = get_cached_string( to_strc(name_stripped) ); | 	result->Name = get_cached_string( string_to_strc(name_stripped) ); | ||||||
|  |  | ||||||
| 	if ( attributes ) | 	if ( attributes ) | ||||||
| 		result->Attributes = attributes; | 		result->Attributes = attributes; | ||||||
| @@ -4924,7 +4963,7 @@ CodeTypedef parse_typedef() | |||||||
|  |  | ||||||
| 			s32 idx = tokens.Idx; | 			s32 idx = tokens.Idx; | ||||||
| 			s32 level = 0; | 			s32 level = 0; | ||||||
| 			for ( ; idx < num(tokens.Arr); idx ++ ) | 			for ( ; idx < array_num(tokens.Arr); idx ++ ) | ||||||
| 			{ | 			{ | ||||||
| 				if ( tokens.Arr[idx].Type == Tok_BraceCurly_Open ) | 				if ( tokens.Arr[idx].Type == Tok_BraceCurly_Open ) | ||||||
| 					level++; | 					level++; | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ global CodeTypename t_wchar_t; | |||||||
| global CodeTypename t_class; | global CodeTypename t_class; | ||||||
| global CodeTypename t_typename; | global CodeTypename t_typename; | ||||||
|  |  | ||||||
| global Array< StringCached > PreprocessorDefines; | global Array(StringCached) PreprocessorDefines; | ||||||
|  |  | ||||||
| #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | #ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS | ||||||
| global CodeTypename t_b32; | global CodeTypename t_b32; | ||||||
|   | |||||||
| @@ -31,23 +31,23 @@ usize array_grow_formula(ssize value); | |||||||
|  |  | ||||||
| template<class Type> Array(Type)  array_init        (AllocatorInfo allocator); | template<class Type> Array(Type)  array_init        (AllocatorInfo allocator); | ||||||
| template<class Type> Array(Type)  array_init_reserve(AllocatorInfo allocator, ssize capacity); | template<class Type> Array(Type)  array_init_reserve(AllocatorInfo allocator, ssize capacity); | ||||||
| template<class Type> bool         append            (Array(Type)* array, Array(Type) other); | template<class Type> bool         array_append      (Array(Type)* array, Array(Type) other); | ||||||
| template<class Type> bool         append            (Array(Type)* array, Type value); | template<class Type> bool         array_append      (Array(Type)* array, Type value); | ||||||
| template<class Type> bool         append            (Array(Type)* array, Type* items, usize item_num); | template<class Type> bool         array_append      (Array(Type)* array, Type* items, usize item_num); | ||||||
| template<class Type> bool         append_at         (Array(Type)* array, Type item, usize idx); | template<class Type> bool         array_append_at   (Array(Type)* array, Type item, usize idx); | ||||||
| template<class Type> bool         append_at         (Array(Type)* array, Type* items, usize item_num, usize idx); | template<class Type> bool         array_append_at   (Array(Type)* array, Type* items, usize item_num, usize idx); | ||||||
| template<class Type> Type*        back              (Array(Type)  array); | template<class Type> Type*        array_back        (Array(Type)  array); | ||||||
| template<class Type> void         clear             (Array(Type)  array); | template<class Type> void         array_clear       (Array(Type)  array); | ||||||
| template<class Type> bool         fill              (Array(Type)  array, usize begin, usize end, Type value); | template<class Type> bool         array_fill        (Array(Type)  array, usize begin, usize end, Type value); | ||||||
| template<class Type> void         free              (Array(Type)* array); | template<class Type> void         array_free        (Array(Type)* array); | ||||||
| template<class Type> bool         grow              (Array(Type)* array, usize min_capacity); | template<class Type> bool         arary_grow        (Array(Type)* array, usize min_capacity); | ||||||
| template<class Type> usize        num               (Array(Type)  array); | template<class Type> usize        array_num         (Array(Type)  array); | ||||||
| template<class Type> void         pop               (Array(Type)  array); | template<class Type> void         arary_pop         (Array(Type)  array); | ||||||
| template<class Type> void         remove_at         (Array(Type)  array, usize idx); | template<class Type> void         arary_remove_at   (Array(Type)  array, usize idx); | ||||||
| template<class Type> bool         reserve           (Array(Type)* array, usize new_capacity); | template<class Type> bool         arary_reserve     (Array(Type)* array, usize new_capacity); | ||||||
| template<class Type> bool         resize            (Array(Type)* array, usize num); | template<class Type> bool         arary_resize      (Array(Type)* array, usize num); | ||||||
| template<class Type> bool         set_capacity      (Array(Type)* array, usize new_capacity); | template<class Type> bool         arary_set_capacity(Array(Type)* array, usize new_capacity); | ||||||
| template<class Type> ArrayHeader* get_header        (Array(Type)  array); | template<class Type> ArrayHeader* arary_get_header  (Array(Type)  array); | ||||||
|  |  | ||||||
| struct ArrayHeader { | struct ArrayHeader { | ||||||
| 	AllocatorInfo Allocator; | 	AllocatorInfo Allocator; | ||||||
| @@ -66,23 +66,23 @@ struct Array | |||||||
| 	forceinline static Array  init_reserve(AllocatorInfo allocator, ssize capacity) { return GEN_NS array_init_reserve<Type>(allocator, capacity); } | 	forceinline static Array  init_reserve(AllocatorInfo allocator, ssize capacity) { return GEN_NS array_init_reserve<Type>(allocator, capacity); } | ||||||
| 	forceinline static usize  grow_formula(ssize value)                             { return GEN_NS array_grow_formula<Type>(value); } | 	forceinline static usize  grow_formula(ssize value)                             { return GEN_NS array_grow_formula<Type>(value); } | ||||||
|  |  | ||||||
| 	forceinline bool         append(Array other)                               { return GEN_NS append<Type>(this, other); } | 	forceinline bool         append(Array other)                               { return GEN_NS array_append<Type>(this, other); } | ||||||
| 	forceinline bool         append(Type value)                                { return GEN_NS append<Type>(this, value); } | 	forceinline bool         append(Type value)                                { return GEN_NS array_append<Type>(this, value); } | ||||||
| 	forceinline bool         append(Type* items, usize item_num)               { return GEN_NS append<Type>(this, items, item_num); } | 	forceinline bool         append(Type* items, usize item_num)               { return GEN_NS array_append<Type>(this, items, item_num); } | ||||||
| 	forceinline bool         append_at(Type item, usize idx)                   { return GEN_NS append_at<Type>(this, item, idx); } | 	forceinline bool         append_at(Type item, usize idx)                   { return GEN_NS array_append_at<Type>(this, item, idx); } | ||||||
| 	forceinline bool         append_at(Type* items, usize item_num, usize idx) { return GEN_NS append_at<Type>(this, items, item_num, idx); } | 	forceinline bool         append_at(Type* items, usize item_num, usize idx) { return GEN_NS array_append_at<Type>(this, items, item_num, idx); } | ||||||
| 	forceinline Type*        back()                                            { return GEN_NS back<Type>(* this); } | 	forceinline Type*        back()                                            { return GEN_NS array_back<Type>(* this); } | ||||||
| 	forceinline void         clear()                                           { GEN_NS clear<Type>(* this); } | 	forceinline void         clear()                                           {        GEN_NS array_clear<Type>(* this); } | ||||||
| 	forceinline bool         fill(usize begin, usize end, Type value)          { return GEN_NS fill<Type>(* this, begin, end, value); } | 	forceinline bool         fill(usize begin, usize end, Type value)          { return GEN_NS array_fill<Type>(* this, begin, end, value); } | ||||||
| 	forceinline void         free()                                            { GEN_NS free<Type>(this); } | 	forceinline void         free()                                            {        GEN_NS array_free<Type>(this); } | ||||||
| 	forceinline ArrayHeader* get_header()                                      { return GEN_NS get_header<Type>(* this); } | 	forceinline ArrayHeader* get_header()                                      { return GEN_NS array_get_header<Type>(* this); } | ||||||
| 	forceinline bool         grow(usize min_capacity)                          { return GEN_NS grow<Type>(this, min_capacity); } | 	forceinline bool         grow(usize min_capacity)                          { return GEN_NS array_grow<Type>(this, min_capacity); } | ||||||
| 	forceinline usize        num()                                             { return GEN_NS num<Type>(*this); } | 	forceinline usize        num()                                             { return GEN_NS array_num<Type>(*this); } | ||||||
| 	forceinline void         pop()                                             { GEN_NS pop<Type>(* this); } | 	forceinline void         pop()                                             {        GEN_NS array_pop<Type>(* this); } | ||||||
| 	forceinline void         remove_at(usize idx)                              { GEN_NS remove_at<Type>(* this, idx); } | 	forceinline void         remove_at(usize idx)                              {        GEN_NS array_remove_at<Type>(* this, idx); } | ||||||
| 	forceinline bool         reserve(usize new_capacity)                       { return GEN_NS reserve<Type>(this, new_capacity); } | 	forceinline bool         reserve(usize new_capacity)                       { return GEN_NS array_reserve<Type>(this, new_capacity); } | ||||||
| 	forceinline bool         resize(usize num)                                 { return GEN_NS resize<Type>(this, num); } | 	forceinline bool         resize(usize num)                                 { return GEN_NS array_resize<Type>(this, num); } | ||||||
| 	forceinline bool         set_capacity(usize new_capacity)                  { return GEN_NS set_capacity<Type>(this, new_capacity); } | 	forceinline bool         set_capacity(usize new_capacity)                  { return GEN_NS array_set_capacity<Type>(this, new_capacity); } | ||||||
| #pragma endregion Member Mapping | #pragma endregion Member Mapping | ||||||
|  |  | ||||||
| 	forceinline operator Type*()             { return Data; } | 	forceinline operator Type*()             { return Data; } | ||||||
| @@ -108,14 +108,14 @@ template<class Type> bool         resize(Array<Type>& array, usize num) | |||||||
| template<class Type> bool         set_capacity(Array<Type>& array, usize new_capacity)                  { return GEN_NS set_capacity( & array, new_capacity); } | template<class Type> bool         set_capacity(Array<Type>& array, usize new_capacity)                  { return GEN_NS set_capacity( & array, new_capacity); } | ||||||
|  |  | ||||||
| template<class Type> forceinline Type* begin(Array<Type>& array)             { return array;      } | template<class Type> forceinline Type* begin(Array<Type>& array)             { return array;      } | ||||||
| template<class Type> forceinline Type* end(Array<Type>& array)               { return array + get_header(array)->Num; } | template<class Type> forceinline Type* end(Array<Type>& array)               { return array + array_get_header(array)->Num; } | ||||||
| template<class Type> forceinline Type* next(Array<Type>& array, Type* entry) { return entry + 1; } | template<class Type> forceinline Type* next(Array<Type>& array, Type* entry) { return entry + 1; } | ||||||
| #else |  | ||||||
| template<class Type> forceinline Type* begin(Array<Type> array)             { return array;      } |  | ||||||
| template<class Type> forceinline Type* end(Array<Type> array)               { return array + get_header(array)->Num; } |  | ||||||
| template<class Type> forceinline Type* next(Array<Type> array, Type* entry) { return entry + 1; } |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | template<class Type> forceinline Type* array_begin(Array<Type> array)             { return array;      } | ||||||
|  | template<class Type> forceinline Type* array_end(Array<Type> array)               { return array + array_get_header(array)->Num; } | ||||||
|  | template<class Type> forceinline Type* array_next(Array<Type> array, Type* entry) { return ++ entry; } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| Array<Type> array_init(AllocatorInfo allocator) { | Array<Type> array_init(AllocatorInfo allocator) { | ||||||
| 	return array_init_reserve<Type>(allocator, array_grow_formula(0)); | 	return array_init_reserve<Type>(allocator, array_grow_formula(0)); | ||||||
| @@ -141,20 +141,20 @@ usize array_grow_formula(ssize value) { | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append(Array<Type>* array, Array<Type> other) { | bool array_append(Array<Type>* array, Array<Type> other) { | ||||||
| 	return append(array, other, num(other)); | 	return append(array, other, num(other)); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append(Array<Type>* array, Type value) | bool array_append(Array<Type>* array, Type value) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
|  |  | ||||||
| 	if (header->Num == header->Capacity) | 	if (header->Num == header->Capacity) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! grow(array, header->Capacity)) | 		if ( ! array_grow(array, header->Capacity)) | ||||||
| 			return false; | 			return false; | ||||||
| 		header = get_header(* array); | 		header = array_get_header(* array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	(*array)[ header->Num] = value; | 	(*array)[ header->Num] = value; | ||||||
| @@ -164,15 +164,15 @@ bool append(Array<Type>* array, Type value) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append(Array<Type>* array, Type* items, usize item_num) | bool array_append(Array<Type>* array, Type* items, usize item_num) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
|  |  | ||||||
| 	if (header->Num + item_num > header->Capacity) | 	if (header->Num + item_num > header->Capacity) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! grow(array, header->Capacity + item_num)) | 		if ( ! grow(array, header->Capacity + item_num)) | ||||||
| 			return false; | 			return false; | ||||||
| 		header = get_header(array); | 		header = array_get_header(array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	mem_copy((Type*)array + header->Num, items, item_num * sizeof(Type)); | 	mem_copy((Type*)array + header->Num, items, item_num * sizeof(Type)); | ||||||
| @@ -182,9 +182,9 @@ bool append(Array<Type>* array, Type* items, usize item_num) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append_at(Array<Type>* array, Type item, usize idx) | bool array_append_at(Array<Type>* array, Type item, usize idx) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
|  |  | ||||||
| 	ssize slot = idx; | 	ssize slot = idx; | ||||||
| 	if (slot >= header->Num) | 	if (slot >= header->Num) | ||||||
| @@ -195,10 +195,10 @@ bool append_at(Array<Type>* array, Type item, usize idx) | |||||||
|  |  | ||||||
| 	if (header->Capacity < header->Num + 1) | 	if (header->Capacity < header->Num + 1) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! grow(array, header->Capacity + 1)) | 		if ( ! array_grow(array, header->Capacity + 1)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		header = get_header(* array); | 		header = array_get_header(* array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Type* target = &(*array)[slot]; | 	Type* target = &(*array)[slot]; | ||||||
| @@ -206,13 +206,13 @@ bool append_at(Array<Type>* array, Type item, usize idx) | |||||||
| 	mem_move(target + 1, target, (header->Num - slot) * sizeof(Type)); | 	mem_move(target + 1, target, (header->Num - slot) * sizeof(Type)); | ||||||
| 	header->Num++; | 	header->Num++; | ||||||
|  |  | ||||||
| 	header = get_header(* array); | 	header = array_get_header(* array); | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool append_at(Array<Type>* array, Type* items, usize item_num, usize idx) | bool array_append_at(Array<Type>* array, Type* items, usize item_num, usize idx) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = get_header(array); | ||||||
|  |  | ||||||
| @@ -240,11 +240,11 @@ bool append_at(Array<Type>* array, Type* items, usize item_num, usize idx) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| Type* back(Array<Type>* array) | Type* array_back(Array<Type>* array) | ||||||
| { | { | ||||||
| 	GEN_ASSERT(array != nullptr); | 	GEN_ASSERT(array != nullptr); | ||||||
|  |  | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
| 	if (header->Num <= 0) | 	if (header->Num <= 0) | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
|  |  | ||||||
| @@ -252,15 +252,15 @@ Type* back(Array<Type>* array) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void clear(Array<Type> array) { | void array_clear(Array<Type> array) { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
| 	header->Num = 0; | 	header->Num = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool fill(Array<Type> array, usize begin, usize end, Type value) | bool array_fill(Array<Type> array, usize begin, usize end, Type value) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
|  |  | ||||||
| 	if (begin < 0 || end > header->Num) | 	if (begin < 0 || end > header->Num) | ||||||
| 	return false; | 	return false; | ||||||
| @@ -274,49 +274,49 @@ bool fill(Array<Type> array, usize begin, usize end, Type value) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void free(Array<Type>* array) { | void array_free(Array<Type>* array) { | ||||||
| 	GEN_ASSERT(array != nullptr); | 	GEN_ASSERT(array != nullptr); | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
| 	GEN_NS free(header->Allocator, header); | 	allocator_free(header->Allocator, header); | ||||||
| 	Type** Data = (Type**)array; | 	Type** Data = (Type**)array; | ||||||
| 	*Data = nullptr; | 	*Data = nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> forceinline | template<class Type> forceinline | ||||||
| ArrayHeader* get_header(Array<Type> array) { | ArrayHeader* array_get_header(Array<Type> array) { | ||||||
|     Type* Data = array; |     Type* Data = array; | ||||||
|  |  | ||||||
| 	using NonConstType = TRemoveConst<Type>; | 	using NonConstType = TRemoveConst<Type>; | ||||||
|     return rcast(ArrayHeader*, const_cast<NonConstType*>(Data)) - 1; |     return rcast(ArrayHeader*, const_cast<NonConstType*>(Data)) - 1; | ||||||
| } | } | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool grow(Array<Type>* array, usize min_capacity) | bool array_grow(Array<Type>* array, usize min_capacity) | ||||||
| { | { | ||||||
| 	ArrayHeader* header       = get_header(* array); | 	ArrayHeader* header       = array_get_header(* array); | ||||||
| 	usize        new_capacity = array_grow_formula(header->Capacity); | 	usize        new_capacity = array_grow_formula(header->Capacity); | ||||||
|  |  | ||||||
| 	if (new_capacity < min_capacity) | 	if (new_capacity < min_capacity) | ||||||
| 		new_capacity = min_capacity; | 		new_capacity = min_capacity; | ||||||
|  |  | ||||||
| 	return set_capacity(array, new_capacity); | 	return array_set_capacity(array, new_capacity); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| usize num(Array<Type> array) { | usize array_num(Array<Type> array) { | ||||||
| 	return get_header(array)->Num; | 	return array_get_header(array)->Num; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void pop(Array<Type> array) { | void array_pop(Array<Type> array) { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
| 	GEN_ASSERT(header->Num > 0); | 	GEN_ASSERT(header->Num > 0); | ||||||
| 	header->Num--; | 	header->Num--; | ||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| void remove_at(Array<Type> array, usize idx) | void array_remove_at(Array<Type> array, usize idx) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
| 	GEN_ASSERT(idx < header->Num); | 	GEN_ASSERT(idx < header->Num); | ||||||
|  |  | ||||||
| 	mem_move(array + idx, array + idx + 1, sizeof(Type) * (header->Num - idx - 1)); | 	mem_move(array + idx, array + idx + 1, sizeof(Type) * (header->Num - idx - 1)); | ||||||
| @@ -324,9 +324,9 @@ void remove_at(Array<Type> array, usize idx) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool reserve(Array<Type>* array, usize new_capacity) | bool array_reserve(Array<Type>* array, usize new_capacity) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(array); | 	ArrayHeader* header = array_get_header(array); | ||||||
|  |  | ||||||
| 	if (header->Capacity < new_capacity) | 	if (header->Capacity < new_capacity) | ||||||
|  		return set_capacity(array, new_capacity); |  		return set_capacity(array, new_capacity); | ||||||
| @@ -335,14 +335,14 @@ bool reserve(Array<Type>* array, usize new_capacity) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool resize(Array<Type>* array, usize num) | bool array_resize(Array<Type>* array, usize num) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
|  |  | ||||||
| 	if (header->Capacity < num) { | 	if (header->Capacity < num) { | ||||||
| 		if (! grow( array, num)) | 		if (! array_grow( array, num)) | ||||||
| 			return false; | 			return false; | ||||||
| 		header = get_header(* array); | 		header = array_get_header(* array); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	header->Num = num; | 	header->Num = num; | ||||||
| @@ -350,9 +350,9 @@ bool resize(Array<Type>* array, usize num) | |||||||
| } | } | ||||||
|  |  | ||||||
| template<class Type> inline | template<class Type> inline | ||||||
| bool set_capacity(Array<Type>* array, usize new_capacity) | bool array_set_capacity(Array<Type>* array, usize new_capacity) | ||||||
| { | { | ||||||
| 	ArrayHeader* header = get_header(* array); | 	ArrayHeader* header = array_get_header(* array); | ||||||
|  |  | ||||||
| 	if (new_capacity == header->Capacity) | 	if (new_capacity == header->Capacity) | ||||||
| 	return true; | 	return true; | ||||||
| @@ -373,13 +373,15 @@ bool set_capacity(Array<Type>* array, usize new_capacity) | |||||||
|  |  | ||||||
| 	new_header->Capacity = new_capacity; | 	new_header->Capacity = new_capacity; | ||||||
|  |  | ||||||
| 	GEN_NS free(header->Allocator, header); | 	allocator_free(header->Allocator, header); | ||||||
|  |  | ||||||
| 	Type** Data = (Type**)array; | 	Type** Data = (Type**)array; | ||||||
| 	* Data = rcast(Type*, new_header + 1); | 	* Data = rcast(Type*, new_header + 1); | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #define array_init_reserve(type, allocator, cap) array_init_reserve<type>(allocator, cap) | ||||||
|  |  | ||||||
| #pragma endregion Array | #pragma endregion Array | ||||||
|  |  | ||||||
| // TODO(Ed) : This thing needs ALOT of work. | // TODO(Ed) : This thing needs ALOT of work. | ||||||
| @@ -471,9 +473,9 @@ HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num) | |||||||
| 	HashTable<Type> result = { { nullptr }, { nullptr } }; | 	HashTable<Type> result = { { nullptr }, { nullptr } }; | ||||||
|  |  | ||||||
| 	result.Hashes = array_init_reserve<ssize>(allocator, num); | 	result.Hashes = array_init_reserve<ssize>(allocator, num); | ||||||
| 	get_header(result.Hashes)->Num = num; | 	array_get_header(result.Hashes)->Num = num; | ||||||
| 	resize(& result.Hashes, num); | 	array_resize(& result.Hashes, num); | ||||||
| 	fill<ssize>(result.Hashes, 0, num, -1); | 	array_fill<ssize>(result.Hashes, 0, num, -1); | ||||||
|  |  | ||||||
| 	result.Entries = array_init_reserve<HashTableEntry<Type>>(allocator, num); | 	result.Entries = array_init_reserve<HashTableEntry<Type>>(allocator, num); | ||||||
| 	return result; | 	return result; | ||||||
| @@ -481,15 +483,15 @@ HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num) | |||||||
|  |  | ||||||
| template<typename Type> inline | template<typename Type> inline | ||||||
| void clear(HashTable<Type> table) { | void clear(HashTable<Type> table) { | ||||||
| 	clear(table.Entries); | 	array_clear(table.Entries); | ||||||
| 	fill<ssize>(table.Hashes, 0, num(table.Hashes), -1); | 	array_fill(table.Hashes, 0, array_num(table.Hashes), (ssize)-1); | ||||||
| } | } | ||||||
|  |  | ||||||
| template<typename Type> inline | template<typename Type> inline | ||||||
| void destroy(HashTable<Type>* table) { | void destroy(HashTable<Type>* table) { | ||||||
| 	if (table->Hashes && get_header(table->Hashes)->Capacity) { | 	if (table->Hashes && array_get_header(table->Hashes)->Capacity) { | ||||||
| 		free(& table->Hashes); | 		array_free(& table->Hashes); | ||||||
| 		free(& table->Entries); | 		array_free(& table->Entries); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -522,7 +524,7 @@ void map_mut(HashTable<Type> table, void (*map_proc)(u64 key, Type* value)) { | |||||||
|  |  | ||||||
| template<typename Type> inline | template<typename Type> inline | ||||||
| void grow(HashTable<Type>* table) { | void grow(HashTable<Type>* table) { | ||||||
| 	ssize new_num = array_grow_formula(num(table->Entries)); | 	ssize new_num = array_grow_formula( array_num(table->Entries)); | ||||||
| 	rehash(table, new_num); | 	rehash(table, new_num); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -530,9 +532,9 @@ template<typename Type> inline | |||||||
| void rehash(HashTable<Type>* table, ssize new_num) | void rehash(HashTable<Type>* table, ssize new_num) | ||||||
| { | { | ||||||
| 	ssize last_added_index; | 	ssize last_added_index; | ||||||
| 	HashTable<Type> new_ht = hashtable_init_reserve<Type>(get_header(table->Hashes)->Allocator, new_num); | 	HashTable<Type> new_ht = hashtable_init_reserve<Type>( array_get_header(table->Hashes)->Allocator, new_num); | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx < ssize(num(table->Entries)); ++idx) | 	for (ssize idx = 0; idx < ssize( array_num(table->Entries)); ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		HashTableFindResult find_result; | 		HashTableFindResult find_result; | ||||||
| 		HashTableEntry<Type>& entry = table->Entries[idx]; | 		HashTableEntry<Type>& entry = table->Entries[idx]; | ||||||
| @@ -639,8 +641,8 @@ ssize add_entry(HashTable<Type>* table, u64 key) { | |||||||
| 	ssize idx; | 	ssize idx; | ||||||
| 	HashTableEntry<Type> entry = { key, -1 }; | 	HashTableEntry<Type> entry = { key, -1 }; | ||||||
|  |  | ||||||
| 	idx = num(table->Entries); | 	idx = array_num(table->Entries); | ||||||
| 	append( & table->Entries, entry); | 	array_append( & table->Entries, entry); | ||||||
| 	return idx; | 	return idx; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -649,9 +651,9 @@ HashTableFindResult find(HashTable<Type> table, u64 key) | |||||||
| { | { | ||||||
| 	HashTableFindResult result = { -1, -1, -1 }; | 	HashTableFindResult result = { -1, -1, -1 }; | ||||||
|  |  | ||||||
| 	if (num(table.Hashes) > 0) | 	if (array_num(table.Hashes) > 0) | ||||||
| 	{ | 	{ | ||||||
| 		result.HashIndex = key % num(table.Hashes); | 		result.HashIndex = key % array_num(table.Hashes); | ||||||
| 		result.EntryIndex = table.Hashes[result.HashIndex]; | 		result.EntryIndex = table.Hashes[result.HashIndex]; | ||||||
|  |  | ||||||
| 		while (result.EntryIndex >= 0) | 		while (result.EntryIndex >= 0) | ||||||
| @@ -669,8 +671,8 @@ HashTableFindResult find(HashTable<Type> table, u64 key) | |||||||
|  |  | ||||||
| template<typename Type> inline | template<typename Type> inline | ||||||
| bool full(HashTable<Type> table) { | bool full(HashTable<Type> table) { | ||||||
| 	usize critical_load = usize(HashTable_CriticalLoadScale * f32(num(table.Hashes))); | 	usize critical_load = usize(HashTable_CriticalLoadScale * f32(array_num(table.Hashes))); | ||||||
| 	b32 result = num(table.Entries) > critical_load; | 	b32 result = array_num(table.Entries) > critical_load; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -56,8 +56,10 @@ | |||||||
| 	while (0) | 	while (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
| void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); | void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... ); | ||||||
| s32  assert_crash( char const* condition ); | s32  assert_crash( char const* condition ); | ||||||
| void process_exit( u32 code ); | void process_exit( u32 code ); | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Debug | #pragma endregion Debug | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, ssize* w_len_ ) | |||||||
| 	w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), w_text, scast( 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 ); | 		allocator_free( a, w_text ); | ||||||
| 		if ( w_len_ ) | 		if ( w_len_ ) | ||||||
| 			*w_len_ = 0; | 			*w_len_ = 0; | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -145,7 +145,7 @@ GEN_FILE_OPEN_PROC( _win32_file_open ) | |||||||
| 	w_text = _alloc_utf8_to_ucs2( heap(), filename, NULL ); | 	w_text = _alloc_utf8_to_ucs2( heap(), filename, NULL ); | ||||||
| 	handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL ); | 	handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL ); | ||||||
|  |  | ||||||
| 	free( heap(), w_text ); | 	allocator_free( heap(), w_text ); | ||||||
|  |  | ||||||
| 	if ( handle == INVALID_HANDLE_VALUE ) | 	if ( handle == INVALID_HANDLE_VALUE ) | ||||||
| 	{ | 	{ | ||||||
| @@ -340,7 +340,7 @@ FileError file_close( FileInfo* f ) | |||||||
| 		return EFileError_INVALID; | 		return EFileError_INVALID; | ||||||
|  |  | ||||||
| 	if ( f->filename ) | 	if ( f->filename ) | ||||||
| 		free( heap(), ccast( char*, f->filename )); | 		allocator_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 ) | ||||||
| @@ -540,7 +540,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize | |||||||
| 		mem_copy( d->buf, buffer, size ); | 		mem_copy( d->buf, buffer, size ); | ||||||
| 		d->cap = size; | 		d->cap = size; | ||||||
|  |  | ||||||
| 		get_header(arr)->Num = size; | 		array_get_header(arr)->Num = size; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -610,9 +610,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write ) | |||||||
| 	{ | 	{ | ||||||
| 		Array<u8> arr = { d->buf }; | 		Array<u8> arr = { d->buf }; | ||||||
|  |  | ||||||
| 		if ( get_header(arr)->Capacity < usize(new_cap) ) | 		if ( array_get_header(arr)->Capacity < usize(new_cap) ) | ||||||
| 		{ | 		{ | ||||||
| 			if ( ! grow( & arr, ( s64 )( new_cap ) ) ) | 			if ( ! array_grow( & arr, ( s64 )( new_cap ) ) ) | ||||||
| 				return false; | 				return false; | ||||||
| 			d->buf = arr; | 			d->buf = arr; | ||||||
| 		} | 		} | ||||||
| @@ -626,7 +626,7 @@ 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; | ||||||
| 		get_header(arr)->Capacity = new_cap; | 		array_get_header(arr)->Capacity = new_cap; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @@ -647,10 +647,10 @@ 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 }; | ||||||
| 		free(& arr); | 		array_free(& arr); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	free( allocator, d ); | 	allocator_free( allocator, d ); | ||||||
| } | } | ||||||
|  |  | ||||||
| FileOperations const memory_file_operations = { _memory_file_read, _memory_file_write, _memory_file_seek, _memory_file_close }; | FileOperations const memory_file_operations = { _memory_file_read, _memory_file_write, _memory_file_seek, _memory_file_close }; | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ 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, ssize size, s64 offset, ssize* 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, ssize size, s64 offset, ssize* bytes_written ) | #define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, mem_ptr_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 ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,11 @@ | |||||||
|  |  | ||||||
| #pragma region Hashing | #pragma region Hashing | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| u32 crc32( void const* data, ssize len ); | u32 crc32( void const* data, ssize len ); | ||||||
| u64 crc64( void const* data, ssize len ); | u64 crc64( void const* data, ssize len ); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Hashing | #pragma endregion Hashing | ||||||
|   | |||||||
| @@ -14,17 +14,12 @@ | |||||||
| #define local_persist static    // Local Persisting variables | #define local_persist static    // Local Persisting variables | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef api_c |  | ||||||
| #define api_c extern "C" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifndef bit | #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 | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
| #if ! GEN_C_COMPILER |  | ||||||
| #	ifndef cast | #	ifndef cast | ||||||
| #	define cast( type, value ) (tmpl_cast<type>( value )) | #	define cast( type, value ) (tmpl_cast<type>( value )) | ||||||
| #	endif | #	endif | ||||||
| @@ -210,9 +205,15 @@ | |||||||
| #	endif | #	endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // This is intended to only really be used internally or with the C-library variant | #ifndef GEN_API_C_BEGIN | ||||||
| // C++ users can just use the for-range directly. | #	if GEN_COMPILER_C || (GEN_COMPILER_CPP && GEN_SUPPORT_CPP_REFERENCES) | ||||||
| #define foreach(Type, entry_id, iterable) for ( Type entry_id = begin(iterable); entry_id != end(iterable); entry_id = next(iterable, entry_id) ) | #		define GEN_API_C_BEGIN | ||||||
|  | #		define GEN_API_C_END | ||||||
|  | #	else | ||||||
|  | #		define GEN_API_C_BEGIN extern "C" { | ||||||
|  | #		define GEN_API_C_END } | ||||||
|  | #	endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if GEN_COMPILER_C | #if GEN_COMPILER_C | ||||||
| #	if __STDC_VERSION__ >= 202311L | #	if __STDC_VERSION__ >= 202311L | ||||||
| @@ -230,7 +231,7 @@ | |||||||
| #	endif | #	endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if ! defined(GEN_PARAM_DEFAULT) && ! GEN_COMPILER_C | #if ! defined(GEN_PARAM_DEFAULT) && GEN_COMPILER_CPP | ||||||
| #	define GEN_PARAM_DEFAULT = {} | #	define GEN_PARAM_DEFAULT = {} | ||||||
| #else | #else | ||||||
| #	define GEN_PARAM_DEFAULT | #	define GEN_PARAM_DEFAULT | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
|  |  | ||||||
| #pragma region Memory | #pragma region Memory | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| void* mem_copy( void* dest, void const* source, ssize n ) | void* mem_copy( void* dest, void const* source, ssize n ) | ||||||
| { | { | ||||||
| 	if ( dest == NULL ) | 	if ( dest == NULL ) | ||||||
| @@ -346,7 +348,7 @@ void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ss | |||||||
| 		case EAllocation_ALLOC : | 		case EAllocation_ALLOC : | ||||||
| 			{ | 			{ | ||||||
| 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | 				void* end        = pointer_add( arena->PhysicalStart, arena->TotalUsed ); | ||||||
| 				ssize    total_size = align_forward_i64( size, alignment ); | 				ssize total_size = align_forward_s64( size, alignment ); | ||||||
|  |  | ||||||
| 				// NOTE: Out of memory | 				// NOTE: Out of memory | ||||||
| 				if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize ) | 				if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize ) | ||||||
| @@ -495,16 +497,16 @@ Pool pool_init_align( AllocatorInfo backing, ssize num_blocks, ssize block_size, | |||||||
| 	return pool; | 	return pool; | ||||||
| } | } | ||||||
|  |  | ||||||
| void clear(Pool& pool) | void pool_clear(Pool* pool) | ||||||
| { | { | ||||||
| 	ssize actual_block_size, block_index; | 	ssize actual_block_size, block_index; | ||||||
| 	void* curr; | 	void* curr; | ||||||
| 	uptr* end; | 	uptr* end; | ||||||
|  |  | ||||||
| 	actual_block_size = pool.BlockSize + pool.BlockAlign; | 	actual_block_size = pool->BlockSize + pool->BlockAlign; | ||||||
|  |  | ||||||
| 	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 = ( uptr* ) curr; | 		uptr* next = ( uptr* ) curr; | ||||||
| 		*next      = ( uptr  ) curr + actual_block_size; | 		*next      = ( uptr  ) curr + actual_block_size; | ||||||
| @@ -514,7 +516,9 @@ void clear(Pool& pool) | |||||||
| 	end  =  ( uptr* ) curr; | 	end  =  ( uptr* ) curr; | ||||||
| 	*end =  ( uptr )  NULL; | 	*end =  ( uptr )  NULL; | ||||||
|  |  | ||||||
| 	pool.FreeList = pool.PhysicalStart; | 	pool->FreeList = pool->PhysicalStart; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Memory | #pragma endregion Memory | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ void swap( Type& a, Type& b ) | |||||||
| 	b = tmp; | 	b = tmp; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| //! Checks if value is power of 2. | //! Checks if value is power of 2. | ||||||
| b32 is_power_of_two( ssize x ); | b32 is_power_of_two( ssize x ); | ||||||
|  |  | ||||||
| @@ -29,7 +31,7 @@ b32 is_power_of_two( ssize x ); | |||||||
| void* align_forward( void* ptr, ssize alignment ); | void* align_forward( void* ptr, ssize alignment ); | ||||||
|  |  | ||||||
| //! Aligns value to a specified alignment. | //! Aligns value to a specified alignment. | ||||||
| s64 align_forward_i64( s64 value, ssize alignment ); | s64 align_forward_by_value( s64 value, ssize alignment ); | ||||||
|  |  | ||||||
| //! Moves pointer forward by bytes. | //! Moves pointer forward by bytes. | ||||||
| void* pointer_add( void* ptr, ssize bytes ); | void* pointer_add( void* ptr, ssize bytes ); | ||||||
| @@ -100,7 +102,7 @@ void* alloc( AllocatorInfo a, ssize size ); | |||||||
| void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ); | void* alloc_align( AllocatorInfo a, ssize size, ssize alignment ); | ||||||
|  |  | ||||||
| //! Free allocated memory. | //! Free allocated memory. | ||||||
| void free( AllocatorInfo a, void* ptr ); | void allocator_free( AllocatorInfo a, void* ptr ); | ||||||
|  |  | ||||||
| //! Free all memory allocated by an allocator. | //! Free all memory allocated by an allocator. | ||||||
| void free_all( AllocatorInfo a ); | void free_all( AllocatorInfo a ); | ||||||
| @@ -142,11 +144,12 @@ constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocato | |||||||
| //! 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 ) | ||||||
|  |  | ||||||
| struct VirtualMemory | struct VirtualMemory_Def | ||||||
| { | { | ||||||
| 	void*  data; | 	void*  data; | ||||||
| 	ssize size; | 	ssize size; | ||||||
| }; | }; | ||||||
|  | typedef struct VirtualMemory_Def VirtualMemory; | ||||||
|  |  | ||||||
| //! Initialize virtual memory from existing data. | //! Initialize virtual memory from existing data. | ||||||
| VirtualMemory vm_from_memory( void* data, ssize size ); | VirtualMemory vm_from_memory( void* data, ssize size ); | ||||||
| @@ -164,15 +167,16 @@ b32 vm_free( VirtualMemory vm ); | |||||||
| VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ); | VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size ); | ||||||
|  |  | ||||||
| //! Purge virtual memory. | //! Purge virtual memory. | ||||||
| b32 gen_vm_purge( VirtualMemory vm ); | b32 vm_purge( VirtualMemory vm ); | ||||||
|  |  | ||||||
| //! Retrieve VM's page size and alignment. | //! Retrieve VM's page size and alignment. | ||||||
| ssize gen_virtual_memory_page_size( ssize* alignment_out ); | ssize virtual_memory_page_size( ssize* alignment_out ); | ||||||
|  |  | ||||||
| #pragma region Arena | #pragma region Arena | ||||||
| struct Arena; | struct Arena_Def; | ||||||
|  | typedef struct Arena_Def Arena; | ||||||
|  |  | ||||||
| AllocatorInfo allocator_info( Arena* arena ); | AllocatorInfo arena_allocator_info( Arena* arena ); | ||||||
|  |  | ||||||
| // Remove static keyword and rename allocator_proc | // 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); | void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags); | ||||||
| @@ -181,18 +185,13 @@ void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssi | |||||||
| Arena arena_init_from_allocator(AllocatorInfo backing, ssize size); | Arena arena_init_from_allocator(AllocatorInfo backing, ssize size); | ||||||
| Arena arena_init_from_memory   ( void* start, ssize size ); | Arena arena_init_from_memory   ( void* start, ssize size ); | ||||||
|  |  | ||||||
| Arena init_sub      (Arena* parent, ssize size); | Arena arena_init_sub      (Arena* parent, ssize size); | ||||||
| ssize alignment_of  (Arena* arena, ssize alignment); | ssize arena_alignment_of  (Arena* arena, ssize alignment); | ||||||
| void  free          (Arena* arena); | void  arena_check         (Arena* arena); | ||||||
| ssize size_remaining(Arena* arena, ssize alignment); | void  arena_free          (Arena* arena); | ||||||
|  | ssize arena_size_remaining(Arena* arena, ssize alignment); | ||||||
|  |  | ||||||
| // This id is defined by Unreal for asserts | struct Arena_Def | ||||||
| #pragma push_macro("check") |  | ||||||
| #undef check |  | ||||||
| void   check(Arena* arena); |  | ||||||
| #pragma pop_macro("check") |  | ||||||
|  |  | ||||||
| struct Arena |  | ||||||
| { | { | ||||||
| 	AllocatorInfo Backing; | 	AllocatorInfo Backing; | ||||||
| 	void*         PhysicalStart; | 	void*         PhysicalStart; | ||||||
| @@ -202,20 +201,20 @@ struct Arena | |||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_MEMBER_FEATURES | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| #pragma region Member Mapping | #pragma region Member Mapping | ||||||
| 	forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); } | 	forceinline operator AllocatorInfo() { return GEN_NS arena_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 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_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_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 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        ssize alignment_of( ssize alignment )                                                                                                  { return GEN_NS arena_alignment_of(this, alignment); } | ||||||
| 	forceinline        void  free()                                                                                                                           { return GEN_NS free(this);  } | 	forceinline        void  free()                                                                                                                           { return GEN_NS arena_free(this);  } | ||||||
| 	forceinline        ssize size_remaining( ssize alignment )                                                                                                { return GEN_NS size_remaining(this, alignment); } | 	forceinline        ssize size_remaining( ssize alignment )                                                                                                { return GEN_NS arena_size_remaining(this, alignment); } | ||||||
|  |  | ||||||
| // This id is defined by Unreal for asserts | // This id is defined by Unreal for asserts | ||||||
| #pragma push_macro("check") | #pragma push_macro("check") | ||||||
| #undef check | #undef check | ||||||
| 	forceinline void check() { GEN_NS check(this); } | 	forceinline void check() { GEN_NS arena_check(this); } | ||||||
| #pragma pop_macro("check") | #pragma pop_macro("check") | ||||||
|  |  | ||||||
| #pragma endregion Member Mapping | #pragma endregion Member Mapping | ||||||
| @@ -223,24 +222,27 @@ struct Arena | |||||||
| }; | }; | ||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_REFERENCES | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
| forceinline AllocatorInfo allocator_info(Arena& arena )                 { return allocator_info(& arena); } | GEN_API_C_END | ||||||
| forceinline Arena         init_sub      (Arena& parent, ssize size)     { return init_sub( & parent, size); } | forceinline AllocatorInfo allocator_info(Arena& arena )                 { return arena_allocator_info(& arena); } | ||||||
| forceinline ssize         alignment_of  (Arena& arena, ssize alignment) { return alignment_of( & arena, alignment); } | forceinline Arena         init_sub      (Arena& parent, ssize size)     { return arena_init_sub( & parent, size); } | ||||||
| forceinline void          free          (Arena& arena)                  { return free(& arena); } | forceinline ssize         alignment_of  (Arena& arena, ssize alignment) { return arena_alignment_of( & arena, alignment); } | ||||||
| forceinline ssize         size_remaining(Arena& arena, ssize alignment) { return size_remaining(& arena, alignment); } | forceinline void          free          (Arena& arena)                  { return arena_free(& arena); } | ||||||
|  | forceinline ssize         size_remaining(Arena& arena, ssize alignment) { return arena_size_remaining(& arena, alignment); } | ||||||
|  |  | ||||||
| // This id is defined by Unreal for asserts | // This id is defined by Unreal for asserts | ||||||
| #pragma push_macro("check") | #pragma push_macro("check") | ||||||
| #undef check | #undef check | ||||||
| forceinline void check(Arena& arena) { return check(& arena); }; | forceinline void check(Arena& arena) { return arena_check(& arena); }; | ||||||
| #pragma pop_macro("check") | #pragma pop_macro("check") | ||||||
|  | GEN_API_C_BEGIN | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| inline | inline | ||||||
| AllocatorInfo allocator_info( Arena* arena ) { | AllocatorInfo arena_allocator_info( Arena* arena ) { | ||||||
| 	GEN_ASSERT(arena != nullptr); | 	GEN_ASSERT(arena != nullptr); | ||||||
| 	return { arena_allocator_proc, arena }; | 	AllocatorInfo info = { arena_allocator_proc, arena }; | ||||||
|  | 	return info; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| @@ -269,13 +271,13 @@ Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| Arena init_sub(Arena* parent, ssize size) { | Arena arena_init_sub(Arena* parent, ssize size) { | ||||||
| 	GEN_ASSERT(parent != nullptr); | 	GEN_ASSERT(parent != nullptr); | ||||||
| 	return arena_init_from_allocator(parent->Backing, size); | 	return arena_init_from_allocator(parent->Backing, size); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| ssize alignment_of(Arena* arena, ssize alignment) | ssize arena_alignment_of(Arena* arena, ssize alignment) | ||||||
| { | { | ||||||
| 	GEN_ASSERT(arena != nullptr); | 	GEN_ASSERT(arena != nullptr); | ||||||
| 	ssize alignment_offset, result_pointer, mask; | 	ssize alignment_offset, result_pointer, mask; | ||||||
| @@ -291,36 +293,37 @@ ssize alignment_of(Arena* arena, ssize alignment) | |||||||
| 	return alignment_offset; | 	return alignment_offset; | ||||||
| } | } | ||||||
|  |  | ||||||
| #pragma push_macro("check") |  | ||||||
| #undef check |  | ||||||
| inline | inline | ||||||
| void check(Arena* arena) | void arena_check(Arena* arena) | ||||||
| { | { | ||||||
|     GEN_ASSERT(arena != nullptr ); |     GEN_ASSERT(arena != nullptr ); | ||||||
|     GEN_ASSERT(arena->TempCount == 0); |     GEN_ASSERT(arena->TempCount == 0); | ||||||
| } | } | ||||||
| #pragma pop_macro("check") |  | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void free(Arena* arena) | void arena_free(Arena* arena) | ||||||
| { | { | ||||||
| 	GEN_ASSERT(arena != nullptr); | 	GEN_ASSERT(arena != nullptr); | ||||||
| 	if (arena->Backing.Proc) | 	if (arena->Backing.Proc) | ||||||
| 	{ | 	{ | ||||||
| 		GEN_NS free(arena->Backing, arena->PhysicalStart); | 		allocator_free(arena->Backing, arena->PhysicalStart); | ||||||
| 		arena->PhysicalStart = nullptr; | 		arena->PhysicalStart = nullptr; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| ssize size_remaining(Arena* arena, ssize alignment) | ssize arena_size_remaining(Arena* arena, ssize alignment) | ||||||
| { | { | ||||||
| 	GEN_ASSERT(arena != nullptr); | 	GEN_ASSERT(arena != nullptr); | ||||||
| 	ssize result = arena->TotalSize - (arena->TotalUsed + alignment_of(arena, alignment)); | 	ssize result = arena->TotalSize - (arena->TotalUsed + arena_alignment_of(arena, alignment)); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| #pragma endregion Arena | #pragma endregion Arena | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  |  | ||||||
| #pragma region FixedArena | #pragma region FixedArena | ||||||
| template<s32 Size> | template<s32 Size> | ||||||
| struct FixedArena; | struct FixedArena; | ||||||
| @@ -383,24 +386,31 @@ using Arena_2MB   = FixedArena< megabytes( 2 ) >; | |||||||
| using Arena_4MB   = FixedArena< megabytes( 4 ) >; | using Arena_4MB   = FixedArena< megabytes( 4 ) >; | ||||||
| #pragma endregion FixedArena | #pragma endregion FixedArena | ||||||
|  |  | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  |  | ||||||
| #pragma region Pool | #pragma region Pool | ||||||
| struct Pool; | struct Pool_Def; | ||||||
|  | typedef struct Pool_Def Pool; | ||||||
|  |  | ||||||
| void* pool_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize 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_init(AllocatorInfo backing, ssize num_blocks, ssize block_size); | 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); | Pool          pool_init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align); | ||||||
| AllocatorInfo allocator_info(Pool* pool); | AllocatorInfo pool_allocator_info(Pool* pool); | ||||||
| void          clear(Pool* pool); | void          pool_clear(Pool* pool); | ||||||
| void          free(Pool* pool); | void          pool_free(Pool* pool); | ||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_REFERENCES | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
| AllocatorInfo allocator_info(Pool& pool); | GEN_API_C_END | ||||||
| void          clear(Pool& pool); | AllocatorInfo allocator_info(Pool& pool) { return pool_allocator_info(& pool); } | ||||||
| void          free(Pool& pool); | void          clear(Pool& pool)          { return pool_clear(& pool); } | ||||||
|  | void          free(Pool& pool)           { return pool_free(& pool); } | ||||||
|  | GEN_API_C_BEGIN | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| struct Pool | struct Pool_Def | ||||||
| { | { | ||||||
| 	AllocatorInfo Backing; | 	AllocatorInfo Backing; | ||||||
| 	void*         PhysicalStart; | 	void*         PhysicalStart; | ||||||
| @@ -412,19 +422,19 @@ struct Pool | |||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_MEMBER_FEATURES | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| #pragma region Member Mapping | #pragma region Member Mapping | ||||||
|     forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); } |     forceinline operator AllocatorInfo() { return GEN_NS pool_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 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(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 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  clear() { GEN_NS pool_clear( this); } | ||||||
|     forceinline        void  free()  { GEN_NS free( this); } |     forceinline        void  free()  { GEN_NS pool_free( this); } | ||||||
| #pragma endregion | #pragma endregion | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline | inline | ||||||
| AllocatorInfo allocator_info(Pool* pool) { | AllocatorInfo pool_allocator_info(Pool* pool) { | ||||||
|    return { pool_allocator_proc, pool }; |    return { pool_allocator_proc, pool }; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -434,9 +444,9 @@ Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void free(Pool* pool) { | void pool_free(Pool* pool) { | ||||||
|    if(pool->Backing.Proc) { |    if(pool->Backing.Proc) { | ||||||
|        GEN_NS free(pool->Backing, pool->PhysicalStart); |        allocator_free(pool->Backing, pool->PhysicalStart); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| #pragma endregion Pool | #pragma endregion Pool | ||||||
| @@ -458,7 +468,7 @@ mem_ptr align_forward( void* ptr, ssize alignment ) | |||||||
| 	return to_mem_ptr(forward); | 	return to_mem_ptr(forward); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline s64 align_forward_i64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; } | inline s64 align_forward_s64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; } | ||||||
|  |  | ||||||
| inline void*       pointer_add      ( void*       ptr, ssize bytes ) { return rcast(void*,         rcast( u8*,        ptr) + bytes ); } | 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 void const* pointer_add_const( void const* ptr, ssize bytes ) { return rcast(void const*, rcast( u8 const*,  ptr) + bytes ); } | ||||||
| @@ -616,7 +626,7 @@ void* alloc( AllocatorInfo a, ssize size ) { | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| void free( AllocatorInfo a, void* ptr ) { | void allocator_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 ); | ||||||
| } | } | ||||||
| @@ -644,7 +654,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s | |||||||
|  |  | ||||||
| 	if ( new_size == 0 ) | 	if ( new_size == 0 ) | ||||||
| 	{ | 	{ | ||||||
| 		free( a, old_memory ); | 		allocator_free( a, old_memory ); | ||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -662,7 +672,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s | |||||||
| 			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 ); | 		allocator_free( a, old_memory ); | ||||||
| 		return new_memory; | 		return new_memory; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -672,4 +682,6 @@ void zero_size( void* ptr, ssize size ) { | |||||||
| 	mem_set( ptr, 0, size ); | 	mem_set( ptr, 0, size ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Memory | #pragma endregion 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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); ++i ) | 		for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); ++i ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_destroy_branch( node->nodes + i ); | 			adt_destroy_branch( node->nodes + i ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		free(& node->nodes); | 		array_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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | 	for ( ssize i = 0; i < scast(ssize, array_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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | 		for ( ssize i = 0; i < scast(ssize, array_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 ); | ||||||
|  |  | ||||||
| @@ -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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | 	for ( ssize i = 0; i < scast(ssize, array_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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | 				for ( ssize i = 0; i < scast(ssize, array_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 ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ ) | 			for ( ssize i = 0; i < scast(ssize, array_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 ) ) | ||||||
| @@ -257,7 +257,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri ) | |||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); | 		ssize idx = ( ssize )str_to_i64( buf, NULL, 10 ); | ||||||
| 		if ( idx >= 0 && idx < scast(ssize, num(node->nodes)) ) | 		if ( idx >= 0 && idx < scast(ssize, array_num(node->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			found_node = &node->nodes[ idx ]; | 			found_node = &node->nodes[ idx ]; | ||||||
|  |  | ||||||
| @@ -282,12 +282,12 @@ ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	if ( index < 0 || index > scast(ssize, num(parent->nodes)) ) | 	if ( index < 0 || index > scast(ssize, array_num(parent->nodes)) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	ADT_Node o = { 0 }; | 	ADT_Node o = { 0 }; | ||||||
| 	o.parent   = parent; | 	o.parent   = parent; | ||||||
| 	if ( ! append_at( & parent->nodes, o, index ) ) | 	if ( ! array_append_at( & parent->nodes, o, index ) ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	ADT_Node* node = & parent->nodes[index]; | 	ADT_Node* node = & parent->nodes[index]; | ||||||
| @@ -304,7 +304,7 @@ ADT_Node* adt_alloc( ADT_Node* parent ) | |||||||
| 	if ( ! parent->nodes ) | 	if ( ! parent->nodes ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	return adt_alloc_at( parent, num(parent->nodes) ); | 	return adt_alloc_at( parent, array_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 ) | ||||||
| @@ -358,7 +358,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, num(new_parent->nodes) ); | 	return adt_move_node_at( node, new_parent, array_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 ) | ||||||
| @@ -382,7 +382,7 @@ void adt_remove_node( ADT_Node* node ) | |||||||
| 	GEN_ASSERT_NOT_NULL( node->parent ); | 	GEN_ASSERT_NOT_NULL( node->parent ); | ||||||
| 	ADT_Node* parent = node->parent; | 	ADT_Node* parent = node->parent; | ||||||
| 	ssize        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | 	ssize        index  = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) ); | ||||||
| 	remove_at( parent->nodes, index ); | 	array_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 ) | ||||||
| @@ -390,7 +390,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, get_header(parent->nodes)->Allocator ) ) | 	if ( adt_set_obj( o, name, array_get_header(parent->nodes)->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| @@ -404,7 +404,7 @@ ADT_Node* adt_append_arr( ADT_Node* parent, char const* name ) | |||||||
| 	if ( ! o ) | 	if ( ! o ) | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
| 	ArrayHeader* node_header = get_header(parent->nodes); | 	ArrayHeader* node_header = array_get_header(parent->nodes); | ||||||
| 	if ( adt_set_arr( o, name, node_header->Allocator ) ) | 	if ( adt_set_arr( o, name, node_header->Allocator ) ) | ||||||
| 	{ | 	{ | ||||||
| 		adt_remove_node( o ); | 		adt_remove_node( o ); | ||||||
| @@ -510,7 +510,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str ) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		if ( ! str_compare( e, "0x", 2 ) || ! str_compare( e, "0X", 2 ) ) | 		if ( ! str_compare_len( e, "0x", 2 ) || ! str_compare_len( e, "0X", 2 ) ) | ||||||
| 		{ | 		{ | ||||||
| 			node_props = EADT_PROPS_IS_HEX; | 			node_props = EADT_PROPS_IS_HEX; | ||||||
| 		} | 		} | ||||||
| @@ -949,12 +949,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ( columnIndex >= scast(ssize, num(root->nodes)) ) | 		if ( columnIndex >= scast(ssize, array_num(root->nodes)) ) | ||||||
| 		{ | 		{ | ||||||
| 			adt_append_arr( root, NULL ); | 			adt_append_arr( root, NULL ); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		append( & root->nodes[ columnIndex ].nodes, rowItem ); | 		array_append( & root->nodes[ columnIndex ].nodes, rowItem ); | ||||||
|  |  | ||||||
| 		if ( delimiter == delim ) | 		if ( delimiter == delim ) | ||||||
| 		{ | 		{ | ||||||
| @@ -982,7 +982,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b | |||||||
| 	} | 	} | ||||||
| 	while ( *currentChar ); | 	while ( *currentChar ); | ||||||
|  |  | ||||||
| 	if (num( root->nodes) == 0 ) | 	if (array_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; | ||||||
| @@ -992,12 +992,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 ( ssize i = 0; i < scast(ssize, num(root->nodes)); i++ ) | 		for ( ssize i = 0; i < scast(ssize, array_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; | ||||||
| 			remove_at(col->nodes, 0 ); | 			array_remove_at(col->nodes, 0 ); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -1060,11 +1060,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 ); | ||||||
| 	ssize cols = num(obj->nodes); | 	ssize cols = array_num(obj->nodes); | ||||||
| 	if ( cols == 0 ) | 	if ( cols == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	ssize rows = num(obj->nodes[ 0 ].nodes); | 	ssize rows = array_num(obj->nodes[ 0 ].nodes); | ||||||
| 	if ( rows == 0 ) | 	if ( rows == 0 ) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -106,13 +106,25 @@ | |||||||
| #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | #  define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef GEN_COMPILER_C | #if !defined(GEN_COMPILER_C) | ||||||
| #	if defined(__STDC_VERSION__) | #	ifdef __cplusplus | ||||||
| #		define GEN_COMPILER_C 1 |  | ||||||
| #	else |  | ||||||
| #		define GEN_COMPILER_C   0 | #		define GEN_COMPILER_C   0 | ||||||
|  | #		define GEN_COMPILER_CPP 1 | ||||||
|  | #	else | ||||||
|  | #		if defined(__STDC__) | ||||||
|  | #			define GEN_COMPILER_C   1 | ||||||
|  | #		    define GEN_COMPILER_CPP 0 | ||||||
|  | #		else | ||||||
|  |             // Fallback for very old C compilers | ||||||
|  | #			define GEN_COMPILER_C   1 | ||||||
|  | #		    define GEN_COMPILER_CPP 0 | ||||||
| #		endif | #		endif | ||||||
| #   endif | #   endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_C | ||||||
|  | #pragma message("Detected C") | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #pragma endregion Platform Detection | #pragma endregion Platform Detection | ||||||
|  |  | ||||||
| @@ -136,8 +148,6 @@ | |||||||
| #		define GEN_NS_PARSER_BEGIN | #		define GEN_NS_PARSER_BEGIN | ||||||
| #		define GEN_NS_PARSER_END | #		define GEN_NS_PARSER_END | ||||||
| #		define GEN_USING_NS_PARSER | #		define GEN_USING_NS_PARSER | ||||||
| #		define GEN_NS_ENUM_BEGIN |  | ||||||
| #		define GEN_NS_ENUM_END |  | ||||||
| #		define GEN_NS | #		define GEN_NS | ||||||
| #		define GEN_NS_BEGIN | #		define GEN_NS_BEGIN | ||||||
| #		define GEN_NS_END | #		define GEN_NS_END | ||||||
| @@ -145,8 +155,6 @@ | |||||||
| #		define GEN_NS_PARSER_BEGIN namespace parser { | #		define GEN_NS_PARSER_BEGIN namespace parser { | ||||||
| #		define GEN_NS_PARSER_END   } | #		define GEN_NS_PARSER_END   } | ||||||
| #		define GEN_USING_NS_PARSER using namespace parser | #		define GEN_USING_NS_PARSER using namespace parser | ||||||
| #		define GEN_NS_ENUM_BEGIN namespace gen_internal_enums { |  | ||||||
| #		define GEN_NS_ENUM_END   } |  | ||||||
| #		define GEN_NS       :: | #		define GEN_NS       :: | ||||||
| #		define GEN_NS_BEGIN | #		define GEN_NS_BEGIN | ||||||
| #		define GEN_NS_END | #		define GEN_NS_END | ||||||
| @@ -155,8 +163,6 @@ | |||||||
| #	define GEN_NS_PARSER_BEGIN namespace parser { | #	define GEN_NS_PARSER_BEGIN namespace parser { | ||||||
| #	define GEN_NS_PARSER_END   } | #	define GEN_NS_PARSER_END   } | ||||||
| #	define GEN_USING_NS_PARSER using namespace parser | #	define GEN_USING_NS_PARSER using namespace parser | ||||||
| #	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   } | ||||||
|   | |||||||
| @@ -431,7 +431,7 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis | |||||||
|  |  | ||||||
| 				String gen_str = String { va_arg( va, char*) }; | 				String gen_str = String { va_arg( va, char*) }; | ||||||
|  |  | ||||||
| 				info.precision = length(gen_str); | 				info.precision = string_length(gen_str); | ||||||
| 				len            = _print_string( text, remaining, &info, gen_str ); | 				len            = _print_string( text, remaining, &info, gen_str ); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
|  |  | ||||||
| #pragma region Printing | #pragma region Printing | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| struct FileInfo; | struct FileInfo; | ||||||
|  |  | ||||||
| #ifndef GEN_PRINTF_MAXLEN | #ifndef GEN_PRINTF_MAXLEN | ||||||
| @@ -38,4 +40,6 @@ ssize log_fmt(char const* fmt, ...) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion Printing | #pragma endregion Printing | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ ssize _scan_zpl_i64( const char* text, s32 base, s64* value ) | |||||||
| 		text++; | 		text++; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ( base == 16 && str_compare( text, "0x", 2 ) == 0 ) | 	if ( base == 16 && str_compare_len( text, "0x", 2 ) == 0 ) | ||||||
| 		text += 2; | 		text += 2; | ||||||
|  |  | ||||||
| 	for ( ;; ) | 	for ( ;; ) | ||||||
| @@ -61,7 +61,7 @@ s64 str_to_i64( const char* str, char** end_ptr, s32 base ) | |||||||
|  |  | ||||||
| 	if ( ! base ) | 	if ( ! base ) | ||||||
| 	{ | 	{ | ||||||
| 		if ( ( str_len( str ) > 2 ) && ( str_compare( str, "0x", 2 ) == 0 ) ) | 		if ( ( str_len( str ) > 2 ) && ( str_compare_len( str, "0x", 2 ) == 0 ) ) | ||||||
| 			base = 16; | 			base = 16; | ||||||
| 		else | 		else | ||||||
| 			base = 10; | 			base = 10; | ||||||
|   | |||||||
| @@ -5,6 +5,8 @@ | |||||||
|  |  | ||||||
| #pragma region String Ops | #pragma region String Ops | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| const char* char_first_occurence( const char* str, char c ); | const char* char_first_occurence( const char* str, char c ); | ||||||
|  |  | ||||||
| b32   char_is_alpha( char c ); | b32   char_is_alpha( char c ); | ||||||
| @@ -19,11 +21,11 @@ s32  digit_to_int( char c ); | |||||||
| s32  hex_digit_to_int( char c ); | s32  hex_digit_to_int( char c ); | ||||||
|  |  | ||||||
| s32         str_compare( const char* s1, const char* s2 ); | s32         str_compare( const char* s1, const char* s2 ); | ||||||
| s32         str_compare( const char* s1, const char* s2, ssize len ); | s32         str_compare_len( const char* s1, const char* s2, ssize len ); | ||||||
| char*       str_copy( char* dest, const char* source, ssize len ); | char*       str_copy( char* dest, const char* source, ssize len ); | ||||||
| ssize       str_copy_nulpad( char* dest, const char* source, ssize len ); | ssize       str_copy_nulpad( char* dest, const char* source, ssize len ); | ||||||
| ssize       str_len( const char* str ); | ssize       str_len( const char* str ); | ||||||
| ssize       str_len( const char* str, ssize max_len ); | ssize       str_len_capped( const char* str, ssize max_len ); | ||||||
| char*       str_reverse( char* str );    // NOTE: ASCII only | char*       str_reverse( char* str );    // NOTE: ASCII only | ||||||
| char const* str_skip( char const* str, char c ); | char const* str_skip( char const* str, char c ); | ||||||
| char const* str_skip_any( char const* str, char const* char_list ); | char const* str_skip_any( char const* str, char const* char_list ); | ||||||
| @@ -132,7 +134,7 @@ s32 str_compare( const char* s1, const char* s2 ) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| s32 str_compare( const char* s1, const char* s2, ssize len ) | s32 str_compare_len( const char* s1, const char* s2, ssize len ) | ||||||
| { | { | ||||||
| 	for ( ; len > 0; s1++, s2++, len-- ) | 	for ( ; len > 0; s1++, s2++, len-- ) | ||||||
| 	{ | 	{ | ||||||
| @@ -204,7 +206,7 @@ ssize str_len( const char* str ) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| ssize str_len( const char* str, ssize max_len ) | ssize str_len_capped( const char* str, ssize max_len ) | ||||||
| { | { | ||||||
| 	const char* end = rcast(const char*, mem_find( str, 0, max_len )); | 	const char* end = rcast(const char*, mem_find( str, 0, max_len )); | ||||||
| 	if ( end ) | 	if ( end ) | ||||||
| @@ -240,7 +242,7 @@ char const* str_skip( char const* str, char c ) | |||||||
| inline | 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 ) | ||||||
| { | { | ||||||
| 	char const* closest_ptr     = rcast( char const*, pointer_add_const( rcast(void const*, str), str_len( str ) )); | 	char const* closest_ptr     = rcast( char const*, pointer_add_const( rcast(mem_ptr_const, str), str_len( str ) )); | ||||||
| 	ssize       char_list_count = str_len( char_list ); | 	ssize       char_list_count = str_len( char_list ); | ||||||
| 	for ( ssize i = 0; i < char_list_count; i++ ) | 	for ( ssize i = 0; i < char_list_count; i++ ) | ||||||
| 	{ | 	{ | ||||||
| @@ -284,4 +286,6 @@ void str_to_upper( char* str ) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #pragma endregion String Ops | #pragma endregion String Ops | ||||||
|   | |||||||
| @@ -5,15 +5,19 @@ | |||||||
|  |  | ||||||
| #pragma region Strings | #pragma region Strings | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| struct StrC; | struct StrC; | ||||||
|  |  | ||||||
| bool        are_equal           (StrC lhs, StrC rhs); | bool        strc_are_equal           (StrC lhs, StrC rhs); | ||||||
| char const* back                (StrC str); | char const* strc_back                (StrC str); | ||||||
| bool        contains            (StrC str, StrC substring); | bool        strc_contains            (StrC str, StrC substring); | ||||||
| StrC        duplicate           (StrC str, AllocatorInfo allocator); | StrC        strc_duplicate           (StrC str, AllocatorInfo allocator); | ||||||
| b32         starts_with         (StrC str, StrC substring); | b32         strc_starts_with         (StrC str, StrC substring); | ||||||
| StrC        to_str              (char const* bad_string); | StrC        strc_to_str              (char const* bad_string); | ||||||
| StrC        visualize_whitespace(StrC str, AllocatorInfo allocator); | StrC        strc_visualize_whitespace(StrC str, AllocatorInfo allocator); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| // Constant string with length. | // Constant string with length. | ||||||
| struct StrC | struct StrC | ||||||
| @@ -21,17 +25,17 @@ struct StrC | |||||||
| 	ssize       Len; | 	ssize       Len; | ||||||
| 	char const* Ptr; | 	char const* Ptr; | ||||||
|  |  | ||||||
| #if ! GEN_COMPILER_C | #if GEN_COMPILER_CPP | ||||||
| 	operator char const* ()               const { return Ptr; } | 	forceinline operator char const* ()               const { return Ptr; } | ||||||
| 	char const& operator[]( ssize index ) const { return Ptr[index]; } | 	forceinline char const& operator[]( ssize index ) const { return Ptr[index]; } | ||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_MEMBER_FEATURES | #if GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| 	bool        is_equal            (StrC rhs)                const { return GEN_NS are_equal(* this, rhs); } | 	forceinline bool        is_equal            (StrC rhs)                const { return GEN_NS strc_are_equal(* this, rhs); } | ||||||
| 	char const* back                ()                        const { return GEN_NS back(* this); } | 	forceinline char const* back                ()                        const { return GEN_NS strc_back(* this); } | ||||||
| 	bool        contains            (StrC substring)          const { return GEN_NS contains(* this, substring); } | 	forceinline bool        contains            (StrC substring)          const { return GEN_NS strc_contains(* this, substring); } | ||||||
| 	StrC        duplicate           (AllocatorInfo allocator) const { return GEN_NS duplicate(* this, allocator); } | 	forceinline StrC        duplicate           (AllocatorInfo allocator) const { return GEN_NS strc_duplicate(* this, allocator); } | ||||||
| 	b32         starts_with         (StrC substring)          const { return GEN_NS starts_with(* this, substring); } | 	forceinline b32         starts_with         (StrC substring)          const { return GEN_NS strc_starts_with(* this, substring); } | ||||||
| 	StrC        visualize_whitespace(AllocatorInfo allocator) const { return GEN_NS visualize_whitespace(* this, allocator); } | 	forceinline StrC        visualize_whitespace(AllocatorInfo allocator) const { return GEN_NS strc_visualize_whitespace(* this, allocator); } | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| @@ -39,12 +43,22 @@ struct StrC | |||||||
| #define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) ) | #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 ) } | ||||||
|  |  | ||||||
| inline char const* begin(StrC str)                   { return str.Ptr; } | GEN_API_C_BEGIN | ||||||
| inline char const* end  (StrC str)                   { return str.Ptr + str.Len; } | forceinline char const* strc_begin(StrC str)                   { return str.Ptr; } | ||||||
| inline char const* next (StrC str, char const* iter) { return iter + 1; } | forceinline char const* strc_end  (StrC str)                   { return str.Ptr + str.Len; } | ||||||
|  | forceinline char const* strc_next (StrC str, char const* iter) { return iter + 1; } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
|  | #if GEN_COMPILER_CPP | ||||||
|  | forceinline char const* begin(StrC str)                   { return str.Ptr; } | ||||||
|  | forceinline char const* end  (StrC str)                   { return str.Ptr + str.Len; } | ||||||
|  | forceinline char const* next (StrC str, char const* iter) { return iter + 1; } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool are_equal(StrC lhs, StrC rhs) | bool strc_are_equal(StrC lhs, StrC rhs) | ||||||
| { | { | ||||||
| 	if (lhs.Len != rhs.Len) | 	if (lhs.Len != rhs.Len) | ||||||
| 		return false; | 		return false; | ||||||
| @@ -57,12 +71,12 @@ bool are_equal(StrC lhs, StrC rhs) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| char const* back(StrC str) { | char const* strc_back(StrC str) { | ||||||
| 	return & str.Ptr[str.Len - 1]; | 	return & str.Ptr[str.Len - 1]; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool contains(StrC str, StrC substring) | bool strc_contains(StrC str, StrC substring) | ||||||
| { | { | ||||||
| 	if (substring.Len > str.Len) | 	if (substring.Len > str.Len) | ||||||
| 		return false; | 		return false; | ||||||
| @@ -71,25 +85,26 @@ bool contains(StrC str, StrC substring) | |||||||
| 	ssize sub_len  = substring.Len; | 	ssize sub_len  = substring.Len; | ||||||
| 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		if (str_compare(str.Ptr + idx, substring.Ptr, sub_len) == 0) | 		if (str_compare_len(str.Ptr + idx, substring.Ptr, sub_len) == 0) | ||||||
| 			return true; | 			return true; | ||||||
| 	} | 	} | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| b32 starts_with(StrC str, StrC substring) { | b32 strc_starts_with(StrC str, StrC substring) { | ||||||
| 	if (substring.Len > str.Len) | 	if (substring.Len > str.Len) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	b32 result = str_compare(str.Ptr, substring.Ptr, substring.Len) == 0; | 	b32 result = str_compare_len(str.Ptr, substring.Ptr, substring.Len) == 0; | ||||||
| 		return result; | 		return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| StrC to_str( char const* bad_str ) { | StrC to_strc_from_c_str( char const* bad_str ) { | ||||||
| 	return { str_len( bad_str ), bad_str }; | 	return { str_len( bad_str ), bad_str }; | ||||||
| } | } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| // Dynamic String | // Dynamic String | ||||||
| // This is directly based off the ZPL string api. | // This is directly based off the ZPL string api. | ||||||
| @@ -104,42 +119,46 @@ typedef char* String; | |||||||
| struct String; | struct String; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| usize string_grow_formula(usize value); | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
| String        string_make         (AllocatorInfo allocator, char const*  str); | forceinline usize string_grow_formula(usize value); | ||||||
| String        string_make         (AllocatorInfo allocator, StrC         str); |  | ||||||
|  | String        string_make_c_str          (AllocatorInfo allocator, char const*  str); | ||||||
|  | String        string_make_strc           (AllocatorInfo allocator, StrC         str); | ||||||
| String        string_make_reserve        (AllocatorInfo allocator, ssize        capacity); | String        string_make_reserve        (AllocatorInfo allocator, ssize        capacity); | ||||||
| String        string_make_length         (AllocatorInfo allocator, char const*  str,   ssize length); | 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                 (AllocatorInfo allocator, char*        buf,   ssize buf_size,  char const* fmt, ...); | ||||||
| String        string_fmt_buf             (AllocatorInfo allocator, 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); | String        string_join                (AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue); | ||||||
| bool          are_equal           (String const lhs, String const rhs); | bool          string_are_equal           (String const lhs, String const rhs); | ||||||
| bool          are_equal           (String const lhs, StrC rhs); | bool          string_are_equal_strc      (String const lhs, StrC rhs); | ||||||
| bool          make_space_for      (String*      str, char const*  to_append, ssize add_len); | bool          string_make_space_for      (String*      str, char const*  to_append, ssize add_len); | ||||||
| bool          append              (String*      str, char         c); | bool          string_append_char         (String*      str, char         c); | ||||||
| bool          append              (String*      str, char const*  str_to_append); | bool          string_append_c_str        (String*      str, char const*  str_to_append); | ||||||
| bool          append              (String*      str, char const*  str_to_append, ssize length); | bool          string_append_c_str_len    (String*      str, char const*  str_to_append, ssize length); | ||||||
| bool          append              (String*      str, StrC         str_to_append); | bool          string_append_strc         (String*      str, StrC         str_to_append); | ||||||
| bool          append              (String*      str, String const other); | bool          string_append_string       (String*      str, String const other); | ||||||
| bool          append_fmt          (String*      str, char const*  fmt, ...); | bool          string_append_fmt          (String*      str, char const*  fmt, ...); | ||||||
| ssize         avail_space         (String const str); | ssize         string_avail_space         (String const str); | ||||||
| char*         back                (String       str); | char*         string_back                (String       str); | ||||||
| bool          contains            (String const str, StrC         substring); | bool          string_contains_strc       (String const str, StrC         substring); | ||||||
| bool          contains            (String const str, String const substring); | bool          string_contains_string     (String const str, String const substring); | ||||||
| ssize         capacity            (String const str); | ssize         string_capacity            (String const str); | ||||||
| void          clear               (String       str); | void          string_clear               (String       str); | ||||||
| String        duplicate           (String const str, AllocatorInfo allocator); | String        string_duplicate           (String const str, AllocatorInfo allocator); | ||||||
| void          free                (String*      str); | void          string_free                (String*      str); | ||||||
| StringHeader* get_header          (String       str); | StringHeader* string_get_header          (String       str); | ||||||
| ssize         length              (String const str); | ssize         string_length              (String const str); | ||||||
| b32           starts_with         (String const str, StrC   substring); | b32           string_starts_with_strc    (String const str, StrC   substring); | ||||||
| b32           starts_with         (String const str, String substring); | b32           string_starts_with_string  (String const str, String substring); | ||||||
| void          skip_line           (String       str); | void          string_skip_line           (String       str); | ||||||
| void          strip_space         (String       str); | void          string_strip_space         (String       str); | ||||||
| StrC          to_strc             (String       str); | StrC          string_to_strc             (String       str); | ||||||
| void          trim                (String       str, char const* cut_set); | void          string_trim                (String       str, char const* cut_set); | ||||||
| void          trim_space          (String       str); | void          string_trim_space          (String       str); | ||||||
| String        visualize_whitespace(String const str); | String        string_visualize_whitespace(String const str); | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| struct StringHeader { | struct StringHeader { | ||||||
| 	AllocatorInfo Allocator; | 	AllocatorInfo Allocator; | ||||||
| @@ -147,14 +166,14 @@ struct StringHeader { | |||||||
| 	ssize         Length; | 	ssize         Length; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #if ! GEN_COMPILER_C && GEN_SUPPORT_CPP_MEMBER_FEATURES | #if GEN_COMPILER_CPP && GEN_SUPPORT_CPP_MEMBER_FEATURES | ||||||
| struct String | struct String | ||||||
| { | { | ||||||
| 	char* Data; | 	char* Data; | ||||||
|  |  | ||||||
| 	forceinline operator char*()             { return Data; } | 	forceinline operator char*()             { return Data; } | ||||||
| 	forceinline operator char const*() const { return Data; } | 	forceinline operator char const*() const { return Data; } | ||||||
| 	forceinline operator StrC()        const { return { GEN_NS length(* this), Data }; } | 	forceinline operator StrC()        const { return { string_length(* this), Data }; } | ||||||
|  |  | ||||||
| 	String const& operator=(String const& other) const { | 	String const& operator=(String const& other) const { | ||||||
| 		if (this == &other) | 		if (this == &other) | ||||||
| @@ -169,29 +188,29 @@ struct String | |||||||
| 	forceinline char&       operator[](ssize index)       { return Data[index]; } | 	forceinline char&       operator[](ssize index)       { return Data[index]; } | ||||||
| 	forceinline char const& operator[](ssize index) const { return Data[index]; } | 	forceinline char const& operator[](ssize index) const { return Data[index]; } | ||||||
|  |  | ||||||
| 	       bool operator==(std::nullptr_t) const             { return     Data == nullptr; } | 	       forceinline bool operator==(std::nullptr_t) const             { return     Data == nullptr; } | ||||||
| 	       bool operator!=(std::nullptr_t) const             { return     Data != nullptr; } | 	       forceinline bool operator!=(std::nullptr_t) const             { return     Data != nullptr; } | ||||||
| 	friend bool operator==(std::nullptr_t, const String str) { return str.Data == nullptr; } | 	friend forceinline bool operator==(std::nullptr_t, const String str) { return str.Data == nullptr; } | ||||||
| 	friend bool operator!=(std::nullptr_t, const String str) { return str.Data != nullptr; } | 	friend forceinline bool operator!=(std::nullptr_t, const String str) { return str.Data != nullptr; } | ||||||
|  |  | ||||||
| 	forceinline char* begin() const { return Data; } | 	forceinline char* begin() const { return Data; } | ||||||
| 	forceinline char* end()   const { return Data + GEN_NS length(* this); } | 	forceinline char* end()   const { return Data + string_length(* this); } | ||||||
|  |  | ||||||
| #pragma region Member Mapping | #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, char const* str)                { return string_make_c_str(allocator, str); } | ||||||
| 	forceinline static String make(AllocatorInfo allocator, StrC str)                       { return GEN_NS string_make(allocator, str); } | 	forceinline static String make(AllocatorInfo allocator, StrC str)                       { return string_make_strc(allocator, str); } | ||||||
| 	forceinline static String make_reserve(AllocatorInfo allocator, ssize cap)              { return GEN_NS string_make_reserve(allocator, cap); } | 	forceinline static String make_reserve(AllocatorInfo allocator, ssize cap)              { return 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 make_length(AllocatorInfo a, char const* s, ssize l)          { return 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 String join(AllocatorInfo a, char const** p, ssize n, char const* g) { return string_join(a, p, n, g); } | ||||||
| 	forceinline static usize  grow_formula(usize value)                                     { return GEN_NS string_grow_formula(value); } | 	forceinline static usize  grow_formula(usize value)                                     { return string_grow_formula(value); } | ||||||
|  |  | ||||||
| 	static | 	static | ||||||
| 	String fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | 	String fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
| 		va_list va; | 		va_list va; | ||||||
| 		va_start(va, fmt); | 		va_start(va, fmt); | ||||||
| 		str_fmt_va(buf, buf_size, fmt, va); | 		ssize res = str_fmt_va(buf, buf_size, fmt, va); | ||||||
| 		va_end(va); | 		va_end(va); | ||||||
| 		return GEN_NS string_make(allocator, buf); | 		return string_make_length(allocator, buf, res); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static | 	static | ||||||
| @@ -200,37 +219,37 @@ struct String | |||||||
| 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | 		char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
| 		va_list va; | 		va_list va; | ||||||
| 		va_start(va, fmt); | 		va_start(va, fmt); | ||||||
| 		str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | 		ssize res = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | ||||||
| 		va_end(va); | 		va_end(va); | ||||||
| 		return GEN_NS string_make(allocator, buf); | 		return string_make_length(allocator, buf, res); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	forceinline bool          make_space_for(char const* str, ssize add_len) { return GEN_NS make_space_for(this, str, add_len); } | 	forceinline bool          make_space_for(char const* str, ssize add_len) { return string_make_space_for(this, str, add_len); } | ||||||
| 	forceinline bool          append(char c)                                 { return GEN_NS append(this, c); } | 	forceinline bool          append(char c)                                 { return string_append_char(this, c); } | ||||||
| 	forceinline bool          append(char const* str)                        { return GEN_NS append(this, str); } | 	forceinline bool          append(char const* str)                        { return string_append_c_str(this, str); } | ||||||
| 	forceinline bool          append(char const* str, ssize length)          { return GEN_NS append(this, str, length); } | 	forceinline bool          append(char const* str, ssize length)          { return string_append_c_str_len(this, str, length); } | ||||||
| 	forceinline bool          append(StrC str)                               { return GEN_NS append(this, str); } | 	forceinline bool          append(StrC str)                               { return string_append_strc(this, str); } | ||||||
| 	forceinline bool          append(const String other)                     { return GEN_NS append(this, other); } | 	forceinline bool          append(const String other)                     { return string_append_string(this, other); } | ||||||
| 	forceinline ssize         avail_space() const                            { return GEN_NS avail_space(* this); } | 	forceinline ssize         avail_space() const                            { return string_avail_space(* this); } | ||||||
| 	forceinline char*         back()                                         { return GEN_NS back(* this); } | 	forceinline char*         back()                                         { return string_back(* this); } | ||||||
| 	forceinline bool          contains(StrC substring) const                 { return GEN_NS contains(* this, substring); } | 	forceinline bool          contains(StrC substring) const                 { return string_contains_strc(* this, substring); } | ||||||
| 	forceinline bool          contains(String const& substring) const        { return GEN_NS contains(* this, substring); } | 	forceinline bool          contains(String const& substring) const        { return string_contains_string(* this, substring); } | ||||||
| 	forceinline ssize         capacity() const                               { return GEN_NS capacity(* this); } | 	forceinline ssize         capacity() const                               { return string_capacity(* this); } | ||||||
| 	forceinline void          clear()                                        { GEN_NS clear(* this); } | 	forceinline void          clear()                                        {        string_clear(* this); } | ||||||
| 	forceinline String        duplicate(AllocatorInfo allocator) const       { return GEN_NS duplicate(* this, allocator); } | 	forceinline String        duplicate(AllocatorInfo allocator) const       { return string_duplicate(* this, allocator); } | ||||||
| 	forceinline void          free()                                         { GEN_NS free(this); } | 	forceinline void          free()                                         {        string_free(this); } | ||||||
| 	forceinline bool          is_equal(String const& other) const            { return GEN_NS are_equal(* this, other); } | 	forceinline bool          is_equal(String const& other) const            { return string_are_equal(* this, other); } | ||||||
| 	forceinline bool          is_equal(StrC other) const                     { return GEN_NS are_equal(* this, other); } | 	forceinline bool          is_equal(StrC other) const                     { return string_are_equal_strc(* this, other); } | ||||||
| 	forceinline ssize         length() const                                 { return GEN_NS length(* this); } | 	forceinline ssize         length() const                                 { return string_length(* this); } | ||||||
| 	forceinline b32           starts_with(StrC substring) const              { return GEN_NS starts_with(* this, substring); } | 	forceinline b32           starts_with(StrC substring) const              { return string_starts_with_strc(* this, substring); } | ||||||
| 	forceinline b32           starts_with(String substring) const            { return GEN_NS starts_with(* this, substring); } | 	forceinline b32           starts_with(String substring) const            { return string_starts_with_string(* this, substring); } | ||||||
| 	forceinline void          skip_line()                                    { GEN_NS skip_line(* this); } | 	forceinline void          skip_line()                                    {        string_skip_line(* this); } | ||||||
| 	forceinline void          strip_space()                                  { GEN_NS strip_space(* this); } | 	forceinline void          strip_space()                                  {        string_strip_space(* this); } | ||||||
| 	forceinline StrC          to_strc()                                      { return { length(), Data}; } | 	forceinline StrC          to_strc()                                      { return { string_length(*this), Data}; } | ||||||
| 	forceinline void          trim(char const* cut_set)                      { GEN_NS trim(* this, cut_set); } | 	forceinline void          trim(char const* cut_set)                      {        string_trim(* this, cut_set); } | ||||||
| 	forceinline void          trim_space()                                   { GEN_NS trim_space(* this); } | 	forceinline void          trim_space()                                   {        string_trim_space(* this); } | ||||||
| 	forceinline String        visualize_whitespace() const                   { return GEN_NS visualize_whitespace(* this); } | 	forceinline String        visualize_whitespace() const                   { return string_visualize_whitespace(* this); } | ||||||
| 	forceinline StringHeader& get_header()                                   { return * GEN_NS get_header(* this); } | 	forceinline StringHeader& get_header()                                   { return * string_get_header(* this); } | ||||||
|  |  | ||||||
| 	bool append_fmt(char const* fmt, ...) { | 	bool append_fmt(char const* fmt, ...) { | ||||||
| 		ssize res; | 		ssize res; | ||||||
| @@ -241,43 +260,53 @@ struct String | |||||||
| 		res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | 		res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
| 		va_end(va); | 		va_end(va); | ||||||
|  |  | ||||||
| 		return GEN_NS append(this, buf, res); | 		return string_append_c_str_len(this, buf, res); | ||||||
| 	} | 	} | ||||||
| #pragma endregion Member Mapping | #pragma endregion Member Mapping | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| inline char* begin(String str)             { return ((char*) str); } | GEN_API_C_BEGIN | ||||||
| inline char* end  (String str)             { return ((char*) str + length(str)); } | forceinline char* string_begin(String str)                   { return ((char*) str); } | ||||||
| inline char* next (String str, char* iter) { return ((char*) iter + 1); } | forceinline char* string_end  (String str)                   { return ((char*) str + string_length(str)); } | ||||||
|  | forceinline char* string_next (String str, char const* iter) { return ((char*) iter + 1); } | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| #if GEN_SUPPORT_CPP_REFERENCES | #if GEN_COMPILER_CPP && 0 | ||||||
| inline bool          make_space_for(String& str, char const* to_append, ssize add_len); | forceinline char* begin(String str)             { return ((char*) str); } | ||||||
| inline bool          append(String& str, char c); | forceinline char* end  (String str)             { return ((char*) str + string_length(str)); } | ||||||
| inline bool          append(String& str, char const* str_to_append); | forceinline char* next (String str, char* iter) { return ((char*) iter + 1); } | ||||||
| inline bool          append(String& str, char const* str_to_append, ssize length); |  | ||||||
| inline bool          append(String& str, StrC str_to_append); |  | ||||||
| inline bool          append(String& str, const String other); |  | ||||||
| inline bool          append_fmt(String& str, char const* fmt, ...); |  | ||||||
| inline char&         back(String& str); |  | ||||||
| inline void          clear(String& str); |  | ||||||
| inline void          free(String& str); |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| inline | #if GEN_SUPPORT_CPP_REFERENCES | ||||||
|  | forceinline bool  make_space_for(String& str, char const* to_append, ssize add_len); | ||||||
|  | forceinline bool  append(String& str, char c); | ||||||
|  | forceinline bool  append(String& str, char const* str_to_append); | ||||||
|  | forceinline bool  append(String& str, char const* str_to_append, ssize length); | ||||||
|  | forceinline bool  append(String& str, StrC str_to_append); | ||||||
|  | forceinline bool  append(String& str, const String other); | ||||||
|  | forceinline bool  append_fmt(String& str, char const* fmt, ...); | ||||||
|  | forceinline char& back(String& str); | ||||||
|  | forceinline void  clear(String& str); | ||||||
|  | forceinline void  free(String& str); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | GEN_API_C_BEGIN | ||||||
|  |  | ||||||
|  | forceinline | ||||||
| usize string_grow_formula(usize value) { | 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. | 	// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. | ||||||
| 	return 4 * value + 8; | 	return 4 * value + 8; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| String string_make(AllocatorInfo allocator, char const* str) { | String string_make_c_str(AllocatorInfo allocator, char const* str) { | ||||||
| 	ssize length = str ? str_len(str) : 0; | 	ssize length = str ? str_len(str) : 0; | ||||||
| 	return string_make_length(allocator, str, length); | 	return string_make_length(allocator, str, length); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| String string_make(AllocatorInfo allocator, StrC str) { | String string_make_strc(AllocatorInfo allocator, StrC str) { | ||||||
| 	return string_make_length(allocator, str.Ptr, str.Len); | 	return string_make_length(allocator, str.Ptr, str.Len); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -285,10 +314,10 @@ inline | |||||||
| String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) { | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start(va, fmt); | 	va_start(va, fmt); | ||||||
| 	str_fmt_va(buf, buf_size, fmt, va); | 	ssize res = str_fmt_va(buf, buf_size, fmt, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	return string_make(allocator, buf); | 	return string_make_length(allocator, buf, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| @@ -299,52 +328,52 @@ String string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...) | |||||||
|  |  | ||||||
| 	va_list va; | 	va_list va; | ||||||
| 	va_start(va, fmt); | 	va_start(va, fmt); | ||||||
| 	str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | 	ssize res = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va); | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	return string_make(allocator, buf); | 	return string_make_length(allocator, buf, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue) | String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue) | ||||||
| { | { | ||||||
| 	String result = string_make(allocator, ""); | 	String result = string_make_c_str(allocator, ""); | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx < num_parts; ++idx) | 	for (ssize idx = 0; idx < num_parts; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		append(& result, parts[idx]); | 		string_append_c_str(& result, parts[idx]); | ||||||
|  |  | ||||||
| 		if (idx < num_parts - 1) | 		if (idx < num_parts - 1) | ||||||
| 			append(& result, glue); | 			string_append_c_str(& result, glue); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| bool append(String* str, char c) { | bool string_append_char(String* str, char c) { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	return append( str, (char const*)& c, (ssize)1); | 	return string_append_c_str_len( str, (char const*)& c, (ssize)1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | bool string_append_c_str(String* str, char const* str_to_append) { | ||||||
|  | 	GEN_ASSERT(str != nullptr); | ||||||
|  | 	return string_append_c_str_len(str, str_to_append, str_len(str_to_append)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool append(String* str, char const* str_to_append) { | bool string_append_c_str_len(String* str, char const* str_to_append, ssize append_length) | ||||||
| 	GEN_ASSERT(str != nullptr); |  | ||||||
| 	return append(str, str_to_append, str_len(str_to_append)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline |  | ||||||
| bool append(String* str, char const* str_to_append, ssize append_length) |  | ||||||
| { | { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	if (sptr(str_to_append) > 0) | 	if (sptr(str_to_append) > 0) | ||||||
| 	{ | 	{ | ||||||
| 		ssize curr_len = length(* str); | 		ssize curr_len = string_length(* str); | ||||||
|  |  | ||||||
| 		if ( ! make_space_for(str, str_to_append, append_length)) | 		if ( ! string_make_space_for(str, str_to_append, append_length)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		StringHeader* header = get_header(* str); | 		StringHeader* header = string_get_header(* str); | ||||||
|  |  | ||||||
| 		char* Data = * str; | 		char* Data = * str; | ||||||
| 		mem_copy( Data + curr_len, str_to_append, append_length); | 		mem_copy( Data + curr_len, str_to_append, append_length); | ||||||
| @@ -356,19 +385,19 @@ bool append(String* str, char const* str_to_append, ssize append_length) | |||||||
| 	return str_to_append != nullptr; | 	return str_to_append != nullptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| bool append(String* str, StrC str_to_append) { | bool string_append_strc(String* str, StrC str_to_append) { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	return append(str, str_to_append.Ptr, str_to_append.Len); | 	return string_append_c_str_len(str, str_to_append.Ptr, str_to_append.Len); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| bool append(String* str, String const other) { | bool string_append_string(String* str, String const other) { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	return append(str, (char const*)other, length(other)); | 	return string_append_c_str_len(str, (char const*)other, string_length(other)); | ||||||
| } | } | ||||||
|  |  | ||||||
| bool append_fmt(String* str, char const* fmt, ...) { | bool string_append_fmt(String* str, char const* fmt, ...) { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	ssize res; | 	ssize res; | ||||||
| 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | 	char buf[GEN_PRINTF_MAXLEN] = { 0 }; | ||||||
| @@ -378,16 +407,16 @@ bool append_fmt(String* str, char const* fmt, ...) { | |||||||
| 	res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | 	res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1; | ||||||
| 	va_end(va); | 	va_end(va); | ||||||
|  |  | ||||||
| 	return append(str, (char const*)buf, res); | 	return string_append_c_str_len(str, (char const*)buf, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool are_equal(String const lhs, String const rhs) | bool string_are_equal_string(String const lhs, String const rhs) | ||||||
| { | { | ||||||
| 	if (length(lhs) != length(rhs)) | 	if (string_length(lhs) != string_length(rhs)) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx < length(lhs); ++idx) | 	for (ssize idx = 0; idx < string_length(lhs); ++idx) | ||||||
| 		if (lhs[idx] != rhs[idx]) | 		if (lhs[idx] != rhs[idx]) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| @@ -395,31 +424,31 @@ bool are_equal(String const lhs, String const rhs) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool are_equal(String const lhs, StrC rhs) | bool string_are_equal_strc(String const lhs, StrC rhs) | ||||||
| { | { | ||||||
| 	if (length(lhs) != (rhs.Len)) | 	if (string_length(lhs) != (rhs.Len)) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx < length(lhs); ++idx) | 	for (ssize idx = 0; idx < string_length(lhs); ++idx) | ||||||
| 		if (lhs[idx] != rhs.Ptr[idx]) | 		if (lhs[idx] != rhs.Ptr[idx]) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| ssize avail_space(String const str) { | ssize string_avail_space(String const str) { | ||||||
| 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
| 	return header->Capacity - header->Length; | 	return header->Capacity - header->Length; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| char* back(String* str) { | char* string_back(String str) { | ||||||
| 	return & (*str)[length(* str) - 1]; | 	return & (str)[string_length(str) - 1]; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool contains(String const str, StrC substring) | bool string_contains_StrC(String const str, StrC substring) | ||||||
| { | { | ||||||
| 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |  | ||||||
| @@ -431,7 +460,7 @@ bool contains(String const str, StrC substring) | |||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		if (str_compare(str + idx, substring.Ptr, sub_len) == 0) | 		if (str_compare_len(str + idx, substring.Ptr, sub_len) == 0) | ||||||
| 			return true; | 			return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -439,67 +468,67 @@ bool contains(String const str, StrC substring) | |||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool contains(String const str, String const substring) | bool string_contains_string(String const str, String const substring) | ||||||
| { | { | ||||||
| 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | 	StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|  |  | ||||||
| 	if (length(substring) > header->Length) | 	if (string_length(substring) > header->Length) | ||||||
| 		return false; | 		return false; | ||||||
|  |  | ||||||
| 	ssize main_len = header->Length; | 	ssize main_len = header->Length; | ||||||
| 	ssize sub_len  = length(substring); | 	ssize sub_len  = string_length(substring); | ||||||
|  |  | ||||||
| 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | 	for (ssize idx = 0; idx <= main_len - sub_len; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		if (str_compare(str + idx, substring, sub_len) == 0) | 		if (str_compare_len(str + idx, substring, sub_len) == 0) | ||||||
| 			return true; | 			return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| ssize capacity(String const str) { | ssize string_capacity(String const str) { | ||||||
|    StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); |    StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|    return header->Capacity; |    return header->Capacity; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| void clear(String str) { | void string_clear(String str) { | ||||||
|    get_header(str)->Length = 0; |    string_get_header(str)->Length = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| String duplicate(String const str, AllocatorInfo allocator) { | String string_duplicate(String const str, AllocatorInfo allocator) { | ||||||
|    return string_make_length(allocator, str, length(str)); |    return string_make_length(allocator, str, string_length(str)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| void free(String* str) { | void string_free(String* str) { | ||||||
| 	GEN_ASSERT(str != nullptr); | 	GEN_ASSERT(str != nullptr); | ||||||
| 	if (! (* str)) | 	if (! (* str)) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	StringHeader* header = get_header(* str); | 	StringHeader* header = string_get_header(* str); | ||||||
| 	GEN_NS free(header->Allocator, header); | 	allocator_free(header->Allocator, header); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| StringHeader* get_header(String str) { | StringHeader* string_get_header(String str) { | ||||||
|    return (StringHeader*)(scast(char*, str) - sizeof(StringHeader)); |    return (StringHeader*)(scast(char*, str) - sizeof(StringHeader)); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| ssize length(String const str) | ssize string_length(String const str) | ||||||
| { | { | ||||||
|    StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); |    StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader)); | ||||||
|    return header.Length; |    return header.Length; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| bool make_space_for(String* str, char const* to_append, ssize add_len) | bool string_make_space_for(String* str, char const* to_append, ssize add_len) | ||||||
| { | { | ||||||
| 	ssize available = avail_space(* str); | 	ssize available = string_avail_space(* str); | ||||||
|  |  | ||||||
| 	if (available >= add_len) { | 	if (available >= add_len) { | ||||||
| 		return true; | 		return true; | ||||||
| @@ -510,12 +539,12 @@ bool make_space_for(String* str, char const* to_append, ssize add_len) | |||||||
| 		void* ptr; | 		void* ptr; | ||||||
| 		void* new_ptr; | 		void* new_ptr; | ||||||
|  |  | ||||||
| 		AllocatorInfo allocator = get_header(* str)->Allocator; | 		AllocatorInfo allocator = string_get_header(* str)->Allocator; | ||||||
| 		StringHeader* header    = nullptr; | 		StringHeader* header    = nullptr; | ||||||
|  |  | ||||||
| 		new_len  = string_grow_formula(length(* str) + add_len); | 		new_len  = string_grow_formula(string_length(* str) + add_len); | ||||||
| 		ptr      = get_header(* str); | 		ptr      = string_get_header(* str); | ||||||
| 		old_size = size_of(StringHeader) + length(* str) + 1; | 		old_size = size_of(StringHeader) + string_length(* str) + 1; | ||||||
| 		new_size = size_of(StringHeader) + new_len + 1; | 		new_size = size_of(StringHeader) + new_len + 1; | ||||||
|  |  | ||||||
| 		new_ptr = resize(allocator, ptr, old_size, new_size); | 		new_ptr = resize(allocator, ptr, old_size, new_size); | ||||||
| @@ -534,26 +563,26 @@ bool make_space_for(String* str, char const* to_append, ssize add_len) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| b32 starts_with(String const str, StrC substring) { | b32 string_starts_with_strc(String const str, StrC substring) { | ||||||
| 	if (substring.Len > length(str)) | 	if (substring.Len > string_length(str)) | ||||||
| 	return false; | 	return false; | ||||||
|  |  | ||||||
| 	b32 result = str_compare(str, substring.Ptr, substring.Len) == 0; | 	b32 result = str_compare_len(str, substring.Ptr, substring.Len) == 0; | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | forceinline | ||||||
|  | b32 string_starts_with_string(String const str, String substring) { | ||||||
|  | 	if (string_length(substring) > string_length(str)) | ||||||
|  | 		return false; | ||||||
|  |  | ||||||
|  | 	b32 result = str_compare_len(str, substring, string_length(substring) - 1) == 0; | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| b32 starts_with(String const str, String substring) { | void string_skip_line(String str) | ||||||
| 	if (length(substring) > length(str)) |  | ||||||
| 		return false; |  | ||||||
|  |  | ||||||
| 	b32 result = str_compare(str, substring, length(substring) - 1) == 0; |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline |  | ||||||
| void skip_line(String str) |  | ||||||
| { | { | ||||||
| #define current (*scanner) | #define current (*scanner) | ||||||
| 	char* scanner = str; | 	char* scanner = str; | ||||||
| @@ -569,7 +598,7 @@ void skip_line(String str) | |||||||
|  |  | ||||||
| 	mem_move((char*)str, scanner, new_length); | 	mem_move((char*)str, scanner, new_length); | ||||||
|  |  | ||||||
| 	StringHeader* header = get_header(str); | 	StringHeader* header = string_get_header(str); | ||||||
| 	header->Length = new_length; | 	header->Length = new_length; | ||||||
| #undef current | #undef current | ||||||
| } | } | ||||||
| @@ -593,12 +622,12 @@ void strip_space(String str) | |||||||
|    write_pos[0] = '\0';  // Null-terminate the modified string |    write_pos[0] = '\0';  // Null-terminate the modified string | ||||||
|  |  | ||||||
|    // Update the length if needed |    // Update the length if needed | ||||||
|    get_header(str)->Length = write_pos - str; |    string_get_header(str)->Length = write_pos - str; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| StrC to_strc(String str) { | StrC string_to_strc(String str) { | ||||||
| 	return { length(str), (char const*)str }; | 	return { string_length(str), (char const*)str }; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| @@ -607,7 +636,7 @@ void trim(String str, char const* cut_set) | |||||||
| 	ssize len = 0; | 	ssize len = 0; | ||||||
|  |  | ||||||
| 	char* start_pos = str; | 	char* start_pos = str; | ||||||
| 	char* end_pos   = scast(char*, str) + length(str) - 1; | 	char* end_pos   = scast(char*, str) + string_length(str) - 1; | ||||||
|  |  | ||||||
| 	while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos)) | 	while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos)) | ||||||
| 	start_pos++; | 	start_pos++; | ||||||
| @@ -622,10 +651,10 @@ void trim(String str, char const* cut_set) | |||||||
|  |  | ||||||
| 	str[len] = '\0'; | 	str[len] = '\0'; | ||||||
|  |  | ||||||
|    get_header(str)->Length = len; |    string_get_header(str)->Length = len; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| void trim_space(String str) { | void trim_space(String str) { | ||||||
|    trim(str, " \t\r\n\v\f"); |    trim(str, " \t\r\n\v\f"); | ||||||
| } | } | ||||||
| @@ -634,30 +663,31 @@ inline | |||||||
| String visualize_whitespace(String const str) | String visualize_whitespace(String const str) | ||||||
| { | { | ||||||
| 	StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader)); | 	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. | 	String        result = string_make_reserve(header->Allocator, string_length(str) * 2); // Assume worst case for space requirements. | ||||||
|  |  | ||||||
| 	foreach (char*, c, str) switch ( * c ) | 	for (char const* c = string_begin(str); c != string_end(str); c = string_next(str, c)) | ||||||
|  | 	switch ( * c ) | ||||||
| 	{ | 	{ | ||||||
| 		case ' ': | 		case ' ': | ||||||
| 			append(& result, txt("·")); | 			string_append_strc(& result, txt("·")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\t': | 		case '\t': | ||||||
| 			append(& result, txt("→")); | 			string_append_strc(& result, txt("→")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\n': | 		case '\n': | ||||||
| 			append(& result, txt("↵")); | 			string_append_strc(& result, txt("↵")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\r': | 		case '\r': | ||||||
| 			append(& result, txt("⏎")); | 			string_append_strc(& result, txt("⏎")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\v': | 		case '\v': | ||||||
| 			append(& result, txt("⇕")); | 			string_append_strc(& result, txt("⇕")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\f': | 		case '\f': | ||||||
| 			append(& result, txt("⌂")); | 			string_append_strc(& result, txt("⌂")); | ||||||
| 		break; | 		break; | ||||||
| 		default: | 		default: | ||||||
| 			append(& result, c); | 			string_append_char(& result, * c); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -670,47 +700,50 @@ struct String_POD { | |||||||
| }; | }; | ||||||
| static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" ); | ||||||
|  |  | ||||||
| inline | forceinline | ||||||
| StrC duplicate(StrC str, AllocatorInfo allocator) { | StrC strc_duplicate(StrC str, AllocatorInfo allocator) { | ||||||
| 	String result = string_make_length(allocator, str.Ptr, str.Len); | 	String result = string_make_length(allocator, str.Ptr, str.Len); | ||||||
| 	return {  get_header(result)->Length, result }; | 	return { string_get_header(result)->Length, result }; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline | inline | ||||||
| StrC visualize_whitespace(StrC str, AllocatorInfo allocator) | StrC strc_visualize_whitespace(StrC str, AllocatorInfo allocator) | ||||||
| { | { | ||||||
| 	String result = string_make_reserve(allocator, str.Len * 2); // Assume worst case for space requirements. | 	String result = string_make_reserve(allocator, str.Len * 2); // Assume worst case for space requirements. | ||||||
| 	foreach (char const*, c, str) switch ( * c ) | 	for (char const* c = strc_begin(str); c != strc_end(str); c = strc_next(str, c))  | ||||||
|  | 	switch ( * c ) | ||||||
| 	{ | 	{ | ||||||
| 		case ' ': | 		case ' ': | ||||||
| 			append(& result, txt("·")); | 			string_append_strc(& result, txt("·")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\t': | 		case '\t': | ||||||
| 			append(& result, txt("→")); | 			string_append_strc(& result, txt("→")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\n': | 		case '\n': | ||||||
| 			append(& result, txt("↵")); | 			string_append_strc(& result, txt("↵")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\r': | 		case '\r': | ||||||
| 			append(& result, txt("⏎")); | 			string_append_strc(& result, txt("⏎")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\v': | 		case '\v': | ||||||
| 			append(& result, txt("⇕")); | 			string_append_strc(& result, txt("⇕")); | ||||||
| 		break; | 		break; | ||||||
| 		case '\f': | 		case '\f': | ||||||
| 			append(& result, txt("⌂")); | 			string_append_strc(& result, txt("⌂")); | ||||||
| 		break; | 		break; | ||||||
| 		default: | 		default: | ||||||
| 			append(& result, c); | 			string_append_char(& result, * c); | ||||||
| 		break; | 		break; | ||||||
| } | } | ||||||
| 	return to_strc(result); | 	return string_to_strc(result); | ||||||
| } | } | ||||||
|  |  | ||||||
| // 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. | ||||||
| typedef StrC StringCached; | typedef StrC StringCached; | ||||||
|  |  | ||||||
|  | GEN_API_C_END | ||||||
|  |  | ||||||
| // Implements basic string interning. Data structure is based off the ZPL Hashtable. | // Implements basic string interning. Data structure is based off the ZPL Hashtable. | ||||||
| typedef HashTable<StringCached> StringTable; | typedef HashTable<StringCached> StringTable; | ||||||
| #pragma endregion Strings | #pragma endregion Strings | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ 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( allocator_info( & scratch), zero_terminate, path ); | 	file_read_contents( arena_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 ); | ||||||
| @@ -23,19 +23,21 @@ CodeBody gen_ecode( char const* path ) | |||||||
| 	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 = array_begin(enum_strs); node != array_end(enum_strs); node = array_next(enum_strs, node) ) | ||||||
| 	{ | 	{ | ||||||
| 		char const* code = node.string; | 		char const* code = node->string; | ||||||
|  |  | ||||||
| 		append_fmt( & enum_entries, "CT_%s,\n", code ); | 		string_append_fmt( & enum_entries, "CT_%s,\n", code ); | ||||||
| 		append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", code, code ); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", to_strc(enum_entries), "enum CodeType_Def : u32 { <entries> CT_NumTypes };")); | 	CodeEnum enum_code = parse_enum(gen::token_fmt_impl((3 + 1) / 2, "entries", string_to_strc(enum_entries),  | ||||||
|  | 		"enum CodeType_Def : u32 { <entries> CT_NumTypes };" | ||||||
|  | 	)); | ||||||
|  |  | ||||||
| #pragma push_macro("local_persist") | #pragma push_macro("local_persist") | ||||||
| #undef local_persist | #undef local_persist | ||||||
| 	CodeFn to_str = parse_function( token_fmt( "entries", to_strc(to_str_entries), stringize( | 	CodeFn to_str = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( CodeType type ) | 		StrC to_str( CodeType type ) | ||||||
| 		{ | 		{ | ||||||
| @@ -61,7 +63,7 @@ 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( allocator_info(& scratch), zero_terminate, path ); | 	file_read_contents( arena_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 ); | ||||||
| @@ -72,16 +74,16 @@ CodeBody gen_eoperator( char const* path ) | |||||||
| 	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 (usize idx = 0; idx < num(enum_strs); idx++) | 	for (usize idx = 0; idx < array_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; | ||||||
|  |  | ||||||
| 		append_fmt( & enum_entries, "Op_%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Op_%s,\n", enum_str ); | ||||||
| 		append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", to_strc(enum_entries), stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), stringize( | ||||||
| 		enum Operator_Def : u32 | 		enum Operator_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| @@ -91,7 +93,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", to_strc(to_str_entries), stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Operator op ) | 		StrC to_str( Operator op ) | ||||||
| 		{ | 		{ | ||||||
| @@ -117,7 +119,7 @@ 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( allocator_info(& scratch), zero_terminate, path ); | 	file_read_contents( arena_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 ); | ||||||
| @@ -128,16 +130,16 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 	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 (usize idx = 0; idx < num(enum_strs); idx++) | 	for (usize idx = 0; idx < array_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; | ||||||
|  |  | ||||||
| 		append_fmt( & enum_entries, "Spec_%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Spec_%s,\n", enum_str ); | ||||||
| 		append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	CodeEnum  enum_code = parse_enum(token_fmt("entries", to_strc(enum_entries), stringize( | 	CodeEnum  enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), stringize( | ||||||
| 		enum Specifier_Def : u32 | 		enum Specifier_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| @@ -145,7 +147,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 		}; | 		}; | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn is_trailing = parse_function(token_fmt("specifier", to_strc(to_str_entries), stringize( | 	CodeFn is_trailing = parse_function(token_fmt("specifier", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		bool is_trailing( Specifier specifier ) | 		bool is_trailing( Specifier specifier ) | ||||||
| 		{ | 		{ | ||||||
| @@ -163,7 +165,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| #undef do_once_end | #undef do_once_end | ||||||
| #undef forceinline | #undef forceinline | ||||||
| #undef neverinline | #undef neverinline | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", to_strc(to_str_entries), stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( Specifier type ) | 		StrC to_str( Specifier type ) | ||||||
| 		{ | 		{ | ||||||
| @@ -176,7 +178,7 @@ CodeBody gen_especifier( char const* path ) | |||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", to_strc(to_str_entries), stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		Specifier to_specifier( StrC str ) | 		Specifier to_specifier( StrC str ) | ||||||
| 		{ | 		{ | ||||||
| @@ -222,7 +224,7 @@ 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) ); | ||||||
|  |  | ||||||
| 	AllocatorInfo scratch_info = allocator_info(& scratch); | 	AllocatorInfo scratch_info = arena_allocator_info(& scratch); | ||||||
|  |  | ||||||
| 	FileContents enum_content = file_read_contents( scratch_info, zero_terminate, etok_path ); | 	FileContents enum_content = file_read_contents( scratch_info, zero_terminate, etok_path ); | ||||||
|  |  | ||||||
| @@ -245,37 +247,37 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 	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 (usize idx = 0; idx < num(enum_strs); idx++) | 	for (usize idx = 0; idx < array_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; | ||||||
|  |  | ||||||
| 		append_fmt( & enum_entries, "Tok_%s,\n", enum_str ); | 		string_append_fmt( & enum_entries, "Tok_%s,\n", enum_str ); | ||||||
| 		append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_entries, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for ( usize idx = 0; idx < num(attribute_strs); idx++ ) | 	for ( usize idx = 0; idx < array_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; | ||||||
|  |  | ||||||
| 		append_fmt( & attribute_entries, "Tok_Attribute_%s,\n", attribute_str ); | 		string_append_fmt( & attribute_entries, "Tok_Attribute_%s,\n", attribute_str ); | ||||||
| 		append_fmt( & to_str_attributes, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | 		string_append_fmt( & to_str_attributes, "{ sizeof(\"%s\"), \"%s\" },\n", entry_to_str, entry_to_str); | ||||||
| 		append_fmt( & attribute_define_entries, "Entry( Tok_Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | 		string_append_fmt( & attribute_define_entries, "Entry( Tok_Attribute_%s, \"%s\" )", attribute_str, entry_to_str ); | ||||||
|  |  | ||||||
| 		if ( idx < num(attribute_strs) - 1 ) | 		if ( idx < array_num(attribute_strs) - 1 ) | ||||||
| 			append( & attribute_define_entries, " \\\n"); | 			string_append_strc( & attribute_define_entries, txt(" \\\n")); | ||||||
| 		else | 		else | ||||||
| 			append( & attribute_define_entries, "\n"); | 			string_append_strc( & attribute_define_entries, txt("\n")); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | #pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | ||||||
| #undef GEN_DEFINE_ATTRIBUTE_TOKENS | #undef GEN_DEFINE_ATTRIBUTE_TOKENS | ||||||
| 	CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), to_strc(attribute_define_entries)  ); | 	CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), string_to_strc(attribute_define_entries)  ); | ||||||
| #pragma pop_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | #pragma pop_macro("GEN_DEFINE_ATTRIBUTE_TOKENS") | ||||||
|  |  | ||||||
| 	// We cannot parse this enum, it has Attribute names as enums | 	// We cannot parse this enum, it has Attribute names as enums | ||||||
| 	CodeEnum enum_code = parse_enum(token_fmt("entries", to_str(enum_entries), "attribute_toks", to_str(attribute_entries), stringize( | 	CodeEnum enum_code = parse_enum(token_fmt("entries", string_to_strc(enum_entries), "attribute_toks", string_to_strc(attribute_entries), stringize( | ||||||
| 		enum TokType_Def : u32 | 		enum TokType_Def : u32 | ||||||
| 		{ | 		{ | ||||||
| 			<entries> | 			<entries> | ||||||
| @@ -290,7 +292,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| #undef local_persist | #undef local_persist | ||||||
| #undef do_once_start | #undef do_once_start | ||||||
| #undef do_once_end | #undef do_once_end | ||||||
| 	CodeFn to_str = parse_function(token_fmt("entries", to_strc(to_str_entries), "attribute_toks", to_strc(to_str_attributes), stringize( | 	CodeFn to_str = parse_function(token_fmt("entries", string_to_strc(to_str_entries), "attribute_toks", string_to_strc(to_str_attributes), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		StrC to_str( TokType type ) | 		StrC to_str( TokType type ) | ||||||
| 		{ | 		{ | ||||||
| @@ -304,7 +306,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path ) | |||||||
| 		} | 		} | ||||||
| 	))); | 	))); | ||||||
|  |  | ||||||
| 	CodeFn to_type = parse_function( token_fmt( "entries", to_strc(to_str_entries), stringize( | 	CodeFn to_type = parse_function( token_fmt( "entries", string_to_strc(to_str_entries), stringize( | ||||||
| 		inline | 		inline | ||||||
| 		TokType to_toktype( StrC str ) | 		TokType to_toktype( StrC str ) | ||||||
| 		{ | 		{ | ||||||
|   | |||||||
| @@ -231,10 +231,12 @@ if ( $c_library ) | |||||||
| 	$executable = join-path $path_build     "gen_c_library_test.exe" | 	$executable = join-path $path_build     "gen_c_library_test.exe" | ||||||
|  |  | ||||||
| 	if ($vendor -eq "clang") { | 	if ($vendor -eq "clang") { | ||||||
| 		$compiler_args += "-x" | 		$compiler_args += '-x' | ||||||
| 		$compiler_args += "c" | 		$compiler_args += 'c' | ||||||
|  | 		$compiler_args += '-std=c11' | ||||||
| 	} elseif ($vendor -eq "msvc") { | 	} elseif ($vendor -eq "msvc") { | ||||||
| 		$compiler_args += "/TC" | 		$compiler_args += "/TC"       # Compile as C | ||||||
|  | 		$compiler_args += "/Zc:__cplusplus" # Fix __cplusplus macro | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | 	build-simple $path_build $includes $compiler_args $linker_args $unit $executable | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user