summaryrefslogtreecommitdiff
path: root/src/util/string.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/string.h')
-rw-r--r--src/util/string.h209
1 files changed, 193 insertions, 16 deletions
diff --git a/src/util/string.h b/src/util/string.h
index 47da1a0..0781fca 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -1,7 +1,9 @@
#pragma once
+#include <cstdio>
+#include <stdarg.h>
#include <string.h>
-#include "typedef.h"
+#include "allocator.h"
constexpr U32 strlen_ct( const char* str ) {
U32 len = 0;
@@ -10,40 +12,215 @@ constexpr U32 strlen_ct( const char* str ) {
}
template <U32 N>
-struct STR {
+struct ARRSTR {
char data[N]{ 0 };
enum {
size = N
};
- STR() {
+ ARRSTR() {
memset( data, 0, N );
}
- STR( const char* str ) {
+ ARRSTR( const char* str ) {
memcpy( data, str, strlen_ct( str ) );
}
- STR( const STR<N>& str ) {
+ ARRSTR( const ARRSTR<N>& str ) {
memcpy( data, str.data, N );
}
template <U32 other>
- auto operator+( const STR<other>& rhs ) {
- constexpr U32 l1 = strlen_ct( data );
- constexpr U32 l2 = strlen_ct( rhs.data );
+ auto operator+( const ARRSTR<other>& rhs ) {
+ const U32 l1 = strlen_ct( data );
+ const U32 l2 = strlen_ct( rhs.data );
- constexpr U32 high = N > other ? N : other;
- constexpr U32 max = (l1 + l2 > high) ? l1 + l2 + 1 : high;
+ if( l1 + l2 >= N ) {
+ dlog( "STR::operator+(): string overflow" );
+ abort();
+ return *this;
+ }
- STR<max> result;
- memcpy( result.data, data, l1 );
- memcpy( result.data + l1, rhs.data, l2 );
- result.data[l1 + l2] = '\0';
- return result;
+ memcpy( data + l1, rhs.data, l2 );
+ data[l1 + l2] = '\0';
+ return *this;
}
template <U32 other>
- auto concat( const STR<other>& str ) {
+ auto concat( const ARRSTR<other>& str ) {
return *this + str;
}
operator char*() { return data; }
};
+
+template <typename CT>
+struct __str : public LIST<CT> {
+ __str() : LIST<CT>() {}
+ __str( const CT* fmt, ... ) : LIST<CT>() {
+ va_list args;
+ va_start( args, fmt );
+ va_list args2;
+ va_copy( args2, args );
+ U32 c = vsnprintf( 0, 0, fmt, args );
+ va_end( args );
+ this->data = 0;
+ this->reserve( c * 2 );
+ vsnprintf( this->data, c + 1, fmt, args2 );
+ this->data[c] = 0;
+ this->size = c;
+ va_end( args2 );
+ }
+
+ __str( const __str<CT>& rhs ) : LIST<CT>( rhs ) {
+ this->data[this->size] = 0;
+ }
+
+ __str<CT>& operator=( const __str<CT>& other ) {
+ if( this == &other )
+ return *this;
+
+ if( this->data && this->data != other.data )
+ free( this->data );
+
+ this->data = 0;
+
+ if( !other.capacity || !other.size ) {
+ this->capacity = 1;
+ this->size = 0;
+ this->data = (CT*)malloc( sizeof(CT) );
+ memset( this->data, 0, sizeof(CT) );
+ return *this;
+ }
+
+ this->data = (CT*)malloc( other.capacity * sizeof( CT ) );
+ memcpy( this->data, other.data, (other.size + 1) * sizeof( CT ) );
+ this->size = other.size;
+ this->capacity = other.capacity;
+
+ return *this;
+ }
+
+ const bool operator==( const __str<CT>& rhs ) { return this->equals( rhs ); }
+ const bool operator!=( const __str<CT>& rhs ) { return !(*this == rhs); }
+ const bool operator==( const CT* rhs ) { return this->equals( rhs ); }
+ const bool operator!=( const CT* rhs ) { return !(*this == rhs); }
+ __str<CT> operator+( const __str<CT>& rhs ) { __str<CT> ret = *this; return ret.append( rhs ); }
+ __str<CT> operator+( const CT* rhs ) { __str<CT> ret = *this; return ret.append( rhs ); }
+ __str<CT> operator+( const CT rhs ) { __str<CT> ret = *this; ret.push( rhs ); return ret; }
+ __str<CT>& operator+=( const __str<CT>& rhs ) { return this->append( rhs ); }
+ __str<CT>& operator+=( const CT* rhs ) { return this->append( rhs ); }
+ __str<CT>& operator+=( const CT rhs ) { this->push( rhs ); return this; }
+
+ operator CT*() { return this->data; }
+
+ CT operator[]( U32 i ) {
+ return this->data[i];
+ }
+
+ U8 equals( const __str<CT>& rhs ) {
+ if( rhs.size != this->size )
+ return 0;
+
+ for( U32 i = 0; i < this->size; ++i ) {
+ if( this->data[i] != rhs.data[i] )
+ return 0;
+ }
+
+ return 1;
+ }
+
+ U8 equals( const CT* rhs ) {
+ for( U32 i = 0; i < this->size; ++i ) {
+ if( !rhs[i] || this->data[i] != rhs[i] )
+ return 0;
+ }
+
+ return 1;
+ }
+
+ __str<CT>& fmt( const char* fmt, ... ) {
+ va_list args;
+ va_start( args, fmt );
+ va_list args2;
+ va_copy( args2, args );
+ U32 c = this->size + vsnprintf( 0, 0, fmt, args );
+ va_end( args );
+ if( c > this->capacity )
+ this->reserve( c * 2 );
+ vsnprintf( this->data + this->size, c + 1, fmt, args2 );
+ this->data[c] = 0;
+ this->size = c;
+ va_end( args2 );
+ }
+
+ __str<CT>& append( const CT* str ) {
+ U32 len;
+ for( len = 0; !!str[len]; ++len );
+ if( this->size + len > this->capacity )
+ this->reserve( this->size * 2 );
+
+ memcpy( this->data + this->size, str, len * sizeof(CT) );
+ this->size += len;
+ this->data[this->size] = 0;
+ return *this;
+ }
+
+ __str<CT>& append( const __str<CT>& str ) {
+ U32 len = str.len;
+ if( this->size + len + 1 >= this->capacity )
+ this->reserve( this->size + len + 1 );
+
+ memcpy( this->data + this->size, str, len * sizeof(CT) );
+ this->size += len;
+ this->data[this->size] = 0;
+ return *this;
+ }
+
+ CT* push( const CT& item ) {
+ if( this->capacity <= this->size + 1 )
+ this->grow();
+ this->data[this->size++] = item;
+ this->data[this->size] = 0;
+
+ return &this->data[this->size - 1];
+ }
+
+ U32 idx_of( const CT* str ) {
+ return idx_of( str, 0 );
+ }
+
+ U32 idx_of( const CT* str, U32 offset ) {
+ for( U32 i = offset; i < this->size; ++i ) {
+ U8 found = 1;
+ for( U32 i2 = 0; !!str[i2] && i + i2 < this->size; ++i2 ) {
+ if( this->data[i + i2] != str[i2] ) {
+ found = 0;
+ break;
+ }
+ }
+
+ if( found )
+ return i;
+ }
+ }
+
+ CT* find( const CT* str ) {
+ for( U32 i = 0; i < this->size; ++i ) {
+ U8 found = 1;
+ for( U32 i2 = 0; !!str[i2] && i + i2 < this->size; ++i2 ) {
+ if( this->data[i + i2] != str[i2] ) {
+ found = 0;
+ break;
+ }
+ }
+ if( found )
+ return this->data + i;
+ }
+ return 0;
+ }
+
+ LIST_ITERATOR<CT> end() {
+ return LIST_ITERATOR<CT>( this->data + this->size );
+ }
+};
+
+using STR = __str<char>;
+using WSTR = __str<wchar_t>;