From 545783c1d937b2bed42e0555c9343fa00b8b7a22 Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 5 Dec 2023 15:19:43 +0000 Subject: [PATCH] add support for dynamic vg_str's (tooling) --- vg_platform.h | 119 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/vg_platform.h b/vg_platform.h index ef3daed..295f03f 100644 --- a/vg_platform.h +++ b/vg_platform.h @@ -44,6 +44,7 @@ struct vg_achievement #include #include #include +#include enum strncpy_behaviour{ k_strncpy_always_add_null = 0, @@ -75,47 +76,121 @@ static u32 vg_strncpy( const char *src, char *dst, u32 len, } typedef struct vg_str vg_str; +typedef struct vg_str_dynamic vg_str_dynamic; + struct vg_str{ char *buffer; - i32 i, len; + i32 i, /* -1: error condition. otherwise, current cursor position */ + len; /* -1: dynamically allocated. otherwise, buffer length */ +}; + +struct vg_str_dynamic { + i32 len; }; +/* + * Returns the current storage size of the string + */ +static i32 vg_str_storage( vg_str *str ){ + if( str->len == -1 ){ + if( str->buffer ){ + vg_str_dynamic *arr = (vg_str_dynamic *)str->buffer; + return (arr-1)->len; + } + else return 0; + } + else return str->len; +} + +/* + * Reset string. If len is -1 (dynamically allocated), buffer must be either + * NULL or be acquired from malloc or realloc + */ static void vg_strnull( vg_str *str, char *buffer, i32 len ){ str->buffer = buffer; - str->buffer[0] = '\0'; + if( buffer ) + str->buffer[0] = '\0'; + str->i = 0; str->len = len; assert(len); } -static void vg_strcat( vg_str *str, const char *append ){ - if( !append ) return; - if( str->i == -1 ) return; +static void vg_strfree( vg_str *str ){ + if( str->len == -1 ){ + if( str->buffer ){ + vg_str_dynamic *arr = (vg_str_dynamic *)str->buffer; + free( arr-1 ); + + str->buffer = NULL; + str->i = 0; + } + } +} - for( u32 i=0; str->i < str->len; str->i ++, i ++ ){ - str->buffer[ str->i ] = append[ i ]; +/* + * Double the size of the dynamically allocated string. If unallocated, alloc of + * 16 bytes minimum. + */ +static i32 vg_str_dynamic_grow( vg_str *str ){ + if( str->buffer ){ + vg_str_dynamic *hdr = ((vg_str_dynamic *)str->buffer) - 1; + i32 total = (hdr->len + sizeof(vg_str_dynamic)) * 2; + hdr = realloc( hdr, total ); + hdr->len = total - sizeof(vg_str_dynamic); + str->buffer = (char *)(hdr+1); + return hdr->len; + } + else { + vg_str_dynamic *hdr = malloc(16); + hdr->len = 16-sizeof(vg_str_dynamic); + str->buffer = (char *)(hdr+1); + str->buffer[0] = '\0'; + return hdr->len; + } +} - if( append[ i ] == '\0' ) +/* + * Append null terminated string to vg_str + */ +static void vg_strcat( vg_str *str, const char *append ){ + if( !append || (str->i == -1) ) return; + + i32 max = vg_str_storage( str ), + i = 0; + +append: + if( str->i == max ){ + if( str->len == -1 ) + max = vg_str_dynamic_grow( str ); + else{ + str->i = -1; + str->buffer[ max-1 ] = '\0'; return; + } } - /* overflow */ - str->buffer[ str->len-1 ] = '\0'; - str->i = -1; + char c = append[ i ++ ]; + str->buffer[ str->i ] = c; + + if( c == '\0' ) + return; + + str->i ++; + goto append; } +/* + * Append character to vg_str + */ static void vg_strcatch( vg_str *str, char c ){ - if( str->i == -1 ) return; - if( (str->i + 2) > str->len ){ - str->i = -1; - return; - } - str->buffer[ str->i ++ ] = c; - str->buffer[ str->i ] = '\0'; + vg_strcat( str, (char[]){ c, '\0' } ); } -/* FIXME: Negative numbers */ +/* + * FIXME: Negative numbers + */ static void vg_strcati32( vg_str *str, i32 value ){ if( value ){ char temp[32]; @@ -154,11 +229,17 @@ static void vg_strcati32r( vg_str *str, i32 value, i32 n, char alt ){ vg_strcat( str, temp ); } +/* + * Returns 1 if string did not overflow while building + */ static int vg_strgood( vg_str *str ){ if( str->i == -1 ) return 0; else return 1; } +/* + * Returns pointer to first instance of character + */ static char *vg_strch( vg_str *str, char c ){ char *ptr = NULL; for( i32 i=0; ii; i++ ){ -- 2.25.1