2023-08-28 20:46:50 -07:00
|
|
|
#ifdef GEN_INTELLISENSE_DIRECTIVES
|
|
|
|
# pragma once
|
|
|
|
# include "memory.hpp"
|
|
|
|
#endif
|
2023-08-21 17:30:13 -07:00
|
|
|
|
2023-07-25 20:00:57 -07:00
|
|
|
#pragma region String Ops
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
const char* char_first_occurence( const char* str, char c );
|
2023-07-24 15:19:37 -07:00
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
b32 char_is_alpha( char c );
|
|
|
|
b32 char_is_alphanumeric( char c );
|
|
|
|
b32 char_is_digit( char c );
|
|
|
|
b32 char_is_hex_digit( char c );
|
|
|
|
b32 char_is_space( char c );
|
|
|
|
char char_to_lower( char c );
|
|
|
|
char char_to_upper( char c );
|
2023-07-24 15:19:37 -07:00
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
s32 digit_to_int( char c );
|
|
|
|
s32 hex_digit_to_int( char c );
|
2023-07-24 15:19:37 -07:00
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
s32 str_compare( const char* s1, const char* s2 );
|
2024-12-04 08:01:53 -08:00
|
|
|
s32 str_compare_len( const char* s1, const char* s2, ssize len );
|
2024-10-27 15:58:37 -07:00
|
|
|
char* str_copy( char* dest, const char* source, ssize len );
|
|
|
|
ssize str_copy_nulpad( char* dest, const char* source, ssize len );
|
|
|
|
ssize str_len( const char* str );
|
2024-12-04 08:01:53 -08:00
|
|
|
ssize str_len_capped( const char* str, ssize max_len );
|
2024-10-27 15:58:37 -07:00
|
|
|
char* str_reverse( char* str ); // NOTE: ASCII only
|
|
|
|
char const* str_skip( char const* str, char c );
|
|
|
|
char const* str_skip_any( char const* str, char const* char_list );
|
|
|
|
char const* str_trim( char const* str, b32 catch_newline );
|
2023-07-24 15:19:37 -07:00
|
|
|
|
|
|
|
// NOTE: ASCII only
|
2024-10-27 15:58:37 -07:00
|
|
|
void str_to_lower( char* str );
|
|
|
|
void str_to_upper( char* str );
|
2023-07-24 15:19:37 -07:00
|
|
|
|
|
|
|
s64 str_to_i64( const char* str, char** end_ptr, s32 base );
|
|
|
|
void i64_to_str( s64 value, char* string, s32 base );
|
|
|
|
void u64_to_str( u64 value, char* string, s32 base );
|
|
|
|
f64 str_to_f64( const char* str, char** end_ptr );
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
const char* char_first_occurence( const char* s, char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
char ch = c;
|
|
|
|
for ( ; *s != ch; s++ )
|
|
|
|
{
|
|
|
|
if ( *s == '\0' )
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
b32 char_is_alpha( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
b32 char_is_alphanumeric( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
return char_is_alpha( c ) || char_is_digit( c );
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
b32 char_is_digit( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( c >= '0' && c <= '9' )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
b32 char_is_hex_digit( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( char_is_digit( c ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
b32 char_is_space( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' )
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char char_to_lower( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( c >= 'A' && c <= 'Z' )
|
|
|
|
return 'a' + ( c - 'A' );
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline char char_to_upper( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( c >= 'a' && c <= 'z' )
|
|
|
|
return 'A' + ( c - 'a' );
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
s32 digit_to_int( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
return char_is_digit( c ) ? c - '0' : c - 'W';
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
s32 hex_digit_to_int( char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( char_is_digit( c ) )
|
|
|
|
return digit_to_int( c );
|
|
|
|
else if ( is_between( c, 'a', 'f' ) )
|
|
|
|
return c - 'a' + 10;
|
|
|
|
else if ( is_between( c, 'A', 'F' ) )
|
|
|
|
return c - 'A' + 10;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
s32 str_compare( const char* s1, const char* s2 )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
while ( *s1 && ( *s1 == *s2 ) )
|
|
|
|
{
|
|
|
|
s1++, s2++;
|
|
|
|
}
|
|
|
|
return *( u8* )s1 - *( u8* )s2;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
2024-12-04 08:01:53 -08:00
|
|
|
s32 str_compare_len( const char* s1, const char* s2, ssize len )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
for ( ; len > 0; s1++, s2++, len-- )
|
|
|
|
{
|
|
|
|
if ( *s1 != *s2 )
|
|
|
|
return ( ( s1 < s2 ) ? -1 : +1 );
|
|
|
|
else if ( *s1 == '\0' )
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char* str_copy( char* dest, const char* source, ssize len )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
GEN_ASSERT_NOT_NULL( dest );
|
|
|
|
if ( source )
|
|
|
|
{
|
|
|
|
char* str = dest;
|
|
|
|
while ( len > 0 && *source )
|
|
|
|
{
|
|
|
|
*str++ = *source++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
while ( len > 0 )
|
|
|
|
{
|
|
|
|
*str++ = '\0';
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
ssize str_copy_nulpad( char* dest, const char* source, ssize len )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
2024-10-27 15:58:37 -07:00
|
|
|
ssize result = 0;
|
2023-07-24 15:19:37 -07:00
|
|
|
GEN_ASSERT_NOT_NULL( dest );
|
|
|
|
if ( source )
|
|
|
|
{
|
|
|
|
const char* source_start = source;
|
|
|
|
char* str = dest;
|
|
|
|
while ( len > 0 && *source )
|
|
|
|
{
|
|
|
|
*str++ = *source++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
while ( len > 0 )
|
|
|
|
{
|
|
|
|
*str++ = '\0';
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = source - source_start;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
ssize str_len( const char* str )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( str == NULL )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
const char* p = str;
|
|
|
|
while ( *str )
|
|
|
|
str++;
|
|
|
|
return str - p;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
2024-12-04 08:01:53 -08:00
|
|
|
ssize str_len_capped( const char* str, ssize max_len )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
2024-10-27 15:58:37 -07:00
|
|
|
const char* end = rcast(const char*, mem_find( str, 0, max_len ));
|
2023-07-24 15:19:37 -07:00
|
|
|
if ( end )
|
|
|
|
return end - str;
|
|
|
|
return max_len;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char* str_reverse( char* str )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
2024-10-27 15:58:37 -07:00
|
|
|
ssize len = str_len( str );
|
2023-07-24 15:19:37 -07:00
|
|
|
char* a = str + 0;
|
|
|
|
char* b = str + len - 1;
|
|
|
|
len /= 2;
|
|
|
|
while ( len-- )
|
|
|
|
{
|
|
|
|
swap( *a, *b );
|
|
|
|
a++, b--;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char const* str_skip( char const* str, char c )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
while ( *str && *str != c )
|
|
|
|
{
|
|
|
|
++str;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char const* str_skip_any( char const* str, char const* char_list )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
2024-12-04 08:01:53 -08:00
|
|
|
char const* closest_ptr = rcast( char const*, pointer_add_const( rcast(mem_ptr_const, str), str_len( str ) ));
|
2024-10-27 15:58:37 -07:00
|
|
|
ssize char_list_count = str_len( char_list );
|
|
|
|
for ( ssize i = 0; i < char_list_count; i++ )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
char const* p = str_skip( str, char_list[ i ] );
|
|
|
|
closest_ptr = min( closest_ptr, p );
|
|
|
|
}
|
|
|
|
return closest_ptr;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
char const* str_trim( char const* str, b32 catch_newline )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
while ( *str && char_is_space( *str ) && ( ! catch_newline || ( catch_newline && *str != '\n' ) ) )
|
|
|
|
{
|
|
|
|
++str;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
void str_to_lower( char* str )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( ! str )
|
|
|
|
return;
|
|
|
|
while ( *str )
|
|
|
|
{
|
|
|
|
*str = char_to_lower( *str );
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-27 15:58:37 -07:00
|
|
|
inline
|
|
|
|
void str_to_upper( char* str )
|
2023-07-24 15:19:37 -07:00
|
|
|
{
|
|
|
|
if ( ! str )
|
|
|
|
return;
|
|
|
|
while ( *str )
|
|
|
|
{
|
|
|
|
*str = char_to_upper( *str );
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
2023-07-25 20:00:57 -07:00
|
|
|
|
|
|
|
#pragma endregion String Ops
|