mirror of
				https://github.com/Ed94/HandmadeHero.git
				synced 2025-10-30 14:30:54 -07:00 
			
		
		
		
	I'm splitting this implementation into parts since so much already happened... I fully updated the code the the latest convention I want to use for the project. Engine & Game replay should work.
		
			
				
	
	
		
			192 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "macros.hpp"
 | |
| #include "types.hpp"
 | |
| 
 | |
| void str_append( u32 dest_len, char* dest, u32 src_len, char const* src );
 | |
| void str_concat( u32 dest_size, char* dest
 | |
| 	, u32 str_a_len, char const* str_a
 | |
| 	, u32 str_b_len, char const* str_b );
 | |
| u32 str_length( char const* str );
 | |
| 
 | |
| #define str_ascii( str ) { sizeof( str ) - 1, ccast( char*, str) }
 | |
| 
 | |
| // Length tracked raw strings.
 | |
| struct Str
 | |
| {
 | |
| 	u32   len;
 | |
| 	char* ptr;
 | |
| 
 | |
| 	void append( u32 src_len, char const* src ) {
 | |
| 		str_append( len, ptr, src_len, src );
 | |
| 	}
 | |
| 	void append( Str const src ) {
 | |
| 		str_append( len, ptr, src.len, src.ptr );
 | |
| 	}
 | |
| 
 | |
| 	void concat( u32 dest_size, Str* dest, Str const str_a, Str const str_b )
 | |
| 	{
 | |
| 		str_concat( dest_size, dest->ptr
 | |
| 			, str_a.len, str_a.ptr
 | |
| 			, str_b.len, str_b.ptr );
 | |
| 		dest->len = str_a.len + str_b.len;
 | |
| 	}
 | |
| 
 | |
| 	operator char*() const {
 | |
| 		return ptr;
 | |
| 	}
 | |
| 	char& operator []( u32 idx ) {
 | |
| 		return ptr[idx];
 | |
| 	}
 | |
| 	char const& operator []( u32 idx ) const {
 | |
| 		return ptr[idx];
 | |
| 	}
 | |
| };
 | |
| 
 | |
| // Fixed length raw strings.
 | |
| template< u32 capacity >
 | |
| struct StrFixed
 | |
| {
 | |
| 	constexpr static u32 Capacity = capacity;
 | |
| 
 | |
| 	u32  len;
 | |
| 	char ptr[capacity];
 | |
| 
 | |
| 	void append( u32 src_len, char const* src ) {
 | |
| 		str_append( len, data, src_len, src );
 | |
| 	}
 | |
| 	void append( Str const src ) {
 | |
| 		str_append( len, data, src.Len, src.data );
 | |
| 	}
 | |
| 
 | |
| 	void concat( Str const str_a, Str const str_b )
 | |
| 	{
 | |
| 		str_concat( Capacity, ptr
 | |
| 			, str_a.len, str_a.ptr
 | |
| 			, str_b.len, str_b.ptr );
 | |
| 		len = str_a.len + str_b.len;
 | |
| 	}
 | |
| 
 | |
| 	operator char*()           { return ptr;}
 | |
| 	operator char const*()     { return ptr; }
 | |
| 	operator Str()             { return { len, ptr }; }
 | |
| 	operator Str const() const { return { len, ptr }; }
 | |
| 	char& operator []( u32 idx ) {
 | |
| 		assert( idx < Capacity );
 | |
| 		return ptr[idx];
 | |
| 	}
 | |
| 	char const& operator []( u32 idx ) const {
 | |
| 		assert( idx < Capacity );
 | |
| 		return ptr[idx];
 | |
| 	}
 | |
| };
 | |
| 
 | |
| inline
 | |
| void str_append( u32 dest_len, char* dest, u32 src_len, char const* src )
 | |
| {
 | |
| 	assert( dest_len > 0 );
 | |
| 	assert( dest != nullptr );
 | |
| 	assert( src_len > 0 );
 | |
| 	assert( src != nullptr );
 | |
| 	assert( dest_len >= src_len );
 | |
| 
 | |
| 	char* dest_end = dest + dest_len;
 | |
| 	assert( *dest_end == '\0' );
 | |
| 
 | |
| 	u32 left = src_len;
 | |
| 	while ( left-- )
 | |
| 	{
 | |
| 		*dest = *src;
 | |
| 		++ dest;
 | |
| 		++ src;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void str_concat( u32 dest_size, char* dest
 | |
| 	, u32 str_a_len, char const* str_a
 | |
| 	, u32 str_b_len, char const* str_b )
 | |
| {
 | |
| 	assert( dest_size > 0 );
 | |
| 	assert( dest != nullptr );
 | |
| 	assert( *dest == '\0' );
 | |
| 	assert( str_a_len > 0 );
 | |
| 	assert( str_a != nullptr );
 | |
| 	assert( str_b_len > 0 );
 | |
| 	assert( str_b != nullptr );
 | |
| 	assert( str_a_len + str_b_len < dest_size );
 | |
| 
 | |
| 	char* dest_a = dest;
 | |
| 	char* dest_b = dest + str_a_len;
 | |
| 	if ( str_a_len > str_b_len )
 | |
| 	{
 | |
| 		u32 left = str_b_len;
 | |
| 		while ( left-- )
 | |
| 		{
 | |
| 			*dest_a = *str_a;
 | |
| 			*dest_b = *str_b;
 | |
| 
 | |
| 			++ dest_a;
 | |
| 			++ dest_b;
 | |
| 			++ str_a;
 | |
| 			++ str_b;
 | |
| 		}
 | |
| 
 | |
| 		left = str_a_len - str_b_len;
 | |
| 		while ( left-- )
 | |
| 		{
 | |
| 			*dest_a = *str_a;
 | |
| 			++ dest_a;
 | |
| 			++ str_a;
 | |
| 		}
 | |
| 	}
 | |
| 	else if ( str_a_len < str_b_len )
 | |
| 	{
 | |
| 		u32 left = str_a_len;
 | |
| 		while ( left-- )
 | |
| 		{
 | |
| 			*dest_a = *str_a;
 | |
| 			*dest_b = *str_b;
 | |
| 			++ dest_a;
 | |
| 			++ dest_b;
 | |
| 			++ str_a;
 | |
| 			++ str_b;
 | |
| 		}
 | |
| 
 | |
| 		left = str_b_len - str_a_len;
 | |
| 		while ( left-- )
 | |
| 		{
 | |
| 			*dest_b = *str_b;
 | |
| 			++ dest_b;
 | |
| 			++ str_b;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		u32 left = str_a_len;
 | |
| 		while ( left-- )
 | |
| 		{
 | |
| 			*dest_a = *str_a;
 | |
| 			*dest_b = *str_b;
 | |
| 			++ dest_a;
 | |
| 			++ str_a;
 | |
| 			++ dest_b;
 | |
| 			++ str_b;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| inline
 | |
| u32 str_length( char const* str )
 | |
| {
 | |
| 	assert( str != nullptr );
 | |
| 
 | |
| 	u32 result = 0;
 | |
| 	while ( *str != '\0' )
 | |
| 	{
 | |
| 		++ result;
 | |
| 		++ str;
 | |
| 	}
 | |
| 
 | |
| 	return result;
 | |
| }
 | |
| 
 | |
| using StrPath = StrFixed< S16_MAX >;
 |