2023-09-26 22:16:41 -07:00
|
|
|
#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 );
|
|
|
|
|
2023-09-28 15:38:06 -07:00
|
|
|
#define str_ascii( str ) { sizeof( str ) - 1, ccast( char*, str) }
|
2023-09-26 22:16:41 -07:00
|
|
|
|
|
|
|
// Length tracked raw strings.
|
|
|
|
struct Str
|
|
|
|
{
|
|
|
|
u32 Len;
|
|
|
|
char* Data;
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2023-09-29 12:58:18 -07:00
|
|
|
void concat( u32 dest_size, Str* dest, Str const str_a, Str const str_b )
|
2023-09-26 22:16:41 -07:00
|
|
|
{
|
|
|
|
str_concat( dest_size, dest->Data
|
|
|
|
, str_a.Len, str_a.Data
|
|
|
|
, str_b.Len, str_b.Data );
|
|
|
|
dest->Len = str_a.Len + str_b.Len;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator char*() const {
|
|
|
|
return Data;
|
|
|
|
}
|
|
|
|
char& operator []( u32 idx ) {
|
|
|
|
return Data[idx];
|
|
|
|
}
|
|
|
|
char const& operator []( u32 idx ) const {
|
|
|
|
return Data[idx];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Fixed length raw strings.
|
2023-09-29 12:58:18 -07:00
|
|
|
template< u32 capacity >
|
2023-09-26 22:16:41 -07:00
|
|
|
struct StrFixed
|
|
|
|
{
|
|
|
|
constexpr static u32 Capacity = capacity;
|
|
|
|
|
|
|
|
u32 Len;
|
|
|
|
char Data[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, Data
|
|
|
|
, str_a.Len, str_a.Data
|
|
|
|
, str_b.Len, str_b.Data );
|
|
|
|
Len = str_a.Len + str_b.Len;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator char*() { return Data;}
|
|
|
|
operator char const*() { return Data; }
|
|
|
|
operator Str() { return { Len, Data }; }
|
|
|
|
operator Str const() const { return { Len, Data }; }
|
|
|
|
char& operator []( u32 idx ) {
|
|
|
|
assert( idx < Capacity );
|
|
|
|
return Data[idx];
|
|
|
|
}
|
|
|
|
char const& operator []( u32 idx ) const {
|
|
|
|
assert( idx < Capacity );
|
|
|
|
return Data[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 )
|
|
|
|
{
|
2023-09-28 15:38:06 -07:00
|
|
|
u32 left = str_b_len;
|
2023-09-26 22:16:41 -07:00
|
|
|
while ( left-- )
|
|
|
|
{
|
2023-09-28 15:38:06 -07:00
|
|
|
*dest_a = *str_a;
|
2023-09-26 22:16:41 -07:00
|
|
|
*dest_b = *str_b;
|
|
|
|
|
|
|
|
++ dest_a;
|
|
|
|
++ dest_b;
|
|
|
|
++ str_a;
|
|
|
|
++ str_b;
|
|
|
|
}
|
|
|
|
|
|
|
|
left = str_a_len - str_b_len;
|
|
|
|
while ( left-- )
|
|
|
|
{
|
2023-09-28 15:38:06 -07:00
|
|
|
*dest_a = *str_a;
|
|
|
|
++ dest_a;
|
|
|
|
++ str_a;
|
2023-09-26 22:16:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( str_a_len < str_b_len )
|
|
|
|
{
|
2023-09-28 15:38:06 -07:00
|
|
|
u32 left = str_a_len;
|
2023-09-26 22:16:41 -07:00
|
|
|
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-- )
|
|
|
|
{
|
2023-09-28 15:38:06 -07:00
|
|
|
*dest_b = *str_b;
|
|
|
|
++ dest_b;
|
|
|
|
++ str_b;
|
2023-09-26 22:16:41 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2023-09-29 12:58:18 -07:00
|
|
|
|
|
|
|
using StrPath = StrFixed< S16_MAX >;
|